diff --git a/src/runner/browser-job.ts b/src/runner/browser-job.ts index 78d26e3615..41739a5faa 100644 --- a/src/runner/browser-job.ts +++ b/src/runner/browser-job.ts @@ -20,8 +20,10 @@ interface BrowserJobResultInfo { data?: any; // eslint-disable-line @typescript-eslint/no-explicit-any } +enum BrowserJobStatus { initialized, starting, started } + export default class BrowserJob extends AsyncEventEmitter { - private _started: boolean; + private _status: BrowserJobStatus; private _startTime: Date; private _total: number; private _passed: number; @@ -53,7 +55,7 @@ export default class BrowserJob extends AsyncEventEmitter { }: BrowserJobInit) { super(); - this._started = false; + this._status = BrowserJobStatus.initialized; this._startTime = new Date(); this._total = 0; @@ -170,6 +172,11 @@ export default class BrowserJob extends AsyncEventEmitter { } private async _isNextTestRunAvailable (testRunController: TestRunController): Promise { + // NOTE: event task start is currently executing, + // so test run is temporary blocked + if (this._status === BrowserJobStatus.starting) + return false; + // NOTE: before hook for test run fixture is currently // executing, so test run is temporary blocked const isBlocked = testRunController.blocked; @@ -213,11 +220,13 @@ export default class BrowserJob extends AsyncEventEmitter { this._testRunControllerQueue.shift(); this._addToCompletionQueue(testRunController); - if (!this._started) { - this._started = true; - this._startTime = new Date(); + if (this._status === BrowserJobStatus.initialized) { + this._status = BrowserJobStatus.starting; + this._startTime = new Date(); await this.emit('start', this._startTime); + + this._status = BrowserJobStatus.started; } const testRunUrl = await testRunController.start(connection, this._startTime); diff --git a/test/functional/fixtures/concurrency/test.js b/test/functional/fixtures/concurrency/test.js index 6f33876ced..be25606888 100644 --- a/test/functional/fixtures/concurrency/test.js +++ b/test/functional/fixtures/concurrency/test.js @@ -77,6 +77,17 @@ if (config.useLocalBrowsers) { }, }); + const slowReporter = createReporter({ + reportTaskStart: async function () { + await new Promise(resolve => setTimeout(() => resolve(), 100)); + this.write('Task start').newline(); + }, + + reportTestStart: async function () { + this.write('Test start').newline(); + }, + }); + beforeEach(function () { data = ''; }); @@ -138,6 +149,19 @@ if (config.useLocalBrowsers) { }); }); + it('Should not start any test before report task start finishes', function () { + return run('chrome:headless --no-sandbox', 2, './testcafe-fixtures/concurrent-test.js', slowReporter) + .then(failedCount => { + expect(failedCount).eql(0); + expect(data.split('\n')).eql([ + 'Task start', + 'Test start', + 'Test start', + '', + ]); + }); + }); + it('Should fail if number of remotes is not divisible by concurrency', function () { return createConnections(3) .then(function (connections) {