diff --git a/test/runner/fixturesUI.js b/test/runner/fixturesUI.js index 0ef0f128136cb..d135d2163c2f7 100644 --- a/test/runner/fixturesUI.js +++ b/test/runner/fixturesUI.js @@ -80,7 +80,7 @@ function fixturesUI(wrappers, suite) { if (specs.slow && specs.slow[0]) test.timeout(90000); if (only) - test.markOnly(); + test.__only = true; if (!only && specs.skip && specs.skip[0]) test.pending = true; if (!only && specs.fail && specs.fail[0]) @@ -96,7 +96,7 @@ function fixturesUI(wrappers, suite) { }); const only = wrappers.ignoreOnly ? false : specs.only && specs.only[0]; if (only) - suite.markOnly(); + suite.__only = true; if (!only && specs.skip && specs.skip[0]) suite.pending = true; if (!only && specs.fail && specs.fail[0]) diff --git a/test/runner/index.js b/test/runner/index.js index ad42c1b8e7477..c85b960431c48 100644 --- a/test/runner/index.js +++ b/test/runner/index.js @@ -37,27 +37,27 @@ program const testDir = path.join(process.cwd(), command.args[0]); const files = collectFiles(testDir, '', command.args.slice(1)); - const testCollector = new TestCollector({ + const testCollector = new TestCollector(files, { forbidOnly: command.forbidOnly || undefined, grep: command.grep, timeout: command.timeout, }); - for (const file of files) - testCollector.addFile(file); - const rootSuite = testCollector.suite; + if (command.forbidOnly && testCollector.hasOnly()) { + console.error('====================================='); + console.error(' --forbid-only found a focused test.'); + console.error('====================================='); + process.exit(1); + } + const total = rootSuite.total(); if (!total) { console.error('================='); - console.error(' No tests found.'); + console.error(' no tests found.'); console.error('================='); process.exit(1); } - // Filter tests. - if (rootSuite.hasOnly()) - rootSuite.filterOnly(); - // Trial run does not need many workers, use one. const jobs = (command.trialRun || command.debug) ? 1 : command.jobs; const runner = new Runner(rootSuite, total, { diff --git a/test/runner/testCollector.js b/test/runner/testCollector.js index 9b9d151e0e9f4..5bffe48556744 100644 --- a/test/runner/testCollector.js +++ b/test/runner/testCollector.js @@ -24,7 +24,7 @@ global.testOptions = require('./testOptions'); class NullReporter {} class TestCollector { - constructor(options) { + constructor(files, options) { this._options = options; this.suite = new Mocha.Suite('', new Mocha.Context(), true); this._total = 0; @@ -32,9 +32,18 @@ class TestCollector { const match = options.grep.match(/^\/(.*)\/(g|i|)$|.*/); this._grep = new RegExp(match[1] || match[0], match[2]); } + + for (const file of files) + this._addFile(file); + + this._hasOnly = this._filterOnly(this.suite); } - addFile(file) { + hasOnly() { + return this._hasOnly; + } + + _addFile(file) { const mocha = new Mocha({ forbidOnly: this._options.forbidOnly, reporter: NullReporter, @@ -90,9 +99,6 @@ class TestCollector { } }); - if (mocha.suite.hasOnly()) - mocha.suite.filterOnly(); - // Clone the suite as many times as there are worker hashes. // Only include the tests that requested these generations. for (const [hash, {configurationObject, configurationString, tests}] of workerGeneratorConfigurations.entries()) { @@ -104,7 +110,7 @@ class TestCollector { _cloneSuite(suite, configurationObject, configurationString, tests) { const copy = suite.clone(); - copy.__configurationObject = configurationObject; + copy.__only = suite.__only; for (const child of suite.suites) copy.addSuite(this._cloneSuite(child, configurationObject, configurationString, tests)); for (const test of suite.tests) { @@ -113,23 +119,25 @@ class TestCollector { if (this._grep && !this._grep.test(test.fullTitle())) continue; const testCopy = test.clone(); + testCopy.__only = test.__only; testCopy.__ordinal = test.__ordinal; testCopy.__configurationObject = configurationObject; testCopy.__configurationString = configurationString; copy.addTest(testCopy); } return copy; - } -} - + } -function grepTotal(mocha, suite) { - let total = 0; - suite.eachTest(test => { - if (mocha.options.grep.test(test.fullTitle())) - total++; - }); - return total; + _filterOnly(suite) { + const onlySuites = suite.suites.filter(child => this._filterOnly(child) || child.__only); + const onlyTests = suite.tests.filter(test => test.__only); + if (onlySuites.length || onlyTests.length) { + suite.suites = onlySuites; + suite.tests = onlyTests; + return true; + } + return false; + } } module.exports = { TestCollector };