Commit 936876b5 authored by Daniel Shumway's avatar Daniel Shumway

test(tape): test core library

parent 69fc1483
require('./tape/test.js');
require('./tape/assertions.js');
require('./tape/callback.js');
require('./tape/recursion.js');
/*
* BASIC TEST RESOLUTION
*----------------------------------------------------------
*
* This checks that logic for tests passing/failing works correctly
* It also does shallow tests for recursion
*
* Ways to resolve a test include:
* - passing nothing
* - passing a (failed) promise
* - passing false
*
* If a function or a resolved promise are passed:
* - the returned/resolved result is recursively evaluated with the above rules
*/
var tape = require('tape');
var Distilled = require('Distilled');
tape('accept `null`', function (t) {
t.plan(2);
var suite = new Distilled(function (test) {
if (test.label === 'A' || test.label === 'B') {
t.equal(test.status, Distilled.STATUS.PASSED, 'Passing `null` or `undefined` causes the test to pass');
}
});
suite.test('A', null);
suite.test('B', undefined);
});
tape('accept Boolean`', function (t) {
t.plan(2);
var suite = new Distilled(function (test) {
if (test.label === 'A') {
t.equal(test.status, Distilled.STATUS.PASSED, 'Passing `true` causes the test to pass');
}
if (test.label === 'B') {
t.equal(test.status, Distilled.STATUS.FAILED, 'Passing `false` causes the test to fail');
}
});
suite.test('A', true);
suite.test('B', false);
});
tape('accept Promise', function (t) {
t.plan(3);
var suite = new Distilled(function (test) {
if (test.label === 'A') {
t.equal(test.status, Distilled.STATUS.PASSED, 'Passing Promise (resolved) causes the test to pass');
}
if (test.label === 'B') {
t.equal(test.status, Distilled.STATUS.FAILED, 'Passing Promise (rejected) causes the test to fail');
t.equal(test.error, 'error', '`test.error` is set to the rejected promise\'s error');
}
});
suite.test('A', Promise.resolve());
suite.test('B', Promise.reject('error'));
});
tape('accept Promise: advanced', function (t) {
t.plan(4);
var suite = new Distilled(function (test) {
if (test.label === 'A') {
t.equal(test.status, Distilled.STATUS.FAILED, 'A promise resolving to false causes the test to fail');
}
});
suite.test('A', Promise.resolve(false));
var B = suite.test('B', Promise.resolve(function (test) {
t.pass('A promise resolving to a function calls that function');
t.equal(test, B, 'The resulting test/suite is passed into the function');
t.equal(test, this, '`this` is set to the resulting test/suite');
}));
});
tape('accept Function', function (t) {
t.plan(7);
var suite = new Distilled(function (test) {
switch (test.label) {
case 'A':
t.equal(test.status, Distilled.STATUS.PASSED, 'returning `undefined` from a function causes test to pass');
break;
case 'B':
t.equal(test.status, Distilled.STATUS.FAILED, 'returning `false` from a function causes test to fail');
break;
case 'C':
t.equal(test.status, Distilled.STATUS.FAILED, 'throwing exception from function causes test to fail');
t.equal(test.error, 'error', '`test.error` is set to the thrown exception');
}
});
var A = suite.test('A', function (test) {
t.pass('passing a function calls the function');
t.equal(test, A, 'The resulting test/suite is passed into the function');
t.equal(test, this, '`this` is set to the resulting test/suite');
});
suite.test('B', function () { return false; });
suite.test('C', function () { throw 'error'; });
});
/*
* CALLBACK TESTS
*-----------------------------------------------------------
*
* Whenever a test resolves, a callback is called:
* - this is primarily a place to do reporting and logging
* - it can also be adapted into a harness runner
* - it can also be used to extend Distilled and add new features
*
* You don't need to understand how Promises work to use Distilled:
* - but, if you do understand Promises, that will probably make you better
* - tests are executed as promises, and when they resolve, the callback is called
*/
var Distilled = require('Distilled');
var tape = require('tape');
tape('Basic callback', function (t) {
t.plan(3);
var suite = new Distilled(function (test) {
t.pass('Callback is called immediately after a suite is created');
t.equal(test, suite, 'Callback is passed the resulting test/suite as a parameter');
t.equal(this, suite, '`this` is set to the resulting test/suite');
});
});
tape('Multiple tests', function (t) {
t.plan(2);
var calls = [];
var tests = [];
var suite = new Distilled(function (test) {
calls.push(test);
if (calls.length === 3) {
t.pass('Callback is called for each test');
t.deepEqual(calls, tests, 'Correct test/suite passed into each callback');
}
});
tests.push(suite);
tests.push(suite.test('A'));
tests.push(suite.test('B'));
});
tape('Nested tests', function (t) {
t.plan(2);
var calls = [];
var tests = [];
var suite = new Distilled(function (test) {
calls.push(test);
if (calls.length === 4) {
t.pass('Callback is called for each test');
t.deepEqual(calls, tests, 'Correct test/suite passed into each callback');
}
});
var A = suite.test('A');
var B = A.test('B');
var C = B.test('C');
tests.push(suite);
tests.push(A);
tests.push(B);
tests.push(C);
});
tape('test statuses are set correctly for passed test', function (t) {
t.plan(3);
var pass;
var suite = new Distilled(function (test) {
if (test === pass) {
t.equal(test.label, 'A', '`test.label` is the label originally passed into the test');
t.equal(test.status, Distilled.STATUS.PASSED, '`test.status` is set to `STATUS.PASSED`');
t.equal(test.error, null, '`test.error` in `null` for passed test');
}
});
pass = suite.test('A');
});
tape('test statuses are set correctly for failed test', function (t) {
t.plan(3);
var fail,
error = new Error('error');
var suite = new Distilled(function (test) {
if (test === fail) {
t.equal(test.label, 'A', '`test.label` is the label originally passed into the test');
t.equal(test.status, Distilled.STATUS.FAILED, '`test.status` is set to `STATUS.FAILED`');
t.equal(test.error, error, '`test.error` is set to the error the test failed with');
}
});
fail = suite.test('A', Promise.reject(error));
});
/*
* This test relies on promise resolution order:
* - it's possible this is not reliable.
* - consider codifying promise resolution order, if it is actually predictable and possible to do so.
*/
tape('Skip children of failed tests', function (t) {
t.plan(1);
var calls = 0;
var suite = new Distilled(function () {
++calls;
if (this.label === '_a') {
t.pass('label: ' + this.status);
}
if (this.label === '_b') {
t.equal(calls, 5, 'callbacks are not called for skipped tests');
}
});
suite.test('A', false).test('a').test('_a');
suite.test('B').test('b').test('_b');
});
/*
* RESOLUTION RECURSION
*-----------------------------------------------------
* Short tests to provide some evidence that resolution recursion is actually infinite
*/
var tape = require('tape');
var Distilled = require('Distilled');
tape('Recursively resolving function results', function (t) {
t.plan(2);
var suite = new Distilled(function (test) {
if (test.label === 'A') {
t.equal(test.status, Distilled.STATUS.PASSED, 'nested functions eventually pass correctly');
}
if (test.label === 'B') {
t.equal(test.status, Distilled.STATUS.FAILED, 'nested functions eventually fail correctly');
}
});
suite.test('A', function () {
return function () {
return function () {
return function () {
return function () {
return true;
};
};
};
};
});
suite.test('B', function () {
return function () {
return function () {
return function () {
return function () {
return false;
};
};
};
};
});
});
tape('Recursively resolving promise results', function (t) {
t.plan(2);
var suite = new Distilled(function (test) {
if (test.label === 'A') {
t.equal(test.status, Distilled.STATUS.PASSED, 'nested promises eventually pass correctly');
}
if (test.label === 'B') {
t.equal(test.status, Distilled.STATUS.FAILED, 'nested promises eventually fail correctly');
}
});
suite.test('A', Promise.resolve(
Promise.resolve(
Promise.resolve(
Promise.resolve(
Promise.resolve(true)
)
)
)
));
suite.test('B', Promise.resolve(
Promise.resolve(
Promise.resolve(
Promise.resolve(
Promise.resolve(false)
)
)
)
));
});
tape('Recursively resolving "weird" results', function (t) {
t.plan(2);
var suite = new Distilled(function (test) {
if (test.label === 'A') {
t.equal(test.status, Distilled.STATUS.PASSED, 'nested (mixed) promises/functions eventually pass correctly');
}
if (test.label === 'B') {
t.equal(test.status, Distilled.STATUS.FAILED, 'nested (mixed) promises/functions eventually pass correctly');
}
});
suite.test('A', function () {
return Promise.resolve(function () {
return Promise.resolve(function () {
return true;
});
});
});
suite.test('B', function () {
return Promise.resolve(function () {
return Promise.resolve(function () {
return false;
});
});
});
});
/*
* BASIC TEST BEHAVIOR
*------------------------------------------------------
*
* Tests can be infinitely nested and chained.
* - structure can be accessed through `parent` and `children`
* - children of failed tests are not called/resolved
*/
var tape = require('tape');
var Distilled = require('Distilled');
tape('Tests/suites expose a `test` method', function (t) {
t.plan(2);
var suite = new Distilled(function () {});
t.equal(typeof suite.test, 'function', '`test` function is exposed');
//Use OK instead of `equal` because tape tries to incorrectly access prototype properties during the test
t.ok(Object.getPrototypeOf(suite) === Object.getPrototypeOf(suite.test('A')),
'Calling `test` returns a new test/suite of the same type');
});
tape('Child tests/suites are chained off of their parents', function (t) {
t.plan(4);
var calls = [];
var tests = [];
var suite = new Distilled(function () {});
var child = suite.test('A', function () {
calls.push('A');
}).test('a', function (test) {
calls.push('a');
/*
* Promise resolution order means that this should resolve last.
* - promises that are chained will resolve after promises that are added synchronously.
*/
t.deepEqual(calls, ['A', 'B', 'a'], 'Child tests are resolved in the correct order');
t.equals(test.parent.label, 'A', '`parent` points to parent test');
t.equals(test.parent.status, Distilled.STATUS.PASSED, 'Child is resolved after parent resolves');
});
child.test('_a', function (test) {
t.deepEqual(child.children[0], test, 'Children are added to `children` array on parent test/suite');
});
suite.test('B', function () {
calls.push('B');
});
});
tape('Ignore children of failed tests', function (t) {
t.plan(1);
var calls = [];
var suite = new Distilled(function () {});
suite.test('A', false).test('a', function () {
calls.push('a');
});
/*
* Once again exploiting promise resolution order to guarantee that the above test has an opportunity to fail.
*/
suite.test('B').test('b').test('_b', function () {
t.equal(calls.length, 0, 'Children of failed tests are never resolved');
});
})
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment