mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-12-29 19:40:28 +00:00
162 lines
6.5 KiB
JavaScript
162 lines
6.5 KiB
JavaScript
/*\
|
|
title: $:/plugins/tiddlywiki/jasmine/jasmine-plugin.js
|
|
type: application/javascript
|
|
module-type: library
|
|
|
|
The main module of the Jasmine test plugin for TiddlyWiki5
|
|
|
|
\*/
|
|
(function(){
|
|
|
|
/*jslint node: true, browser: true */
|
|
/*global $tw: true */
|
|
"use strict";
|
|
|
|
var TEST_TIDDLER_FILTER = "[all[tiddlers+shadows]type[application/javascript]tag[$:/tags/test-spec]]";
|
|
var TESTS_DONE = false;
|
|
|
|
exports.testsWereRun = function() {
|
|
return TESTS_DONE;
|
|
};
|
|
|
|
/*
|
|
function for running tests
|
|
|
|
Below, paths like jasmine-core/jasmine.js refer to files in the 'jasmine-core' npm
|
|
package, whose repository is https://github.com/jasmine/jasmine.
|
|
Paths like jasmine/jasmine.js refer to files in the 'jasmine' npm package, whose
|
|
repository is https://github.com/jasmine/jasmine-npm.
|
|
|
|
They're all locally checked into the `./files` directory.
|
|
*/
|
|
|
|
exports.runTests = function(callback,specFilter) {
|
|
// Set up a shared context object.
|
|
var context = {
|
|
console: console,
|
|
setInterval: setInterval,
|
|
clearInterval: clearInterval,
|
|
setTimeout: setTimeout,
|
|
clearTimeout: clearTimeout,
|
|
$tw: $tw
|
|
};
|
|
// The `global` property is needed in two places:
|
|
// 1. jasmine-core/node_boot.js: extends the global object with jasmine interface.
|
|
// 2. jasmine-core/jasmine.js: when it's loaded, if it determines that it's
|
|
// running in a commonjs environment and `global` is undefined, it will set
|
|
// `jasmineGlobal`, its internal reference to the global object, to {},
|
|
// which is not what we want. Alternatively, the `jasmine.getEnv()` API allows
|
|
// you to pass in a `global` object, but the boot scripts we use don't allow
|
|
// the caller to customize the `.getEnv()` call. We'd rather use the boot scripts
|
|
// as-is than duplicating them in order to do minor tweaks.
|
|
//
|
|
// We need this `$tw.browser ?` conditional because:
|
|
// 1. In a browser environment, 'jasmine-core/jasmine.js' calls `setTimeout` like
|
|
// `setTimeout.apply(jasmineGlobal, ...)`; the browser throws an "illegal invocation"
|
|
// unless `jasmineGlobal` is the right context object, which is `window`.
|
|
// 2. In Node.js, there is no `window` object.
|
|
// Further more, we don't have access to the `global` object when this code
|
|
// is executed, so we use the `context` object instead.
|
|
context.global = $tw.browser ? window : context;
|
|
|
|
// We set this early rather than at the end for simplicity. The browser
|
|
// and node.js environments don't end the same way.
|
|
TESTS_DONE = true;
|
|
|
|
function evalInContext(title) {
|
|
var code = $tw.wiki.getTiddlerText(title,"");
|
|
var _exports = {};
|
|
context.exports = _exports;
|
|
context.module = {exports: _exports};
|
|
context.require = function(moduleTitle) {
|
|
// mock out the 'glob' module required in
|
|
// "$:/plugins/tiddlywiki/jasmine/jasmine/jasmine.js"
|
|
if (moduleTitle === "glob") {
|
|
return {};
|
|
}
|
|
return $tw.modules.execute(moduleTitle,title);
|
|
};
|
|
var contextExports = $tw.utils.evalSandboxed(code,context,title,true);
|
|
// jasmine/jasmine.js assigns directly to `module.exports`: check
|
|
// for it first.
|
|
return context.module.exports || contextExports;
|
|
}
|
|
|
|
// Get the core Jasmine exports.
|
|
// We load 'jasmine-core/jasmine.js' here in order to start with a module
|
|
// that is shared between browser and Node.js environments. Browser-specific
|
|
// and Node-specific modules are loaded next.
|
|
var jasmineCore = evalInContext("$:/plugins/tiddlywiki/jasmine/jasmine-core/jasmine-core/jasmine.js");
|
|
// The core Jasmine instance
|
|
var jasmine;
|
|
// Node.js wrapper for calling `.execute()`
|
|
var nodeJasmineWrapper;
|
|
if($tw.browser) {
|
|
window.jasmineRequire = jasmineCore;
|
|
$tw.modules.execute("$:/plugins/tiddlywiki/jasmine/jasmine-core/jasmine-core/jasmine-html.js");
|
|
// Prevent jasmine-core/boot.js from installing its own onload handler. We'll execute it explicitly when everything is ready
|
|
var previousOnloadHandler = window.onload;
|
|
window.onload = function() {};
|
|
$tw.modules.execute("$:/plugins/tiddlywiki/jasmine/jasmine-core/jasmine-core/boot.js");
|
|
var jasmineOnloadHandler = window.onload;
|
|
window.onload = function() {};
|
|
jasmine = window.jasmine;
|
|
} else {
|
|
// Add missing properties to `jasmineCore` in order to call the Jasmine
|
|
// constructor in Node.js.
|
|
//
|
|
// The constructor loads the `jasmineCore` object automatically, if
|
|
// not explicitly specified, by calling `require('jasmine-core')`.
|
|
// What happens internally next is...
|
|
//
|
|
// 1. require('jasmine-core')
|
|
// a. loads the package's main script, 'jasmine-core/jasmine-core.js'
|
|
// i. requires 'jasmine-core/jasmine.js'
|
|
// ii. reads some extra files and returns a `jasmineCore` object
|
|
//
|
|
// Because we're in TiddlyWiki land, we really don't need step 1.a.ii.
|
|
//
|
|
// Since the `jasmineCore` variable already holds the result of 1.a.i,
|
|
// we'll add a few properties necessary for calling the Jasmine constructor
|
|
// and pass it in explicitly. The consructor function can be seen here:
|
|
// https://github.com/jasmine/jasmine-npm/blob/v3.4.0/lib/jasmine.js#L10
|
|
|
|
// 'jasmine/jasmine.js' requires the `.boot()` function
|
|
jasmineCore.boot = evalInContext("$:/plugins/tiddlywiki/jasmine/jasmine-core/jasmine-core/node_boot.js");
|
|
// 'jasmine/jasmine.js' references `.files.path`
|
|
jasmineCore.files = {
|
|
path: "$:/plugins/tiddlywiki/jasmine/jasmine-core/jasmine-core"
|
|
};
|
|
// 'jasmine/jasmine.js' references `process.exit`, among other properties
|
|
// It will call 'exit' after it's done, which gives us an
|
|
// opportunity to resynchronize and finish any following commands.
|
|
context.process = Object.create(process);
|
|
context.process.exit = function(code) {
|
|
// If jasmine's exit code is non-zero, tests failed. Abort any
|
|
// further commands. If they're important, they could have come
|
|
// before the testing suite.
|
|
callback(code ? "Tests failed with code " + code : undefined);
|
|
};
|
|
|
|
var NodeJasmine = evalInContext("$:/plugins/tiddlywiki/jasmine/jasmine/jasmine.js");
|
|
nodeJasmineWrapper = new NodeJasmine({jasmineCore: jasmineCore});
|
|
jasmine = nodeJasmineWrapper.jasmine;
|
|
}
|
|
// Add Jasmine's DSL to our context
|
|
var env = jasmine.getEnv();
|
|
var jasmineInterface = jasmineCore.interface(jasmine,env)
|
|
context = $tw.utils.extend({},jasmineInterface,context);
|
|
// Iterate through all the test modules
|
|
var tests = $tw.wiki.filterTiddlers(TEST_TIDDLER_FILTER);
|
|
$tw.utils.each(tests,evalInContext);
|
|
// In a browser environment, we use jasmine-core/boot.js to call `execute()` for us.
|
|
// In Node.js, we call it manually.
|
|
if($tw.browser) {
|
|
jasmineOnloadHandler();
|
|
} else {
|
|
nodeJasmineWrapper.execute(null,specFilter);
|
|
}
|
|
};
|
|
|
|
})();
|