diff --git a/src/core/config.js b/src/core/config.js index 1d3d7e54d..9112f7eeb 100644 --- a/src/core/config.js +++ b/src/core/config.js @@ -131,6 +131,8 @@ const config = { // started: 0, // Internal state + _event_listeners: Object.create(null), + _event_memory: {}, _deprecated_timeout_shown: false, _deprecated_countEachStep_shown: false, blocking: true, diff --git a/src/events.js b/src/events.js index 7a84f395d..5be7b5327 100644 --- a/src/events.js +++ b/src/events.js @@ -1,6 +1,6 @@ import { inArray } from './core/utilities'; +import config from './core/config'; -const LISTENERS = Object.create(null); const SUPPORTED_EVENTS = [ 'error', 'runStart', @@ -11,6 +11,9 @@ const SUPPORTED_EVENTS = [ 'suiteEnd', 'runEnd' ]; +const MEMORY_EVENTS = [ + 'runEnd' +]; /** * Emits an event with the specified data to all currently registered listeners. @@ -30,12 +33,16 @@ export function emit (eventName, data) { } // Clone the callbacks in case one of them registers a new callback - const originalCallbacks = LISTENERS[eventName]; + const originalCallbacks = config._event_listeners[eventName]; const callbacks = originalCallbacks ? [...originalCallbacks] : []; for (let i = 0; i < callbacks.length; i++) { callbacks[i](data); } + + if (inArray(MEMORY_EVENTS, eventName)) { + config._event_memory[eventName] = data; + } } /** @@ -57,12 +64,14 @@ export function on (eventName, callback) { throw new TypeError('callback must be a function when registering a listener'); } - if (!LISTENERS[eventName]) { - LISTENERS[eventName] = []; - } + const listeners = config._event_listeners[eventName] || (config._event_listeners[eventName] = []); // Don't register the same callback more than once - if (!inArray(callback, LISTENERS[eventName])) { - LISTENERS[eventName].push(callback); + if (!inArray(callback, listeners)) { + listeners.push(callback); + + if (config._event_memory[eventName] !== undefined) { + callback(config._event_memory[eventName]); + } } } diff --git a/test/cli/fixtures/event-runEnd-memory.js b/test/cli/fixtures/event-runEnd-memory.js new file mode 100644 index 000000000..9e4fb1f61 --- /dev/null +++ b/test/cli/fixtures/event-runEnd-memory.js @@ -0,0 +1,23 @@ +QUnit.on('runEnd', function (run) { + console.log(`# early runEnd total=${run.testCounts.total} passed=${run.testCounts.passed} failed=${run.testCounts.failed}`); + setTimeout(function () { + QUnit.on('runEnd', function (run) { + console.log(`# late runEnd total=${run.testCounts.total} passed=${run.testCounts.passed} failed=${run.testCounts.failed}`); + }); + }); +}); + +QUnit.module('First', function () { + QUnit.test('A', function (assert) { + assert.true(true); + }); + QUnit.test('B', function (assert) { + assert.true(false); + }); +}); + +QUnit.module('Second', function () { + QUnit.test('C', function (assert) { + assert.true(true); + }); +}); diff --git a/test/cli/fixtures/event-runEnd-memory.tap.txt b/test/cli/fixtures/event-runEnd-memory.tap.txt new file mode 100644 index 000000000..79e980f26 --- /dev/null +++ b/test/cli/fixtures/event-runEnd-memory.tap.txt @@ -0,0 +1,23 @@ +# command: ["qunit", "event-runEnd-memory.js"] + +TAP version 13 +ok 1 First > A +not ok 2 First > B + --- + message: failed + severity: failed + actual : false + expected: true + stack: | + at /qunit/test/cli/fixtures/event-runEnd-memory.js:15:16 + ... +ok 3 Second > C +1..3 +# pass 2 +# skip 0 +# todo 0 +# fail 1 +# early runEnd total=3 passed=2 failed=1 +# late runEnd total=3 passed=2 failed=1 + +# exit code: 1