summaryrefslogtreecommitdiff
path: root/node_modules/jake/lib/test_task.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/jake/lib/test_task.js')
-rw-r--r--node_modules/jake/lib/test_task.js270
1 files changed, 270 insertions, 0 deletions
diff --git a/node_modules/jake/lib/test_task.js b/node_modules/jake/lib/test_task.js
new file mode 100644
index 0000000..6482bf1
--- /dev/null
+++ b/node_modules/jake/lib/test_task.js
@@ -0,0 +1,270 @@
+/*
+ * Jake JavaScript build tool
+ * Copyright 2112 Matthew Eernisse (mde@fleegix.org)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+let path = require('path');
+let currDir = process.cwd();
+
+/**
+ @name jake
+ @namespace jake
+*/
+/**
+ @name jake.TestTask
+ @constructor
+ @description Instantiating a TestTask creates a number of Jake
+ Tasks that make running tests for your software easy.
+
+ @param {String} name The name of the project
+ @param {Function} definition Defines the list of files containing the tests,
+ and the name of the namespace/task for running them. Will be executed on the
+ instantiated TestTask (i.e., 'this', will be the TestTask instance), to set
+ the various instance-propertiess.
+
+ @example
+ let t = new jake.TestTask('bij-js', function () {
+ this.testName = 'testSpecial';
+ this.testFiles.include('test/**');
+ });
+
+ */
+let TestTask = function () {
+ let self = this;
+ let args = Array.prototype.slice.call(arguments);
+ let name = args.shift();
+ let definition = args.pop();
+ let prereqs = args.pop() || [];
+
+ /**
+ @name jake.TestTask#testNam
+ @public
+ @type {String}
+ @description The name of the namespace to place the tests in, and
+ the top-level task for running tests. Defaults to "test"
+ */
+ this.testName = 'test';
+
+ /**
+ @name jake.TestTask#testFiles
+ @public
+ @type {jake.FileList}
+ @description The list of files containing tests to load
+ */
+ this.testFiles = new jake.FileList();
+
+ /**
+ @name jake.TestTask#showDescription
+ @public
+ @type {Boolean}
+ @description Show the created task when doing Jake -T
+ */
+ this.showDescription = true;
+
+ /*
+ @name jake.TestTask#totalTests
+ @public
+ @type {Number}
+ @description The total number of tests to run
+ */
+ this.totalTests = 0;
+
+ /*
+ @name jake.TestTask#executedTests
+ @public
+ @type {Number}
+ @description The number of tests successfully run
+ */
+ this.executedTests = 0;
+
+ if (typeof definition == 'function') {
+ definition.call(this);
+ }
+
+ if (this.showDescription) {
+ desc('Run the tests for ' + name);
+ }
+
+ task(this.testName, prereqs, {async: true}, function () {
+ let t = jake.Task[this.fullName + ':run'];
+ t.on('complete', function () {
+ complete();
+ });
+ // Pass args to the namespaced test
+ t.invoke.apply(t, arguments);
+ });
+
+ namespace(self.testName, function () {
+
+ let runTask = task('run', {async: true}, function (pat) {
+ let re;
+ let testFiles;
+
+ // Don't nest; make a top-level namespace. Don't want
+ // re-calling from inside to nest infinitely
+ jake.currentNamespace = jake.defaultNamespace;
+
+ re = new RegExp(pat);
+ // Get test files that match the passed-in pattern
+ testFiles = self.testFiles.toArray()
+ .filter(function (f) {
+ return (re).test(f);
+ }) // Don't load the same file multiple times -- should this be in FileList?
+ .reduce(function (p, c) {
+ if (p.indexOf(c) < 0) {
+ p.push(c);
+ }
+ return p;
+ }, []);
+
+ // Create a namespace for all the testing tasks to live in
+ namespace(self.testName + 'Exec', function () {
+ // Each test will be a prereq for the dummy top-level task
+ let prereqs = [];
+ // Continuation to pass to the async tests, wrapping `continune`
+ let next = function () {
+ complete();
+ };
+ // Create the task for this test-function
+ let createTask = function (name, action) {
+ // If the test-function is defined with a continuation
+ // param, flag the task as async
+ let t;
+ let isAsync = !!action.length;
+
+ // Define the actual namespaced task with the name, the
+ // wrapped action, and the correc async-flag
+ t = task(name, createAction(name, action), {
+ async: isAsync
+ });
+ t.once('complete', function () {
+ self.executedTests++;
+ });
+ t._internal = true;
+ return t;
+ };
+ // Used as the action for the defined task for each test.
+ let createAction = function (n, a) {
+ // A wrapped function that passes in the `next` function
+ // for any tasks that run asynchronously
+ return function () {
+ let cb;
+ if (a.length) {
+ cb = next;
+ }
+ if (!(n == 'before' || n == 'after' ||
+ /_beforeEach$/.test(n) || /_afterEach$/.test(n))) {
+ jake.logger.log(n);
+ }
+ // 'this' will be the task when action is run
+ return a.call(this, cb);
+ };
+ };
+ // Dummy top-level task for everything to be prereqs for
+ let topLevel;
+
+ // Pull in each test-file, and iterate over any exported
+ // test-functions. Register each test-function as a prereq task
+ testFiles.forEach(function (file) {
+ let exp = require(path.join(currDir, file));
+
+ // Create a namespace for each filename, so test-name collisions
+ // won't be a problem
+ namespace(file, function () {
+ let testPrefix = self.testName + 'Exec:' + file + ':';
+ let testName;
+ // Dummy task for displaying file banner
+ testName = '*** Running ' + file + ' ***';
+ prereqs.push(testPrefix + testName);
+ createTask(testName, function () {});
+
+ // 'before' setup
+ if (typeof exp.before == 'function') {
+ prereqs.push(testPrefix + 'before');
+ // Create the task
+ createTask('before', exp.before);
+ }
+
+ // Walk each exported function, and create a task for each
+ for (let p in exp) {
+ if (p == 'before' || p == 'after' ||
+ p == 'beforeEach' || p == 'afterEach') {
+ continue;
+ }
+
+ if (typeof exp.beforeEach == 'function') {
+ prereqs.push(testPrefix + p + '_beforeEach');
+ // Create the task
+ createTask(p + '_beforeEach', exp.beforeEach);
+ }
+
+ // Add the namespace:name of this test to the list of prereqs
+ // for the dummy top-level task
+ prereqs.push(testPrefix + p);
+ // Create the task
+ createTask(p, exp[p]);
+
+ if (typeof exp.afterEach == 'function') {
+ prereqs.push(testPrefix + p + '_afterEach');
+ // Create the task
+ createTask(p + '_afterEach', exp.afterEach);
+ }
+ }
+
+ // 'after' teardown
+ if (typeof exp.after == 'function') {
+ prereqs.push(testPrefix + 'after');
+ // Create the task
+ let afterTask = createTask('after', exp.after);
+ afterTask._internal = true;
+ }
+
+ });
+ });
+
+ self.totalTests = prereqs.length;
+ process.on('exit', function () {
+ // Throw in the case where the process exits without
+ // finishing tests, but no error was thrown
+ if (!jake.errorCode && (self.totalTests > self.executedTests)) {
+ throw new Error('Process exited without all tests completing.');
+ }
+ });
+
+ // Create the dummy top-level task. When calling a task internally
+ // with `invoke` that is async (or has async prereqs), have to listen
+ // for the 'complete' event to know when it's done
+ topLevel = task('__top__', prereqs);
+ topLevel._internal = true;
+ topLevel.addListener('complete', function () {
+ jake.logger.log('All tests ran successfully');
+ complete();
+ });
+
+ topLevel.invoke(); // Do the thing!
+ });
+
+ });
+ runTask._internal = true;
+
+ });
+
+
+};
+
+jake.TestTask = TestTask;
+exports.TestTask = TestTask;
+