diff --git a/Gruntfile.js b/Gruntfile.js index 5caf03f9c..a3464832d 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -122,14 +122,12 @@ module.exports = function( grunt ) { "test/moduleId.html", "test/onerror/inside-test.html", "test/onerror/outside-test.html", - "test/only.html", "test/seed.html", "test/overload.html", "test/preconfigured.html", "test/regex-filter.html", "test/regex-exclude-filter.html", "test/string-filter.html", - "test/module-only.html", "test/module-skip.html", "test/module-todo.html", @@ -157,12 +155,15 @@ module.exports = function( grunt ) { "test/events-in-test.js", "test/onerror/inside-test.js", "test/onerror/outside-test.js", - "test/only.js", "test/setTimeout.js", "test/main/dump.js", "test/node/storage-1.js", "test/node/storage-2.js", + "test/cli/fixtures/only/test.js", + "test/cli/fixtures/only/module.js", + "test/cli/fixtures/only/module-flat.js", + // FIXME: These tests use an ugly hack that re-opens // an already finished test run. This only works reliably // via the HTML Reporter thanks to some delays in the bridge. @@ -174,7 +175,6 @@ module.exports = function( grunt ) { // // Ref https://github.com/qunitjs/qunit/issues/1511 // - // "test/module-only.js", // "test/module-skip.js", // "test/module-todo.js", "test/es2018/async-functions.js", diff --git a/src/module.js b/src/module.js index e669888d5..cfa21ff0a 100644 --- a/src/module.js +++ b/src/module.js @@ -5,8 +5,6 @@ import SuiteReport from "./reports/suite"; import { extend, objectType, generateHash } from "./core/utilities"; import { globalSuite } from "./core"; -let focused = false; - const moduleStack = []; function isParentModuleInQueue() { @@ -37,7 +35,8 @@ function createModule( name, testEnvironment, modifiers ) { // This property will be used to mark own tests and tests of child suites // as either `skipped` or `todo`. skip: skip, - todo: skip ? false : todo + todo: skip ? false : todo, + ignored: modifiers.ignored || false }; const env = {}; @@ -100,21 +99,22 @@ function processModule( name, options, executeNow, modifiers = {} ) { } } +let focused = false; // indicates that the "only" filter was used + export default function module( name, options, executeNow ) { - if ( focused && !isParentModuleInQueue() ) { - return; - } - processModule( name, options, executeNow ); + const ignored = focused && !isParentModuleInQueue(); + + processModule( name, options, executeNow, { ignored } ); } -module.only = function() { +module.only = function( ...args ) { if ( !focused ) { config.modules.length = 0; config.queue.length = 0; } - processModule( ...arguments ); + processModule( ...args ); focused = true; }; diff --git a/src/test.js b/src/test.js index 9008dbae7..8e038c59e 100644 --- a/src/test.js +++ b/src/test.js @@ -22,8 +22,6 @@ import ProcessingQueue from "./core/processing-queue"; import TestReport from "./reports/test"; -let focused = false; - export default function Test( settings ) { this.expected = null; this.assertions = []; @@ -679,9 +677,11 @@ function checkPollution() { } } +let focused = false; // indicates that the "only" filter was used + // Will be exposed as QUnit.test export function test( testName, callback ) { - if ( focused ) { + if ( focused || config.currentModule.ignored ) { return; } @@ -695,7 +695,7 @@ export function test( testName, callback ) { extend( test, { todo: function todo( testName, callback ) { - if ( focused ) { + if ( focused || config.currentModule.ignored ) { return; } @@ -708,7 +708,7 @@ extend( test, { newTest.queue(); }, skip: function skip( testName ) { - if ( focused ) { + if ( focused || config.currentModule.ignored ) { return; } @@ -720,6 +720,9 @@ extend( test, { test.queue(); }, only: function only( testName, callback ) { + if ( config.currentModule.ignored ) { + return; + } if ( !focused ) { config.queue.length = 0; focused = true; diff --git a/test/cli/fixtures/expected/tap-outputs.js b/test/cli/fixtures/expected/tap-outputs.js index 0e83481e5..b4c7d3794 100644 --- a/test/cli/fixtures/expected/tap-outputs.js +++ b/test/cli/fixtures/expected/tap-outputs.js @@ -282,5 +282,54 @@ ok 2 later thing > has released all foos # pass 2 # skip 0 # todo 0 +# fail 0`, + + "qunit only/test.js": +`TAP version 13 +ok 1 run this test +ok 2 all tests with only run +1..3 +# pass 3 +# skip 0 +# todo 0 +# fail 0`, + + "qunit only/module.js": +`TAP version 13 +not ok 1 # TODO module B > Only this module should run > a todo test + --- + message: "not implemented yet" + severity: todo + actual : false + expected: true + stack: .* + ... +ok 2 # SKIP module B > Only this module should run > implicitly skipped test +ok 3 module B > Only this module should run > normal test +ok 4 module D > test D +ok 5 module E > module F > test F +ok 6 module E > test E +1..8 +# pass 6 +# skip 1 +# todo 1 +# fail 0`, + + "qunit only/module-flat.js": +`TAP version 13 +not ok 1 # TODO module B > test B + --- + message: "not implemented yet" + severity: todo + actual : false + expected: true + stack: .* + ... +ok 2 # SKIP module B > test C +ok 3 module B > test D +1..4 +# pass 2 +# skip 1 +# todo 1 # fail 0` }; diff --git a/test/cli/fixtures/only/module-flat.js b/test/cli/fixtures/only/module-flat.js new file mode 100644 index 000000000..d292533f7 --- /dev/null +++ b/test/cli/fixtures/only/module-flat.js @@ -0,0 +1,27 @@ + +QUnit.module( "module A" ); +QUnit.test( "test A", function( assert ) { + assert.true( false, "this test should not run" ); +} ); + +QUnit.module.only( "module B" ); +QUnit.todo( "test B", function( assert ) { + assert.true( false, "not implemented yet" ); +} ); +QUnit.skip( "test C", function( assert ) { + assert.true( false, "test should be skipped" ); +} ); +QUnit.test( "test D", function( assert ) { + assert.true( true, "this test should run" ); +} ); + +QUnit.module( "module C" ); +QUnit.todo( "test E", function( assert ) { + assert.true( false, "not implemented yet" ); +} ); +QUnit.skip( "test F", function( assert ) { + assert.true( false, "test should be skipped" ); +} ); +QUnit.test( "test G", function( assert ) { + assert.true( false, "this test should not run" ); +} ); diff --git a/test/module-only.js b/test/cli/fixtures/only/module.js similarity index 73% rename from test/module-only.js rename to test/cli/fixtures/only/module.js index fa57147a7..cc218603b 100644 --- a/test/module-only.js +++ b/test/cli/fixtures/only/module.js @@ -1,56 +1,3 @@ -var tests = {}; - -var done = false; - -QUnit.testDone( function( details ) { - if ( done ) { - return; - } - - tests[ details.testId ] = { - skipped: details.skipped, - todo: details.todo - }; -} ); - -QUnit.done( function() { - if ( done ) { - return; - } - - done = true; - - QUnit.test( "Compare stats", function( assert ) { - assert.expect( 1 ); - - assert.deepEqual( tests, { - "1fb73641": { - skipped: false, - todo: true - }, - "5fe457c4": { - skipped: true, - todo: false - }, - "75e1bf3f": { - skipped: false, - todo: false - }, - "c7ae85c2": { - skipped: false, - todo: false - }, - "74b800d1": { - skipped: false, - todo: false - }, - "2f8fb2a2": { - skipped: false, - todo: false - } - } ); - } ); -} ); QUnit.module( "module A", function() { QUnit.test( "test A", function( assert ) { diff --git a/test/cli/fixtures/only/test.js b/test/cli/fixtures/only/test.js new file mode 100644 index 000000000..5bbd2029e --- /dev/null +++ b/test/cli/fixtures/only/test.js @@ -0,0 +1,15 @@ +QUnit.test( "implicitly skipped test", function( assert ) { + assert.true( false, "test should be skipped" ); +} ); + +QUnit.only( "run this test", function( assert ) { + assert.true( true, "only this test should run" ); +} ); + +QUnit.test( "another implicitly skipped test", function( assert ) { + assert.true( false, "test should be skipped" ); +} ); + +QUnit.only( "all tests with only run", function( assert ) { + assert.true( true, "this test should run as well" ); +} ); diff --git a/test/cli/main.js b/test/cli/main.js index bbbac9ef2..4b7a078fd 100644 --- a/test/cli/main.js +++ b/test/cli/main.js @@ -4,6 +4,15 @@ const expectedOutput = require( "./fixtures/expected/tap-outputs" ); const execute = require( "./helpers/execute" ); const semver = require( "semver" ); +QUnit.assert.matches = function( actual, expected, message ) { + this.pushResult( { + result: expected.test( actual ), + actual, + expected: expected.toString(), + message + } ); +}; + QUnit.module( "CLI Main", function() { QUnit.test( "defaults to running tests in 'test' directory", async function( assert ) { const command = "qunit"; @@ -295,4 +304,38 @@ QUnit.module( "CLI Main", function() { } } ); } ); + + QUnit.module( "only", function() { + QUnit.test( "test", async function( assert ) { + + const command = "qunit only/test.js"; + const execution = await execute( command ); + + assert.equal( execution.code, 0 ); + assert.equal( execution.stderr, "" ); + assert.equal( execution.stdout, expectedOutput[ command ] ); + } ); + + QUnit.test( "nested modules", async function( assert ) { + + const command = "qunit only/module.js"; + const execution = await execute( command ); + + assert.equal( execution.code, 0 ); + assert.equal( execution.stderr, "" ); + const re = new RegExp( expectedOutput[ command ] ); + assert.matches( execution.stdout, re ); + } ); + + QUnit.test( "flat modules", async function( assert ) { + + const command = "qunit only/module-flat.js"; + const execution = await execute( command ); + + assert.equal( execution.code, 0 ); + assert.equal( execution.stderr, "" ); + const re = new RegExp( expectedOutput[ command ] ); + assert.matches( execution.stdout, re ); + } ); + } ); } ); diff --git a/test/module-only.html b/test/module-only.html deleted file mode 100644 index afe447f14..000000000 --- a/test/module-only.html +++ /dev/null @@ -1,13 +0,0 @@ - - -
- -