aboutsummaryrefslogtreecommitdiff
path: root/node_modules/ava/lib/test-collection.js
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2017-05-28 00:38:50 +0200
committerFlorian Dold <florian.dold@gmail.com>2017-05-28 00:40:43 +0200
commit7fff4499fd915bcea3fa93b1aa8b35f4fe7a6027 (patch)
tree6de9a1aebd150a23b7f8c273ec657a5d0a18fe3e /node_modules/ava/lib/test-collection.js
parent963b7a41feb29cc4be090a2446bdfe0c1f1bcd81 (diff)
add linting (and some initial fixes)
Diffstat (limited to 'node_modules/ava/lib/test-collection.js')
-rw-r--r--node_modules/ava/lib/test-collection.js206
1 files changed, 206 insertions, 0 deletions
diff --git a/node_modules/ava/lib/test-collection.js b/node_modules/ava/lib/test-collection.js
new file mode 100644
index 000000000..5404cb119
--- /dev/null
+++ b/node_modules/ava/lib/test-collection.js
@@ -0,0 +1,206 @@
+'use strict';
+const EventEmitter = require('events');
+const fnName = require('fn-name');
+const Concurrent = require('./concurrent');
+const Sequence = require('./sequence');
+const Test = require('./test');
+
+class TestCollection extends EventEmitter {
+ constructor(options) {
+ super();
+
+ this.bail = options.bail;
+ this.failWithoutAssertions = options.failWithoutAssertions;
+ this.getSnapshotState = options.getSnapshotState;
+ this.hasExclusive = false;
+ this.testCount = 0;
+
+ this.tests = {
+ concurrent: [],
+ serial: []
+ };
+
+ this.hooks = {
+ before: [],
+ beforeEach: [],
+ after: [],
+ afterAlways: [],
+ afterEach: [],
+ afterEachAlways: []
+ };
+
+ this.pendingTestInstances = new Set();
+
+ this._emitTestResult = this._emitTestResult.bind(this);
+ }
+ add(test) {
+ const metadata = test.metadata;
+ const type = metadata.type;
+
+ if (!type) {
+ throw new Error('Test type must be specified');
+ }
+
+ if (!test.title && test.fn) {
+ test.title = fnName(test.fn);
+ }
+
+ // Workaround for Babel giving anonymous functions a name
+ if (test.title === 'callee$0$0') {
+ test.title = null;
+ }
+
+ if (!test.title) {
+ if (type === 'test') {
+ test.title = '[anonymous]';
+ } else {
+ test.title = type;
+ }
+ }
+
+ if (metadata.always && type !== 'after' && type !== 'afterEach') {
+ throw new Error('"always" can only be used with after and afterEach hooks');
+ }
+
+ // Add a hook
+ if (type !== 'test') {
+ if (metadata.exclusive) {
+ throw new Error(`"only" cannot be used with a ${type} hook`);
+ }
+
+ this.hooks[type + (metadata.always ? 'Always' : '')].push(test);
+ return;
+ }
+
+ this.testCount++;
+
+ // Add `.only()` tests if `.only()` was used previously
+ if (this.hasExclusive && !metadata.exclusive) {
+ return;
+ }
+
+ if (metadata.exclusive && !this.hasExclusive) {
+ this.tests.concurrent = [];
+ this.tests.serial = [];
+ this.hasExclusive = true;
+ }
+
+ if (metadata.serial) {
+ this.tests.serial.push(test);
+ } else {
+ this.tests.concurrent.push(test);
+ }
+ }
+ _skippedTest(test) {
+ return {
+ run: () => {
+ this._emitTestResult({
+ passed: true,
+ result: test
+ });
+
+ return true;
+ }
+ };
+ }
+ _emitTestResult(result) {
+ this.pendingTestInstances.delete(result.result);
+ this.emit('test', result);
+ }
+ _buildHooks(hooks, testTitle, context) {
+ return hooks.map(hook => {
+ const test = this._buildHook(hook, testTitle, context);
+
+ if (hook.metadata.skipped || hook.metadata.todo) {
+ return this._skippedTest(test);
+ }
+
+ return test;
+ });
+ }
+ _buildHook(hook, testTitle, contextRef) {
+ let title = hook.title;
+
+ if (testTitle) {
+ title += ` for ${testTitle}`;
+ }
+
+ if (!contextRef) {
+ contextRef = null;
+ }
+
+ const test = new Test({
+ contextRef,
+ failWithoutAssertions: false,
+ fn: hook.fn,
+ getSnapshotState: this.getSnapshotState,
+ metadata: hook.metadata,
+ onResult: this._emitTestResult,
+ title
+ });
+ this.pendingTestInstances.add(test);
+ return test;
+ }
+ _buildTest(test, contextRef) {
+ if (!contextRef) {
+ contextRef = null;
+ }
+
+ test = new Test({
+ contextRef,
+ failWithoutAssertions: this.failWithoutAssertions,
+ fn: test.fn,
+ getSnapshotState: this.getSnapshotState,
+ metadata: test.metadata,
+ onResult: this._emitTestResult,
+ title: test.title
+ });
+ this.pendingTestInstances.add(test);
+ return test;
+ }
+ _buildTestWithHooks(test) {
+ if (test.metadata.skipped || test.metadata.todo) {
+ return new Sequence([this._skippedTest(this._buildTest(test))], true);
+ }
+
+ const context = {context: {}};
+
+ const beforeHooks = this._buildHooks(this.hooks.beforeEach, test.title, context);
+ const afterHooks = this._buildHooks(this.hooks.afterEach, test.title, context);
+
+ let sequence = new Sequence([].concat(beforeHooks, this._buildTest(test, context), afterHooks), true);
+ if (this.hooks.afterEachAlways.length > 0) {
+ const afterAlwaysHooks = new Sequence(this._buildHooks(this.hooks.afterEachAlways, test.title, context));
+ sequence = new Sequence([sequence, afterAlwaysHooks], false);
+ }
+ return sequence;
+ }
+ _buildTests(tests) {
+ return tests.map(test => this._buildTestWithHooks(test));
+ }
+ build() {
+ const beforeHooks = new Sequence(this._buildHooks(this.hooks.before));
+ const afterHooks = new Sequence(this._buildHooks(this.hooks.after));
+
+ const serialTests = new Sequence(this._buildTests(this.tests.serial), this.bail);
+ const concurrentTests = new Concurrent(this._buildTests(this.tests.concurrent), this.bail);
+ const allTests = new Sequence([serialTests, concurrentTests]);
+
+ let finalTests = new Sequence([beforeHooks, allTests, afterHooks], true);
+ if (this.hooks.afterAlways.length > 0) {
+ const afterAlwaysHooks = new Sequence(this._buildHooks(this.hooks.afterAlways));
+ finalTests = new Sequence([finalTests, afterAlwaysHooks], false);
+ }
+ return finalTests;
+ }
+ attributeLeakedError(err) {
+ for (const test of this.pendingTestInstances) {
+ if (test.attributeLeakedError(err)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
+
+module.exports = TestCollection;