Skip to content

Commit

Permalink
Reporter: Recognise "Todo" tests from QUnit
Browse files Browse the repository at this point in the history
This wasn't previously done because versions that support this feature
also have a jsreporters-compatible event emitter built-in, but this
isn't always used (such as in browserstack-runner). So for completion
support it here as well just in case.

Ref qunitjs/qunit#1622.
  • Loading branch information
Krinkle committed Jun 6, 2021
1 parent 9c6d364 commit 83bce59
Show file tree
Hide file tree
Showing 5 changed files with 340 additions and 95 deletions.
11 changes: 8 additions & 3 deletions lib/adapters/QUnitAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -170,10 +170,15 @@ module.exports = class QUnitAdapter extends EventEmitter {
onTestDone (details) {
const testEnd = this.testEnds[details.testId];

if (details.failed > 0) {
testEnd.status = 'failed';
} else if (details.skipped) {
// Handle todo status
const netFailure = (details.failed > 0 && !details.todo) || (details.failed === 0 && details.todo);

if (details.skipped) {
testEnd.status = 'skipped';
} else if (netFailure) {
testEnd.status = 'failed';
} else if (details.todo) {
testEnd.status = 'todo';
} else {
testEnd.status = 'passed';
}
Expand Down
22 changes: 22 additions & 0 deletions test/fixtures/integration/qunit-todo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/* global QUnit */

QUnit.test('global pass', function (assert) {
assert.ok(true);
});

QUnit.todo('global todo', function (assert) {
assert.ok(false);
});

QUnit.module('suite with a todo test');
QUnit.test('should pass', function (assert) {
assert.ok(true);
});
QUnit.todo('should todo', function (assert) {
assert.ok(false);
});

QUnit.module.todo('todo suite');
QUnit.test('should todo', function (assert) {
assert.ok(false);
});
17 changes: 16 additions & 1 deletion test/integration/adapters-run.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ function rerequire (file) {
* Exports a function for each adapter that will run
* against a default test fixture.
*/
module.exports = {
module.exports.main = {
Jasmine: function (collectData) {
const Jasmine = rerequire('jasmine');
const jasmine = new Jasmine();
Expand Down Expand Up @@ -90,3 +90,18 @@ module.exports = {
mocha.run();
}
};

module.exports.todo = {
QUnit: function (collectData) {
const QUnit = rerequire('qunit');
global.QUnit = QUnit;
QUnit.config.autorun = false;

const qunitRunner = new JsReporters.QUnitAdapter(QUnit);
collectData(qunitRunner);

rerequire(path.join(testDir, 'qunit-todo.js'));

QUnit.start();
}
};
191 changes: 100 additions & 91 deletions test/integration/adapters.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,118 +94,127 @@ function fixExpectedData (adapter, expectedData) {
});
}

QUnit.module('Adapters integration', function () {
Object.keys(runAdapters).forEach(function (adapter) {
QUnit.module(adapter + ' adapter', hooks => {
// Re-require for each adapter because we change the expected data.
const expectedData = rerequire('./reference-data.js');
fixExpectedData(adapter, expectedData);

const collectedData = [];

hooks.before(assert => {
const done = assert.async();
runAdapters[adapter](
collectDataFromRunner.bind(null, collectedData, done)
);
});

// Fist check that, overall, all expected events were emitted and in order.
test('Emitted events names', assert => {
assert.propEqual(
collectedData.map(pair => pair[0]),
expectedData.map(pair => pair[0]),
'Event names'
);
});

test('Event "testStart" data', assert => {
const actuals = collectedData.filter(pair => pair[0] === 'testStart');
const expecteds = expectedData.filter(pair => pair[0] === 'testStart');
assert.propEqual(
actuals.map(expected => expected[1].name),
expecteds.map(pair => pair[1].name),
'Test names'
);
expecteds.forEach((expected, i) => {
assert.propEqual(
actuals[i][1],
expected[1],
`Event data for testStart#${i}`
const integrations = [
{ key: 'main', name: 'Adapters main integration', referenceFile: './reference-data.js' },

// This is only implemented by QUnit currently
{ key: 'todo', name: 'Adapters todo integration', referenceFile: './reference-data-todo.js' }
];

integrations.forEach(function (integration) {
QUnit.module(integration.name, function () {
Object.keys(runAdapters[integration.key]).forEach(function (adapter) {
QUnit.module(adapter + ' adapter', hooks => {
// Re-require for each adapter because we mutate the expected data.
const expectedData = rerequire(integration.referenceFile);
fixExpectedData(adapter, expectedData);

const collectedData = [];

hooks.before(assert => {
const done = assert.async();
runAdapters[integration.key][adapter](
collectDataFromRunner.bind(null, collectedData, done)
);
});
});

test('Event "testEnd" data', assert => {
const actuals = collectedData.filter(pair => pair[0] === 'testEnd');
const expecteds = expectedData.filter(pair => pair[0] === 'testEnd');
assert.propEqual(
actuals.map(expected => expected[1].name),
expecteds.map(pair => pair[1].name),
'Test names'
);
expecteds.forEach((expected, i) => {
// Fist check that, overall, all expected events were emitted and in order.
test('Emitted events names', assert => {
assert.propEqual(
actuals[i][1],
expected[1],
`Event data for testEnd#${i}`
collectedData.map(pair => pair[0]),
expectedData.map(pair => pair[0]),
'Event names'
);
});
});

test('Event "suiteStart" data', assert => {
const actuals = collectedData.filter(pair => pair[0] === 'suiteStart');
const expecteds = expectedData.filter(pair => pair[0] === 'suiteStart');
assert.propEqual(
actuals.map(expected => expected[1].name),
expecteds.map(pair => pair[1].name),
'Suite names'
);
expecteds.forEach((expected, i) => {
test('Event "testStart" data', assert => {
const actuals = collectedData.filter(pair => pair[0] === 'testStart');
const expecteds = expectedData.filter(pair => pair[0] === 'testStart');
assert.propEqual(
actuals[i][1],
expected[1],
`Event data for suiteStart#${i}`
actuals.map(expected => expected[1].name),
expecteds.map(pair => pair[1].name),
'Test names'
);
expecteds.forEach((expected, i) => {
assert.propEqual(
actuals[i][1],
expected[1],
`Event data for testStart#${i}`
);
});
});
});

test('Event "suiteEnd" data', assert => {
const actuals = collectedData.filter(pair => pair[0] === 'suiteEnd');
const expecteds = expectedData.filter(pair => pair[0] === 'suiteEnd');
assert.propEqual(
actuals.map(expected => expected[1].name),
expecteds.map(pair => pair[1].name),
'Suite names'
);
expecteds.forEach((expected, i) => {
test('Event "testEnd" data', assert => {
const actuals = collectedData.filter(pair => pair[0] === 'testEnd');
const expecteds = expectedData.filter(pair => pair[0] === 'testEnd');
assert.propEqual(
actuals[i][1],
expected[1],
`Event data for suiteEnd#${i}`
actuals.map(expected => expected[1].name),
expecteds.map(pair => pair[1].name),
'Test names'
);
expecteds.forEach((expected, i) => {
assert.propEqual(
actuals[i][1],
expected[1],
`Event data for testEnd#${i}`
);
});
});
});

test('Event "runStart" data', assert => {
const actuals = collectedData.filter(pair => pair[0] === 'runStart');
expectedData.filter(pair => pair[0] === 'runStart').forEach((expected, i) => {
test('Event "suiteStart" data', assert => {
const actuals = collectedData.filter(pair => pair[0] === 'suiteStart');
const expecteds = expectedData.filter(pair => pair[0] === 'suiteStart');
assert.propEqual(
actuals[i][1],
expected[1],
`Event data for runStart#${i}`
actuals.map(expected => expected[1].name),
expecteds.map(pair => pair[1].name),
'Suite names'
);
expecteds.forEach((expected, i) => {
assert.propEqual(
actuals[i][1],
expected[1],
`Event data for suiteStart#${i}`
);
});
});
});

test('Event "runEnd" data', assert => {
const actuals = collectedData.filter(pair => pair[0] === 'runEnd');
expectedData.filter(pair => pair[0] === 'runEnd').forEach((expected, i) => {
test('Event "suiteEnd" data', assert => {
const actuals = collectedData.filter(pair => pair[0] === 'suiteEnd');
const expecteds = expectedData.filter(pair => pair[0] === 'suiteEnd');
assert.propEqual(
actuals[i][1],
expected[1],
`Event data for runEnd#${i}`
actuals.map(expected => expected[1].name),
expecteds.map(pair => pair[1].name),
'Suite names'
);
expecteds.forEach((expected, i) => {
assert.propEqual(
actuals[i][1],
expected[1],
`Event data for suiteEnd#${i}`
);
});
});

test('Event "runStart" data', assert => {
const actuals = collectedData.filter(pair => pair[0] === 'runStart');
expectedData.filter(pair => pair[0] === 'runStart').forEach((expected, i) => {
assert.propEqual(
actuals[i][1],
expected[1],
`Event data for runStart#${i}`
);
});
});

test('Event "runEnd" data', assert => {
const actuals = collectedData.filter(pair => pair[0] === 'runEnd');
expectedData.filter(pair => pair[0] === 'runEnd').forEach((expected, i) => {
assert.propEqual(
actuals[i][1],
expected[1],
`Event data for runEnd#${i}`
);
});
});
});
});
Expand Down
Loading

0 comments on commit 83bce59

Please sign in to comment.