Skip to content

Instantly share code, notes, and snippets.

@lorenzofox3
Created October 29, 2019 13:59
Show Gist options
  • Save lorenzofox3/a8e6a7b080bcccde0045153ba3c42341 to your computer and use it in GitHub Desktop.
Save lorenzofox3/a8e6a7b080bcccde0045153ba3c42341 to your computer and use it in GitHub Desktop.

Revisions

  1. lorenzofox3 revised this gist Oct 29, 2019. No changes.
  2. lorenzofox3 created this gist Oct 29, 2019.
    16 changes: 16 additions & 0 deletions reporter.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,16 @@
    module.exports = testResult => {
    const isFailed = testResult.pass === false;
    console.log(`${!isFailed ? 'ok' : 'no ok'} - ${testResult.description}`);
    if (testResult.error) {
    console.log(testResult.error.stack);
    if (testResult.error.operator) {
    console.log(`operator: ${testResult.error.operator}`);
    }
    if (testResult.error.expected) {
    console.log(`expected: \n ${JSON.stringify(testResult.error.expected, null, 4)}`);
    }
    if (testResult.error.actual) {
    console.log(`actual: \n ${JSON.stringify(testResult.error.actual, null, 4)}`);
    }
    }
    };
    24 changes: 24 additions & 0 deletions run.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,24 @@
    const testFunction = require('./test.js');
    const reporter = require('./reporter.js');

    const createHarness = () => {
    const testList = [];
    const test = (description, spec) => testFunction(description, spec, testList);

    return {
    test,
    async report() {
    for (const t of testList) {
    for await (const a of t) {
    reporter(a);
    }
    }
    }
    };
    };

    const defaultTestHarness = createHarness();

    process.nextTick(() => defaultTestHarness.report());

    module.exports = defaultTestHarness;
    49 changes: 49 additions & 0 deletions test.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,49 @@
    const testFunction = module.exports = (description, specFunction, testList) => {
    let error = null;
    let passing = true;
    const subTestList = [];
    // we return the routine so we can explicitly wait for it to complete (serial tests)
    const subTest = (description, fn) => testFunction(description, fn, subTestList).execRoutine;

    // eagerly run the test as soon as testFunction is called
    const execRoutine = (async function () {
    try {
    await specFunction({test: subTest});
    } catch (e) {
    passing = false;
    error = e;
    }
    })();

    const testObject = Object.defineProperties({
    // we **report** test result with async iterators... in a non blocking way
    [Symbol.asyncIterator]: async function* () {
    await execRoutine;
    for await (const t of subTestList) {
    yield* t;// report sub test
    passing = passing && t.pass; // mark parent test as failing in case a subtest fails (but don't bubble the error)
    }
    yield this; // report this test
    }
    }, {
    execRoutine: {value: execRoutine},
    error: {
    get() {
    return error;
    }
    },
    description: {
    value: description
    },
    pass: {
    get() {
    return passing;
    }
    }
    });

    // collect the test in the parent's test list
    testList.push(testObject);

    return testObject;
    };
    50 changes: 50 additions & 0 deletions test_program.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,50 @@
    const assert = require('assert').strict;
    const {test} = require('./run.js');

    const wait = (time = 1000) => new Promise(resolve => setTimeout(() => resolve(), time));

    test(`some failing test`, t => {
    assert.deepEqual([1, 2, 3], [1, 2, 4], `array should be equivalent`);
    });

    test(`some nested test`, t => {
    t.test(`inside`, () => {
    assert.deepEqual({foo: 'bar'}, {foo: 'bar'}, `should match`);
    });

    t.test(`failing inside`, () => {
    assert.ok(false, `oh noooo`);
    });
    });

    test(`some async test that shows concurrency`, async t => {

    let foo = 'bar';

    t.test(`nested async`, async t => {
    await wait(100);
    assert.equal(foo, 'baz', 'see changed value although started before');
    foo = 'whatever';
    });

    t.test(`change foo faster`, t => {
    assert.equal(foo, 'bar');
    foo = 'baz';
    });

    });

    test(`some serial test`, async t => {
    let foo = 'bar';

    await t.test('nested inside', async t => {
    await wait(100);
    assert.equal(foo, 'bar', 'see the initial value of foo');
    foo = 'whatever';
    });

    t.test('run only once "nested inside" has finished', () => {
    assert.equal(foo, 'whatever', 'see the changed value');
    });

    });