import {test} from 'tap';import Runner from '../lib/runner.js';import {set as setOptions} from '../lib/worker/options.cjs';setOptions({});const promiseEnd = (runner, next) => new Promise(resolve => {resolve(runner.once('finish'));next(runner);}).then(() => runner);test('before', t => {t.plan(1);const array = [];return promiseEnd(new Runner({file: import.meta.url}), runner => {runner.chain.before(() => {array.push('a');});runner.chain('test', a => {a.pass();array.push('b');});}).then(() => {t.strictSame(array, ['a', 'b']);});});test('after', t => {t.plan(2);const array = [];return promiseEnd(new Runner({file: import.meta.url}), runner => {runner.on('stateChange', evt => {if (evt.type === 'test-passed') {t.pass();}});runner.chain.after(() => {array.push('b');});runner.chain('test', a => {a.pass();array.push('a');});}).then(() => {t.strictSame(array, ['a', 'b']);});});test('after not run if test failed', t => {t.plan(2);const array = [];return promiseEnd(new Runner({file: import.meta.url}), runner => {runner.on('stateChange', evt => {if (evt.type === 'test-failed') {t.pass();}});runner.chain.after(() => {array.push('a');});runner.chain('test', () => {throw new Error('something went wrong');});}).then(() => {t.strictSame(array, []);});});test('after.always run even if test failed', t => {t.plan(2);const array = [];return promiseEnd(new Runner({file: import.meta.url}), runner => {runner.on('stateChange', evt => {if (evt.type === 'test-failed') {t.pass();}});runner.chain.after.always(() => {array.push('a');});runner.chain('test', () => {throw new Error('something went wrong');});}).then(() => {t.strictSame(array, ['a']);});});test('after.always run even if before failed', t => {t.plan(1);const array = [];return promiseEnd(new Runner({file: import.meta.url}), runner => {runner.chain.before(() => {throw new Error('something went wrong');});runner.chain('test', a => a.pass());runner.chain.after.always(() => {array.push('a');});}).then(() => {t.strictSame(array, ['a']);});});test('stop if before hooks failed', t => {t.plan(1);const array = [];return promiseEnd(new Runner({file: import.meta.url}), runner => {runner.chain.before(() => {array.push('a');});runner.chain.before(() => {throw new Error('something went wrong');});runner.chain('test', a => {a.pass();array.push('b');a.end();});}).then(() => {t.strictSame(array, ['a']);});});test('before each with concurrent tests', t => {t.plan(1);const array = [[], []];return promiseEnd(new Runner({file: import.meta.url}), runner => {let i = 0;let k = 0;runner.chain.beforeEach(() => {array[i++].push('a');});runner.chain.beforeEach(() => {array[k++].push('b');});runner.chain('c', a => {a.pass();array[0].push('c');});runner.chain('d', a => {a.pass();array[1].push('d');});}).then(() => {t.strictSame(array, [['a', 'b', 'c'], ['a', 'b', 'd']]);});});test('before each with serial tests', t => {t.plan(1);const array = [];return promiseEnd(new Runner({file: import.meta.url}), runner => {runner.chain.beforeEach(() => {array.push('a');});runner.chain.beforeEach(() => {array.push('b');});runner.chain.serial('c', a => {a.pass();array.push('c');});runner.chain.serial('d', a => {a.pass();array.push('d');});}).then(() => {t.strictSame(array, ['a', 'b', 'c', 'a', 'b', 'd']);});});test('fail if beforeEach hook fails', t => {t.plan(2);const array = [];return promiseEnd(new Runner({file: import.meta.url}), runner => {runner.on('stateChange', evt => {if (evt.type === 'hook-failed') {t.pass();}});runner.chain.beforeEach(a => {array.push('a');a.fail();});runner.chain('test', a => {array.push('b');a.pass();});}).then(() => {t.strictSame(array, ['a']);});});test('after each with concurrent tests', t => {t.plan(1);const array = [[], []];return promiseEnd(new Runner({file: import.meta.url}), runner => {let i = 0;let k = 0;runner.chain.afterEach(() => {array[i++].push('a');});runner.chain.afterEach(() => {array[k++].push('b');});runner.chain('c', a => {a.pass();array[0].push('c');});runner.chain('d', a => {a.pass();array[1].push('d');});}).then(() => {t.strictSame(array, [['c', 'a', 'b'], ['d', 'a', 'b']]);});});test('after each with serial tests', t => {t.plan(1);const array = [];return promiseEnd(new Runner({file: import.meta.url}), runner => {runner.chain.afterEach(() => {array.push('a');});runner.chain.afterEach(() => {array.push('b');});runner.chain.serial('c', a => {a.pass();array.push('c');});runner.chain.serial('d', a => {a.pass();array.push('d');});}).then(() => {t.strictSame(array, ['c', 'a', 'b', 'd', 'a', 'b']);});});test('afterEach not run if concurrent tests failed', t => {t.plan(1);const array = [];return promiseEnd(new Runner({file: import.meta.url}), runner => {runner.chain.afterEach(() => {array.push('a');});runner.chain('test', () => {throw new Error('something went wrong');});}).then(() => {t.strictSame(array, []);});});test('afterEach not run if serial tests failed', t => {t.plan(1);const array = [];return promiseEnd(new Runner({file: import.meta.url}), runner => {runner.chain.afterEach(() => {array.push('a');});runner.chain.serial('test', () => {throw new Error('something went wrong');});}).then(() => {t.strictSame(array, []);});});test('afterEach.always run even if concurrent tests failed', t => {t.plan(1);const array = [];return promiseEnd(new Runner({file: import.meta.url}), runner => {runner.chain.afterEach.always(() => {array.push('a');});runner.chain('test', () => {throw new Error('something went wrong');});}).then(() => {t.strictSame(array, ['a']);});});test('afterEach.always run even if serial tests failed', t => {t.plan(1);const array = [];return promiseEnd(new Runner({file: import.meta.url}), runner => {runner.chain.afterEach.always(() => {array.push('a');});runner.chain.serial('test', () => {throw new Error('something went wrong');});}).then(() => {t.strictSame(array, ['a']);});});test('afterEach.always run even if beforeEach failed', t => {t.plan(1);const array = [];return promiseEnd(new Runner({file: import.meta.url}), runner => {runner.chain.beforeEach(() => {throw new Error('something went wrong');});runner.chain('test', a => {a.pass();array.push('a');});runner.chain.afterEach.always(() => {array.push('b');});}).then(() => {t.strictSame(array, ['b']);});});test('afterEach: property `passed` of execution-context is false when test failed and true when test passed', t => {t.plan(1);const passed = [];let i;return promiseEnd(new Runner({file: import.meta.url}), runner => {runner.chain.afterEach(a => {passed[i] = a.passed;});runner.chain('failure', () => {i = 0;throw new Error('something went wrong');});runner.chain('pass', a => {i = 1;a.pass();});}).then(() => {t.strictSame(passed, [undefined, true]);});});test('afterEach.always: property `passed` of execution-context is false when test failed and true when test passed', t => {t.plan(1);const passed = [];let i;return promiseEnd(new Runner({file: import.meta.url}), runner => {runner.chain.afterEach.always(a => {passed[i] = a.passed;});runner.chain('failure', () => {i = 0;throw new Error('something went wrong');});runner.chain('pass', a => {i = 1;a.pass();});}).then(() => {t.strictSame(passed, [false, true]);});});test('afterEach.always: property `passed` of execution-context is false when before hook failed', t => {t.plan(1);let passed;return promiseEnd(new Runner({file: import.meta.url}), runner => {runner.chain.before(() => {throw new Error('something went wrong');});runner.chain.afterEach.always(a => {passed = a.passed;});runner.chain('pass', a => {a.pass();});}).then(() => {t.notOk(passed);});});test('afterEach.always: property `passed` of execution-context is true when test passed and afterEach hook failed', t => {t.plan(1);let passed;return promiseEnd(new Runner({file: import.meta.url}), runner => {runner.chain.afterEach(() => {throw new Error('something went wrong');});runner.chain.afterEach.always(a => {passed = a.passed;});runner.chain('pass', a => {a.pass();});}).then(() => {t.ok(passed);});});test('ensure hooks run only around tests', t => {t.plan(1);const array = [];return promiseEnd(new Runner({file: import.meta.url}), runner => {runner.chain.beforeEach(() => {array.push('beforeEach');});runner.chain.before(() => {array.push('before');});runner.chain.afterEach(() => {array.push('afterEach');});runner.chain.after(() => {array.push('after');});runner.chain('test', a => {a.pass();array.push('test');});}).then(() => {t.strictSame(array, ['before', 'beforeEach', 'test', 'afterEach', 'after']);});});test('shared context', t => promiseEnd(new Runner({file: import.meta.url}), runner => {runner.on('stateChange', evt => {if (evt.type === 'hook-failed' || evt.type === 'test-failed') {t.fail();}});runner.chain.before(a => {a.deepEqual(a.context, {});a.context.arr = ['a'];a.context.prop = 'before';});runner.chain.after(a => {a.deepEqual(a.context.arr, ['a', 'b', 'c', 'd']);a.is(a.context.prop, 'before');});runner.chain.beforeEach(a => {a.deepEqual(a.context.arr, ['a']);a.context.arr.push('b');a.is(a.context.prop, 'before');a.context.prop = 'beforeEach';});runner.chain('test', a => {a.pass();a.deepEqual(a.context.arr, ['a', 'b']);a.context.arr.push('c');a.is(a.context.prop, 'beforeEach');a.context.prop = 'test';});runner.chain.afterEach(a => {a.deepEqual(a.context.arr, ['a', 'b', 'c']);a.context.arr.push('d');a.is(a.context.prop, 'test');a.context.prop = 'afterEach';});}));test('shared context of any type', t => promiseEnd(new Runner({file: import.meta.url}), runner => {runner.on('stateChange', evt => {if (evt.type === 'hook-failed' || evt.type === 'test-failed') {t.fail();}});runner.chain.beforeEach(a => {a.context = 'foo';});runner.chain('test', a => {a.pass();a.is(a.context, 'foo');});}));test('teardowns cannot be used in hooks', async t => {let hookFailure = null;await promiseEnd(new Runner({file: import.meta.url}), runner => {runner.on('stateChange', evt => {if (evt.type === 'hook-failed') {hookFailure = evt;}});runner.chain.beforeEach(a => {a.teardown(() => {});});runner.chain('test', a => a.pass());});t.ok(hookFailure);t.match(hookFailure.err.message, /not allowed in hooks/);});