www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | Submodules | README | LICENSE

runtests.js (7829B)


      1 Components.utils.import("resource://gre/modules/Services.jsm");
      2 Services.scriptloader.loadSubScript("resource://zotero/polyfill.js");
      3 Components.utils.import("resource://gre/modules/osfile.jsm");
      4 var EventUtils = Components.utils.import("resource://zotero-unit/EventUtils.jsm");
      5 
      6 var ZoteroUnit = Components.classes["@mozilla.org/commandlinehandler/general-startup;1?type=zotero-unit"].
      7                  getService(Components.interfaces.nsISupports).
      8                  wrappedJSObject;
      9 
     10 var dump = ZoteroUnit.dump;
     11 
     12 // Mocha HTML reporter doesn't show deepEqual diffs, so we change this.
     13 chai.config.truncateThreshold = 0
     14 
     15 function quit(failed) {
     16 	// Quit with exit status
     17 	if(!failed) {
     18 		OS.File.writeAtomic(OS.Path.join(OS.Constants.Path.profileDir, "success"), new Uint8Array(0));
     19 	}
     20 	if(!ZoteroUnit.noquit) {
     21 		setTimeout(function () {
     22 			Components.classes['@mozilla.org/toolkit/app-startup;1']
     23 				.getService(Components.interfaces.nsIAppStartup)
     24 				.quit(Components.interfaces.nsIAppStartup.eForceQuit);
     25 		}, 250);
     26 	}
     27 }
     28 
     29 if (ZoteroUnit.makeTestData) {
     30 	let dataPath = getTestDataDirectory().path;
     31 	
     32 	Zotero.Prefs.set("export.citePaperJournalArticleURL", true);
     33 	
     34 	let dataFiles = [
     35 		{
     36 			name: 'allTypesAndFields',
     37 			func: generateAllTypesAndFieldsData
     38 		},
     39 		{
     40 			name: 'itemJSON',
     41 			func: generateItemJSONData,
     42 			args: [null]
     43 		},
     44 		// {
     45 		// 	name: 'citeProcJSExport',
     46 		// 	func: generateCiteProcJSExportData
     47 		// },
     48 		{
     49 			name: 'translatorExportLegacy',
     50 			func: generateTranslatorExportData,
     51 			args: [true]
     52 		},
     53 		{
     54 			name: 'translatorExport',
     55 			func: generateTranslatorExportData,
     56 			args: [false]
     57 		}
     58 	];
     59 	Zotero.Promise.coroutine(function* () {
     60 		yield Zotero.initializationPromise;
     61 		for (let i=0; i<dataFiles.length; i++) {
     62 			let first = !i;
     63 			let params = dataFiles[i];
     64 
     65 			// Make sure to not run next loop if previous fails
     66 			if (!first) dump('\n');
     67 			dump('Generating data for ' + params.name + '...');
     68 
     69 			let filePath = OS.Path.join(dataPath, params.name + '.js');
     70 			let exists = yield OS.File.exists(filePath);
     71 			let currentData;
     72 			if (exists) {
     73 				currentData = loadSampleData(params.name);
     74 			}
     75 
     76 			let args = params.args || [];
     77 			args.push(currentData);
     78 			let newData = params.func.apply(null, args);
     79 			if (newData instanceof Zotero.Promise) {
     80 				newData = yield newData;
     81 			}
     82 			let str = stableStringify(newData);
     83 
     84 			yield OS.File.writeAtomic(OS.Path.join(dataPath, params.name + '.js'), str);
     85 			dump("done.");
     86 		}
     87 	})()
     88 	.catch(function(e) { dump('\n'); dump(Zotero.Utilities.varDump(e)) })
     89 	.finally(function() { quit(false) });
     90 }
     91 
     92 function Reporter(runner) {
     93 	var indents = 0, passed = 0, failed = 0, aborted = false;
     94 
     95 	function indent() {
     96 		return Array(indents).join('  ');
     97 	}
     98 
     99 	runner.on('start', function(){});
    100 
    101 	runner.on('suite', function(suite){
    102 		++indents;
    103 		dump("\r"+indent()+suite.title+"\n");
    104 	});
    105 
    106 	runner.on('suite end', function(suite){
    107 		--indents;
    108 		if (1 == indents) dump("\n");
    109 	});
    110 
    111 	runner.on('pending', function(test){
    112 		dump("\r"+indent()+"pending  -"+test.title+"\n");
    113 	});
    114 
    115 	runner.on('pass', function(test){
    116 		passed++;
    117 		var msg = "\r"+indent()+Mocha.reporters.Base.symbols.ok+" "+test.title;
    118 		if ('fast' != test.speed) {
    119 			msg += " ("+Math.round(test.duration)+" ms)";
    120 		}
    121 		dump(msg+"\n");
    122 	});
    123 
    124 	runner.on('fail', function(test, err){
    125 		// Remove internal code references
    126 		err.stack = err.stack.replace(/.+(?:zotero-unit\/|\/Task\.jsm|\/bluebird\.js).+\n?/g, "");
    127 		
    128 		// Strip "From previous event:" block if it's all internals
    129 		if (err.stack.indexOf('From previous event:') != -1) {
    130 			err.stack = err.stack
    131 				// Drop first line, because it contains the error message
    132 				.replace(/^.+\n/, '')
    133 				// Drop "From previous event:" labels for empty blocks
    134 				.replace(/.*From previous event:.*(?:\n(?=\s*From previous event:)|\s*$)/g, '');
    135 		}
    136 		
    137 		// Make sure there's a blank line after all stack traces
    138 		err.stack = err.stack.replace(/\s*$/, '\n\n');
    139 		
    140 		failed++;
    141 		let indentStr = indent();
    142 		dump("\r" + indentStr
    143 			// Dark red X for errors
    144 			+ "\x1B[31;40m" + Mocha.reporters.Base.symbols.err + " [FAIL]\x1B[0m"
    145 			// Trigger bell if interactive
    146 			+ (Zotero.automatedTest ? "" : "\x07")
    147 			+ " " + test.title + "\n"
    148 			+ indentStr + "  " + err.toString() + " at\n"
    149 			+ err.stack.replace(/^/gm, indentStr + "    "));
    150 		
    151 		if (ZoteroUnit.bail) {
    152 			aborted = true;
    153 			runner.abort();
    154 		}
    155 	});
    156 
    157 	runner.on('end', function() {
    158 		dump(passed + "/" + (passed + failed) + " tests passed"
    159 			+ (aborted ? " -- aborting" : "") + "\n");
    160 		quit(failed != 0);
    161 	});
    162 }
    163 
    164 // Setup Mocha
    165 mocha.setup({
    166 	ui: "bdd",
    167 	reporter: Reporter,
    168 	timeout: ZoteroUnit.timeout || 10000,
    169 	grep: ZoteroUnit.grep
    170 });
    171 
    172 coMocha(Mocha);
    173 
    174 before(function () {
    175 	// Store all prefs set in runtests.sh
    176 	Components.utils.import("resource://zotero/config.js");
    177 	var prefBranch = Services.prefs.getBranch(ZOTERO_CONFIG.PREF_BRANCH);
    178 	ZoteroUnit.customPrefs = {};
    179 	prefBranch.getChildList("", {})
    180 		.filter(key => prefBranch.prefHasUserValue(key))
    181 		.forEach(key => ZoteroUnit.customPrefs[key] = Zotero.Prefs.get(key));
    182 });
    183 
    184 /**
    185  * Clear all prefs, and reset those set in runtests.sh to original values
    186  */
    187 function resetPrefs() {
    188 	Components.utils.import("resource://zotero/config.js");
    189 	var prefBranch = Services.prefs.getBranch(ZOTERO_CONFIG.PREF_BRANCH);
    190 	prefBranch.getChildList("", {}).forEach(key => {
    191 		var origVal = ZoteroUnit.customPrefs[key];
    192 		if (origVal !== undefined) {
    193 			if (origVal != Zotero.Prefs.get(key)) {
    194 				Zotero.Prefs.set(key, ZoteroUnit.customPrefs[key]);
    195 			}
    196 		}
    197 		else if (prefBranch.prefHasUserValue(key)) {
    198 			Zotero.Prefs.clear(key)
    199 		}
    200 	});
    201 }
    202 
    203 afterEach(function () {
    204 	resetPrefs();
    205 });
    206 
    207 
    208 var assert = chai.assert,
    209     expect = chai.expect;
    210 
    211 // Set up tests to run
    212 var run = ZoteroUnit.runTests;
    213 if(run && ZoteroUnit.tests) {
    214 	function getTestFilename(test) {
    215 		// Allow foo, fooTest, fooTest.js, and tests/fooTest.js
    216 		test = test.replace(/\.js$/, "");
    217 		test = test.replace(/Test$/, "");
    218 		test = test.replace(/^tests[/\\]/, "");
    219 		return test + "Test.js";
    220 	}
    221 	
    222 	var testDirectory = getTestDataDirectory().parent,
    223 	    testFiles = [];
    224 	if(ZoteroUnit.tests == "all") {
    225 		var enumerator = testDirectory.directoryEntries;
    226 		let startFile = ZoteroUnit.startAt ? getTestFilename(ZoteroUnit.startAt) : false;
    227 		let started = !startFile;
    228 		let stopFile = ZoteroUnit.stopAt ? getTestFilename(ZoteroUnit.stopAt) : false;
    229 		while(enumerator.hasMoreElements()) {
    230 			var file = enumerator.getNext().QueryInterface(Components.interfaces.nsIFile);
    231 			if (file.leafName.endsWith(".js")) {
    232 				testFiles.push(file.leafName);
    233 			}
    234 		}
    235 		testFiles.sort();
    236 		
    237 		// Find the start and stop files
    238 		let startPos = 0;
    239 		let stopPos = testFiles.length - 1;
    240 		for (let i = 0; i < testFiles.length; i++) {
    241 			if (testFiles[i] == startFile) {
    242 				startPos = i;
    243 			}
    244 			if (testFiles[i] == stopFile) {
    245 				stopPos = i;
    246 				break;
    247 			}
    248 		}
    249 		if (startFile && startPos == 0 && startFile != testFiles[0]) {
    250 			dump(`Invalid start file ${startFile}\n`);
    251 		}
    252 		testFiles = testFiles.slice(startPos, stopPos + 1);
    253 	} else {
    254 		var specifiedTests = ZoteroUnit.tests.split(",");
    255 		for (let test of specifiedTests) {
    256 			let fname = getTestFilename(test);
    257 			let file = testDirectory.clone();
    258 			file.append(fname);
    259 			if (!file.exists()) {
    260 				dump("Invalid test file "+test+"\n");
    261 				run = false;
    262 				quit(true);
    263 			}
    264 			testFiles.push(fname);
    265 		}
    266 	}
    267 
    268 	for(var fname of testFiles) {
    269 		var el = document.createElement("script");
    270 		el.type = "application/javascript;version=1.8";
    271 		el.src = "resource://zotero-unit-tests/"+fname;
    272 		el.async = false;
    273 		document.body.appendChild(el);
    274 	}
    275 }
    276 
    277 if(run) {
    278 	window.onload = function() {
    279 		Zotero.spawn(function* () {
    280 			yield Zotero.Schema.schemaUpdatePromise;
    281 			
    282 			initPDFToolsPath();
    283 			
    284 			return mocha.run();
    285 		})
    286 	};
    287 }