Skip to content
33 changes: 22 additions & 11 deletions src/runner/fixture-hook-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { getFixtureInfo } from '../utils/get-test-and-fixture-info';

interface FixtureState {
started: boolean;
runningFixtureBeforeHook: boolean;
testIsBlocked: boolean;
fixtureBeforeHookErr: null | Error;
pendingTestRunCount: number;
fixtureCtx: object;
Expand All @@ -24,11 +24,11 @@ export default class FixtureHookController {
private static _ensureFixtureMapItem (fixtureMap: Map<Fixture, FixtureState>, fixture: Fixture): void {
if (!fixtureMap.has(fixture)) {
const item = {
started: false,
runningFixtureBeforeHook: false,
fixtureBeforeHookErr: null,
pendingTestRunCount: 0,
fixtureCtx: Object.create(null),
started: false,
testIsBlocked: false,
fixtureBeforeHookErr: null,
pendingTestRunCount: 0,
fixtureCtx: Object.create(null),
};

fixtureMap.set(fixture, item);
Expand Down Expand Up @@ -58,24 +58,35 @@ export default class FixtureHookController {
public isTestBlocked (test: Test): boolean {
const item = this._getFixtureMapItem(test);

return !!item && item.runningFixtureBeforeHook;
return !!item && item.testIsBlocked;
}

public unblockTest (test: Test): void {
const item = this._getFixtureMapItem(test);

if (item)
item.testIsBlocked = false;
}

public blockTestIfNecessary (test: Test): void {
const fixture = test.fixture as Fixture;
const item = this._getFixtureMapItem(test);

if (item && (fixture.globalBeforeFn || fixture.beforeFn))
item.testIsBlocked = true;
}

private async _runFixtureBeforeHook (item: FixtureState, fn: Function, testRun: TestRun): Promise<boolean> {
if (!fn)
return true;

item.runningFixtureBeforeHook = true;

try {
await executeFnWithTimeout(fn, testRun.executionTimeout, item.fixtureCtx, getFixtureInfo(testRun));
}
catch (err) {
item.fixtureBeforeHookErr = processTestFnError(err);
}

item.runningFixtureBeforeHook = false;

return !item.fixtureBeforeHookErr;
}

Expand Down
4 changes: 4 additions & 0 deletions src/runner/test-run-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -270,11 +270,15 @@ export default class TestRunController extends AsyncEventEmitter {

await this._handleNativeAutomationMode(connection);

this._fixtureHookController.blockTestIfNecessary(this.test);

const testRun = await this._createTestRun(connection, startRunExecutionTime);

const hookOk = await this._testRunHook.runTestRunBeforeHookIfNecessary(testRun)
&& await this._fixtureHookController.runFixtureBeforeHookIfNecessary(testRun);

this._fixtureHookController.unblockTest(this.test);

if (this.test.skip || !hookOk) {
await this._emitTestRunStart();
await this.emit('test-run-before-done');
Expand Down
21 changes: 18 additions & 3 deletions test/functional/fixtures/concurrency/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ if (config.useLocalBrowsers) {
return path.join(__dirname, file);
}

function run (browsers, concurrency, files, reporter) {
function run (browsers, concurrency, files, reporter, hooks) {
let src = null;

reporter = reporter || 'json';
Expand All @@ -35,14 +35,16 @@ if (config.useLocalBrowsers) {
write: function (newData) {
data += newData;
},

end: function (newData) {
data += newData;
},
})
.browsers(browsers)
.concurrency(concurrency)
.run({ disableNativeAutomation: !config.nativeAutomation });
.run({
disableNativeAutomation: !config.nativeAutomation,
hooks,
});
}

function createConnections (count) {
Expand Down Expand Up @@ -112,6 +114,19 @@ if (config.useLocalBrowsers) {
});
});

it('Should run tests concurrently after fixture before hook', function () {
return run('chrome:headless --no-sandbox', 5, './testcafe-fixtures/concurrent-fixture-before-test.js', 'json', {
testRun: {
before: async () => {
await new Promise(r => setTimeout(r, 3000));
},
},
})
.then(failedCount => {
expect(failedCount).eql(0);
});
});

it('Report TaskStart event handler should contain links to all opened browsers', async () => {
const concurrency = 2;
const scope = {};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { expect } from 'chai';


let beforeHookCallNumber = 0;

fixture('Concurrent fixture before hook')
.before(async () => {
await new Promise(r => setTimeout(r, 10000));
beforeHookCallNumber += 1;
})
.after(() => {
expect(beforeHookCallNumber).eql(1);
});

test('test1', async t => {
await t.expect(beforeHookCallNumber).eql(1);
});

test('test2', async t => {
await t.expect(beforeHookCallNumber).eql(1);
});

test('test3', async t => {
await t.expect(beforeHookCallNumber).eql(1);
});

test('test4', async t => {
await t.expect(beforeHookCallNumber).eql(1);
});

test('test5', async t => {
await t.expect(beforeHookCallNumber).eql(1);
});