commit 1c32db68dae445904f562ad7183d829ba56a0451
parent 5285fadded70581254465e2ed7e865fe0fc2e7a4
Author: Simon Kornblith <simon@simonster.com>
Date: Sat, 7 Mar 2015 12:18:27 -0500
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...
Diffstat:
12 files changed, 292 insertions(+), 0 deletions(-)
diff --git a/.gitmodules b/.gitmodules
@@ -7,3 +7,9 @@
[submodule "styles"]
path = styles
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
diff --git a/.travis.yml b/.travis.yml
@@ -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
diff --git a/test/chrome.manifest b/test/chrome.manifest
@@ -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
diff --git a/test/components/zotero-unit.js b/test/components/zotero-unit.js
@@ -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]);
diff --git a/test/content/runtests.html b/test/content/runtests.html
@@ -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>
+\ No newline at end of file
diff --git a/test/content/runtests.js b/test/content/runtests.js
@@ -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();
+};
+\ No newline at end of file
diff --git a/test/install.rdf b/test/install.rdf
@@ -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>
diff --git a/test/resource/chai b/test/resource/chai
@@ -0,0 +1 @@
+Subproject commit d7cafca0232756f767275bb00e66930a7823b027
diff --git a/test/resource/mocha b/test/resource/mocha
@@ -0,0 +1 @@
+Subproject commit 65fc80ecd96ca2159a792aff089bbc273d4bd86d
diff --git a/test/runtests.sh b/test/runtests.sh
@@ -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
+\ No newline at end of file
diff --git a/test/tests/index.js b/test/tests/index.js
@@ -0,0 +1,3 @@
+var TESTS = {
+ "utilities":["utilities.js"]
+};
diff --git a/test/tests/utilities.js b/test/tests/utilities.js
@@ -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");
+ }
+ }
+ });
+ });
+});