diff --git a/test/runner/fixturesUI.js b/test/runner/fixturesUI.js index 51d82c942688d..73c03eb8360f5 100644 --- a/test/runner/fixturesUI.js +++ b/test/runner/fixturesUI.js @@ -29,39 +29,90 @@ process.env.JEST_WORKER_ID = 1; const fixturePool = new FixturePool(); let revertBabelRequire; +function specBuilder(modifiers, specCallback) { + function builder(specs, last) { + const callable = (...args) => { + if (!last || (typeof args[0] === 'string' && typeof args[1] === 'function')) { + // Looks like a body (either it or describe). Assume that last modifier is true. + const newSpecs = { ...specs }; + if (last) + newSpecs[last] = [true]; + return specCallback(newSpecs, ...args); + } + const newSpecs = { ...specs }; + newSpecs[last] = args; + return builder(newSpecs, null); + }; + return new Proxy(callable, { + get: (obj, prop) => { + if (typeof prop === 'string' && modifiers.includes(prop)) { + const newSpecs = { ...specs }; + // Modifier was not called, assume true. + if (last) + newSpecs[last] = [true]; + return builder(newSpecs, prop); + } + return obj[prop]; + }, + }); + } + return builder({}, null); +} + function fixturesUI(trialRun, suite) { const suites = [suite]; suite.on(Suite.constants.EVENT_FILE_PRE_REQUIRE, function(context, file, mocha) { const common = commonSuite(suites, context, mocha); - const itBuilder = (markers) => { - return function(title, fn) { - const suite = suites[0]; - if (suite.isPending()) - fn = null; - let wrapper; - if (trialRun) { - if (fn) - wrapper = () => {}; - } else { - const wrapped = fixturePool.wrapTestCallback(fn); - wrapper = wrapped ? (done, ...args) => { - wrapped(...args).then(done).catch(done); - } : undefined; - } - if (wrapper) { - wrapper.toString = () => fn.toString(); - wrapper.__original = fn; - } - const test = new Test(title, wrapper); - if (markers && markers.includes('slow')) - test.timeout(90000); - test.file = file; - suite.addTest(test); - return test; - }; - }; + const it = specBuilder(['skip', 'fail', 'slow', 'only'], (specs, title, fn) => { + const suite = suites[0]; + if (suite.isPending()) + fn = null; + let wrapper; + if (trialRun) { + if (fn) + wrapper = () => {}; + } else { + const wrapped = fixturePool.wrapTestCallback(fn); + wrapper = wrapped ? (done, ...args) => { + wrapped(...args).then(done).catch(done); + } : undefined; + } + if (wrapper) { + wrapper.toString = () => fn.toString(); + wrapper.__original = fn; + } + const test = new Test(title, wrapper); + test.file = file; + suite.addTest(test); + const only = specs.only && specs.only[0]; + if (specs.slow && specs.slow[0]) + test.timeout(90000); + if (only) + test.markOnly(); + if (!only && specs.skip && specs.skip[0]) + test.pending = true; + if (!only && specs.fail && specs.fail[0]) + test.pending = true; + return test; + }); + + const describe = specBuilder(['skip', 'fail', 'only'], (specs, title, fn) => { + const suite = common.suite.create({ + title: title, + file: file, + fn: fn + }); + const only = specs.only && specs.only[0]; + if (only) + suite.markOnly(); + if (!only && specs.skip && specs.skip[0]) + suite.pending = true; + if (!only && specs.fail && specs.fail[0]) + suite.pending = true; + return suite; + }); context.beforeEach = common.beforeEach; context.afterEach = common.afterEach; @@ -77,52 +128,12 @@ function fixturesUI(trialRun, suite) { context.run = mocha.options.delay && common.runWithSuite(suite); - context.describe = (title, fn) => { - return common.suite.create({ - title: title, - file: file, - fn: fn - }); - }; - context.xdescribe = (title, fn) => { - return common.suite.skip({ - title: title, - file: file, - fn: fn - }); - }; - context.describe.skip = function(condition) { - return condition ? context.xdescribe : context.describe; - }; - context.describe.only = (title, fn) => { - return common.suite.only({ - title: title, - file: file, - fn: fn - }); - }; - - context.fdescribe = context.describe.only; - - context.it = itBuilder(); - context.it.only = function(title, fn) { - return common.test.only(mocha, context.it(title, fn)); - }; - context.fit = context.it.only; - context.xit = function(title) { - return context.it(title); - }; - context.it.skip = function(condition) { - return condition ? context.xit : context.it; - }; - context.it.fail = function(condition) { - return condition ? context.xit : context.it; - }; - context.it.slow = () => itBuilder(['slow']); - context.xit.slow = () => context.xit; - context.it.retries = function(n) { - context.retries(n); - }; + context.describe = describe; + context.fdescribe = describe.only(true); + context.xdescribe = describe.skip(true); + context.it = it; + context.fit = it.only(true); + context.xit = it.skip(true); revertBabelRequire = pirates.addHook((code, filename) => { const result = babel.transformFileSync(filename, {