Unit testing infrastructure
Implements the beginnings of unit testing infrastructure using mocha/chai. The unit tests can be run locally using test/runtests.sh, although this will need tweaks to run on Windows. They should also run on commit using Travis-CI. The unit tests themselves live in test/tests. The index.js file specifies separate test sets, which can be run individually by calling test/runtests.sh <testsets>. Right now there is only a single unit test, but hopefully we'll have more soon...
This commit is contained in:
parent
5285fadded
commit
1c32db68da
6
.gitmodules
vendored
6
.gitmodules
vendored
|
@ -7,3 +7,9 @@
|
||||||
[submodule "styles"]
|
[submodule "styles"]
|
||||||
path = styles
|
path = styles
|
||||||
url = git://github.com/zotero/bundled-styles.git
|
url = git://github.com/zotero/bundled-styles.git
|
||||||
|
[submodule "test/resource/chai"]
|
||||||
|
path = test/resource/chai
|
||||||
|
url = https://github.com/chaijs/chai.git
|
||||||
|
[submodule "test/resource/mocha"]
|
||||||
|
path = test/resource/mocha
|
||||||
|
url = https://github.com/mochajs/mocha.git
|
||||||
|
|
16
.travis.yml
Normal file
16
.travis.yml
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
language: cpp
|
||||||
|
compiler:
|
||||||
|
- gcc
|
||||||
|
env:
|
||||||
|
matrix:
|
||||||
|
- FIREFOXVERSION="36.0.1"
|
||||||
|
- FIREFOXVERSION="31.5.0esr"
|
||||||
|
notifications:
|
||||||
|
email: false
|
||||||
|
before_install:
|
||||||
|
- export DISPLAY=:99.0
|
||||||
|
- sh -e /etc/init.d/xvfb start
|
||||||
|
- wget http://ftp.mozilla.org/pub/firefox/releases/${FIREFOXVERSION}/linux-x86_64/en-US/firefox-${FIREFOXVERSION}.tar.bz2
|
||||||
|
- tar -xjf firefox-${FIREFOXVERSION}.tar.bz2
|
||||||
|
script:
|
||||||
|
- test/runtests.sh -x firefox/firefox
|
7
test/chrome.manifest
Normal file
7
test/chrome.manifest
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
content zotero-unit content/
|
||||||
|
resource zotero-unit resource/
|
||||||
|
resource zotero-unit-tests tests/
|
||||||
|
|
||||||
|
component {b8570031-be5e-46e8-9785-38cd50a5d911} components/zotero-unit.js
|
||||||
|
contract @mozilla.org/commandlinehandler/general-startup;1?type=zotero-unit {b8570031-be5e-46e8-9785-38cd50a5d911}
|
||||||
|
category command-line-handler m-zotero-unit @mozilla.org/commandlinehandler/general-startup;1?type=zotero-unit
|
51
test/components/zotero-unit.js
Normal file
51
test/components/zotero-unit.js
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
"use strict";
|
||||||
|
/*
|
||||||
|
***** BEGIN LICENSE BLOCK *****
|
||||||
|
|
||||||
|
Copyright © 2012 Center for History and New Media
|
||||||
|
George Mason University, Fairfax, Virginia, USA
|
||||||
|
http://zotero.org
|
||||||
|
|
||||||
|
This file is part of Zotero.
|
||||||
|
|
||||||
|
Zotero is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Zotero is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
|
||||||
|
function ZoteroUnit() {
|
||||||
|
this.wrappedJSObject = this;
|
||||||
|
}
|
||||||
|
ZoteroUnit.prototype = {
|
||||||
|
/* nsICommandLineHandler */
|
||||||
|
handle:function(cmdLine) {
|
||||||
|
this.tests = cmdLine.handleFlagWithParam("test", false);
|
||||||
|
},
|
||||||
|
|
||||||
|
dump:function(x) {
|
||||||
|
dump(x);
|
||||||
|
},
|
||||||
|
|
||||||
|
contractID: "@mozilla.org/commandlinehandler/general-startup;1?type=zotero-unit",
|
||||||
|
classDescription: "Zotero Unit Command Line Handler",
|
||||||
|
classID: Components.ID("{b8570031-be5e-46e8-9785-38cd50a5d911}"),
|
||||||
|
service: true,
|
||||||
|
_xpcom_categories: [{category:"command-line-handler", entry:"m-zotero-unit"}],
|
||||||
|
QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsICommandLineHandler,
|
||||||
|
Components.interfaces.nsISupports])
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
var NSGetFactory = XPCOMUtils.generateNSGetFactory([ZoteroUnit]);
|
14
test/content/runtests.html
Normal file
14
test/content/runtests.html
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"></meta>
|
||||||
|
<title>Zotero Unit Tests</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script src="jquery.js"></script>
|
||||||
|
<script src="chrome://zotero/content/include.js"></script>
|
||||||
|
<script src="resource://zotero-unit/chai/chai.js"></script>
|
||||||
|
<script src="resource://zotero-unit/mocha/mocha.js"></script>
|
||||||
|
<script src="resource://zotero-unit-tests/index.js"></script>
|
||||||
|
<script src="runtests.js" version="application/javascript;version=1.8"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
88
test/content/runtests.js
Normal file
88
test/content/runtests.js
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
Components.utils.import("resource://gre/modules/FileUtils.jsm");
|
||||||
|
Components.utils.import("resource://gre/modules/osfile.jsm")
|
||||||
|
|
||||||
|
var ZoteroUnit = Components.classes["@mozilla.org/commandlinehandler/general-startup;1?type=zotero-unit"].
|
||||||
|
getService(Components.interfaces.nsISupports).
|
||||||
|
wrappedJSObject;
|
||||||
|
var dump = ZoteroUnit.dump;
|
||||||
|
|
||||||
|
function quit(failed) {
|
||||||
|
// Quit with exit status
|
||||||
|
if(!failed) {
|
||||||
|
OS.File.writeAtomic(FileUtils.getFile("ProfD", ["success"]).path, Uint8Array(0));
|
||||||
|
}
|
||||||
|
Components.classes['@mozilla.org/toolkit/app-startup;1'].
|
||||||
|
getService(Components.interfaces.nsIAppStartup).
|
||||||
|
quit(Components.interfaces.nsIAppStartup.eForceQuit);
|
||||||
|
}
|
||||||
|
|
||||||
|
function Reporter(runner) {
|
||||||
|
var indents = 0, passed = 0, failed = 0;
|
||||||
|
|
||||||
|
function indent() {
|
||||||
|
return Array(indents).join(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
runner.on('start', function(){});
|
||||||
|
|
||||||
|
runner.on('suite', function(suite){
|
||||||
|
++indents;
|
||||||
|
dump(indent()+suite.title+"\n");
|
||||||
|
});
|
||||||
|
|
||||||
|
runner.on('suite end', function(suite){
|
||||||
|
--indents;
|
||||||
|
if (1 == indents) dump("\n");
|
||||||
|
});
|
||||||
|
|
||||||
|
runner.on('pending', function(test){
|
||||||
|
dump(indent()+"pending -"+test.title);
|
||||||
|
});
|
||||||
|
|
||||||
|
runner.on('pass', function(test){
|
||||||
|
passed++;
|
||||||
|
var msg = "\r"+indent()+Mocha.reporters.Base.symbols.ok+" "+test.title;
|
||||||
|
if ('fast' != test.speed) {
|
||||||
|
msg += " ("+Math.round(test.duration)+" ms)";
|
||||||
|
}
|
||||||
|
dump(msg+"\n");
|
||||||
|
});
|
||||||
|
|
||||||
|
runner.on('fail', function(test, err){
|
||||||
|
failed++;
|
||||||
|
dump("\r"+indent()+Mocha.reporters.Base.symbols.err+" "+test.title+"\n");
|
||||||
|
});
|
||||||
|
|
||||||
|
runner.on('end', function() {
|
||||||
|
dump(passed+"/"+(passed+failed)+" tests passed.\n");
|
||||||
|
quit(failed != 0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup Mocha
|
||||||
|
mocha.setup({ui:"bdd", reporter:Reporter});
|
||||||
|
var assert = chai.assert,
|
||||||
|
expect = chai.expect;
|
||||||
|
|
||||||
|
// Set up tests to run
|
||||||
|
if(ZoteroUnit.tests) {
|
||||||
|
document.body.appendChild(document.createTextNode("Running tests..."));
|
||||||
|
var torun = ZoteroUnit.tests == "all" ? Object.keys(TESTS) : ZoteroUnit.tests.split(",");
|
||||||
|
|
||||||
|
for(var key of torun) {
|
||||||
|
if(!TESTS[key]) {
|
||||||
|
dump("Invalid test set "+torun+"\n");
|
||||||
|
quit(true);
|
||||||
|
}
|
||||||
|
for(var test of TESTS[key]) {
|
||||||
|
var el = document.createElement("script");
|
||||||
|
el.type = "application/javascript;version=1.8";
|
||||||
|
el.src = "resource://zotero-unit-tests/"+test;
|
||||||
|
document.body.appendChild(el);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.onload = function() {
|
||||||
|
mocha.run();
|
||||||
|
};
|
26
test/install.rdf
Normal file
26
test/install.rdf
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
|
||||||
|
|
||||||
|
<Description about="urn:mozilla:install-manifest">
|
||||||
|
|
||||||
|
<em:id>zotero-unit@zotero.org</em:id>
|
||||||
|
<em:name>Zotero Unit Tests</em:name>
|
||||||
|
<em:version>1.0</em:version>
|
||||||
|
<em:creator>Center for History and New Media</em:creator>
|
||||||
|
<em:developer>Simon Kornblith</em:developer>
|
||||||
|
<em:homepageURL>http://www.zotero.org</em:homepageURL>
|
||||||
|
<em:iconURL>chrome://zotero/skin/zotero-new-z-48px.png</em:iconURL>
|
||||||
|
<em:type>2</em:type> <!-- type=extension -->
|
||||||
|
|
||||||
|
<!-- Firefox -->
|
||||||
|
<em:targetApplication>
|
||||||
|
<Description>
|
||||||
|
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
|
||||||
|
<em:minVersion>31.0</em:minVersion>
|
||||||
|
<em:maxVersion>38.*</em:maxVersion>
|
||||||
|
</Description>
|
||||||
|
</em:targetApplication>
|
||||||
|
|
||||||
|
</Description>
|
||||||
|
</RDF>
|
1
test/resource/chai
Submodule
1
test/resource/chai
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit d7cafca0232756f767275bb00e66930a7823b027
|
1
test/resource/mocha
Submodule
1
test/resource/mocha
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 65fc80ecd96ca2159a792aff089bbc273d4bd86d
|
56
test/runtests.sh
Executable file
56
test/runtests.sh
Executable file
|
@ -0,0 +1,56 @@
|
||||||
|
#!/bin/bash
|
||||||
|
CWD="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
if [ "`uname`" == "Darwin" ]; then
|
||||||
|
FX_EXECUTABLE="/Applications/Firefox.app/Contents/MacOS/firefox"
|
||||||
|
else
|
||||||
|
FX_EXECUTABLE="firefox"
|
||||||
|
fi
|
||||||
|
|
||||||
|
function usage {
|
||||||
|
cat >&2 <<DONE
|
||||||
|
Usage: $0 [-x FX_EXECUTABLE] [TESTS...]
|
||||||
|
Options
|
||||||
|
-x FX_EXECUTABLE path to Firefox executable (default: $FX_EXECUTABLE)
|
||||||
|
TESTS set of tests to run (default: all)
|
||||||
|
DONE
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
while getopts "x:" opt; do
|
||||||
|
case $opt in
|
||||||
|
x)
|
||||||
|
FX_EXECUTABLE="$OPTARG"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift $((OPTIND-1)); OPTIND=1
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -z $1 ]; then
|
||||||
|
TESTS="all"
|
||||||
|
else
|
||||||
|
ARGS=("${@:1}")
|
||||||
|
function join { local IFS="$1"; shift; echo "$*"; }
|
||||||
|
TESTS="$(join , "${ARGS[@]}")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set up profile directory
|
||||||
|
PROFILE="`mktemp -d 2>/dev/null || mktemp -d -t 'zotero-unit'`"
|
||||||
|
mkdir "$PROFILE/extensions"
|
||||||
|
echo "$CWD" > "$PROFILE/extensions/zotero-unit@zotero.org"
|
||||||
|
echo "`dirname "$CWD"`" > "$PROFILE/extensions/zotero@chnm.gmu.edu"
|
||||||
|
echo 'user_pref("extensions.autoDisableScopes", 0);' > "$PROFILE/prefs.js"
|
||||||
|
|
||||||
|
MOZ_NO_REMOTE=1 NO_EM_RESTART=1 "$FX_EXECUTABLE" -profile "$PROFILE" \
|
||||||
|
-chrome chrome://zotero-unit/content/runtests.html -test "$TESTS"
|
||||||
|
|
||||||
|
# Check for success
|
||||||
|
test -e "$PROFILE/success"
|
||||||
|
STATUS=$?
|
||||||
|
|
||||||
|
# Clean up
|
||||||
|
rm -rf "$PROFILE"
|
||||||
|
exit $STATUS
|
3
test/tests/index.js
Normal file
3
test/tests/index.js
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
var TESTS = {
|
||||||
|
"utilities":["utilities.js"]
|
||||||
|
};
|
20
test/tests/utilities.js
Normal file
20
test/tests/utilities.js
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
describe("Zotero.Utilities", function() {
|
||||||
|
describe("cleanAuthor", function() {
|
||||||
|
it('should parse author names', function() {
|
||||||
|
for(let useComma of [false, true]) {
|
||||||
|
for(let first_expected of [["First", "First"],
|
||||||
|
["First Middle", "First Middle"],
|
||||||
|
["F. R. S.", "F. R. S."],
|
||||||
|
["F.R.S.", "F. R. S."],
|
||||||
|
["F R S", "F. R. S."],
|
||||||
|
["FRS", "F. R. S."]]) {
|
||||||
|
let [first, expected] = first_expected;
|
||||||
|
let str = useComma ? "Last, "+first : first+" Last";
|
||||||
|
let author = Zotero.Utilities.cleanAuthor(str, "author", useComma);
|
||||||
|
assert.equal(author.firstName, expected);
|
||||||
|
assert.equal(author.lastName, "Last");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user