From ebf21028f21d8c40f6161032f1d1d0596cce0ecf Mon Sep 17 00:00:00 2001 From: Mathias Schreck Date: Fri, 31 Jul 2020 17:04:11 +0200 Subject: [PATCH] Extract library to deal with mocha function names --- .eslintrc.json | 3 +- lib/util/ast.js | 14 +-- lib/util/names.js | 77 ++++++++++++ test/util/namesSpec.js | 257 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 340 insertions(+), 11 deletions(-) create mode 100644 lib/util/names.js create mode 100644 test/util/namesSpec.js diff --git a/.eslintrc.json b/.eslintrc.json index a644354..ede75d7 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -20,7 +20,8 @@ "files": [ "test/**/*.js", "benchmarks/**/*.js" ], "env": { "mocha": true }, "rules": { - "max-nested-callbacks": [ "error", 8 ] + "max-nested-callbacks": [ "error", 8 ], + "max-statements": [ "error", 30 ] } } ] diff --git a/lib/util/ast.js b/lib/util/ast.js index 85db2c1..f58f171 100644 --- a/lib/util/ast.js +++ b/lib/util/ast.js @@ -6,25 +6,16 @@ const isNil = require('ramda/src/isNil'); const propEq = require('ramda/src/propEq'); const pathEq = require('ramda/src/pathEq'); const find = require('ramda/src/find'); +const { getTestCaseNames, getSuiteNames } = require('./names'); const isDefined = complement(isNil); const isCallExpression = both(isDefined, propEq('type', 'CallExpression')); -const describeAliases = [ - 'describe', 'xdescribe', 'describe.only', 'describe.skip', - 'context', 'xcontext', 'context.only', 'context.skip', - 'suite', 'xsuite', 'suite.only', 'suite.skip' -]; const hooks = [ 'before', 'after', 'beforeEach', 'afterEach', 'beforeAll', 'afterAll', 'setup', 'teardown', 'suiteSetup', 'suiteTeardown' ]; const suiteConfig = [ 'timeout', 'slow', 'retries' ]; -const testCaseNames = [ - 'it', 'it.only', 'it.skip', 'xit', - 'test', 'test.only', 'test.skip', - 'specify', 'specify.only', 'specify.skip', 'xspecify' -]; function getPropertyName(property) { return property.name || property.value; @@ -38,6 +29,8 @@ function getNodeName(node) { } function isDescribe(node, additionalSuiteNames = []) { + const describeAliases = getSuiteNames({ modifiers: [ 'skip', 'only' ] }); + return isCallExpression(node) && describeAliases.concat(additionalSuiteNames).indexOf(getNodeName(node.callee)) > -1; } @@ -53,6 +46,7 @@ function isHookCall(node) { } function isTestCase(node) { + const testCaseNames = getTestCaseNames({ modifiers: [ 'skip', 'only' ] }); return isCallExpression(node) && testCaseNames.indexOf(getNodeName(node.callee)) > -1; } diff --git a/lib/util/names.js b/lib/util/names.js new file mode 100644 index 0000000..1b41f27 --- /dev/null +++ b/lib/util/names.js @@ -0,0 +1,77 @@ +'use strict'; + +const chain = require('ramda/src/chain'); + +const suiteNames = [ + 'describe', + 'context', + 'suite' +]; + +const suiteModifiers = { + skip: [ + 'describe.skip', + 'context.skip', + 'suite.skip', + 'xdescribe', + 'xcontext', + 'xsuite' + ], + only: [ + 'describe.only', + 'context.only', + 'suite.only' + ] +}; + +const testCaseNames = [ + 'it', + 'test', + 'specify' +]; + +const testCaseModifiers = { + skip: [ + 'it.skip', + 'test.skip', + 'specify.skip', + 'xit', + 'xspecify' + ], + only: [ + 'it.only', + 'test.only', + 'specify.only' + ] +}; + +function getTestCaseNames(options = {}) { + const { modifiers = [], baseNames = true } = options; + const names = baseNames ? testCaseNames : []; + + return names.concat(chain((modifierName) => { + if (testCaseModifiers[modifierName]) { + return testCaseModifiers[modifierName]; + } + + return []; + }, modifiers)); +} + +function getSuiteNames(options = {}) { + const { modifiers = [], baseNames = true, additionalSuiteNames = [] } = options; + const names = baseNames ? suiteNames.concat(additionalSuiteNames) : []; + + return names.concat(chain((modifierName) => { + if (suiteModifiers[modifierName]) { + return suiteModifiers[modifierName]; + } + + return []; + }, modifiers)); +} + +module.exports = { + getTestCaseNames, + getSuiteNames +}; diff --git a/test/util/namesSpec.js b/test/util/namesSpec.js new file mode 100644 index 0000000..545c01c --- /dev/null +++ b/test/util/namesSpec.js @@ -0,0 +1,257 @@ +'use strict'; + +const { expect } = require('chai'); +const { getTestCaseNames, getSuiteNames } = require('../../lib/util/names'); + +describe('mocha names', () => { + describe('test case names', () => { + it('returns the list of basic test case names when no options are provided', () => { + const testCaseNames = getTestCaseNames(); + + expect(testCaseNames).to.deep.equal([ + 'it', + 'test', + 'specify' + ]); + }); + + it('returns an empty list when no modifiers and no base names are wanted', () => { + const testCaseNames = getTestCaseNames({ baseNames: false }); + + expect(testCaseNames).to.deep.equal([]); + }); + + it('always returns a new array', () => { + const testCaseNames1 = getTestCaseNames({ baseNames: false }); + const testCaseNames2 = getTestCaseNames({ baseNames: false }); + + expect(testCaseNames1).to.deep.equal(testCaseNames2); + expect(testCaseNames1).to.not.equal(testCaseNames2); + }); + + it('ignores invalid modifiers', () => { + const testCaseNames = getTestCaseNames({ modifiers: [ 'foo' ], baseNames: false }); + + expect(testCaseNames).to.deep.equal([]); + }); + + it('returns the list of test case names with and without "skip" modifiers applied', () => { + const testCaseNames = getTestCaseNames({ modifiers: [ 'skip' ] }); + + expect(testCaseNames).to.deep.equal([ + 'it', + 'test', + 'specify', + 'it.skip', + 'test.skip', + 'specify.skip', + 'xit', + 'xspecify' + ]); + }); + + it('returns the list of test case names only with "skip" modifiers applied', () => { + const testCaseNames = getTestCaseNames({ modifiers: [ 'skip' ], baseNames: false }); + + expect(testCaseNames).to.deep.equal([ + 'it.skip', + 'test.skip', + 'specify.skip', + 'xit', + 'xspecify' + ]); + }); + + it('returns the list of test case names with and without "only" modifiers applied', () => { + const testCaseNames = getTestCaseNames({ modifiers: [ 'only' ] }); + + expect(testCaseNames).to.deep.equal([ + 'it', + 'test', + 'specify', + 'it.only', + 'test.only', + 'specify.only' + ]); + }); + + it('returns the list of test case names only with "only" modifiers applied', () => { + const testCaseNames = getTestCaseNames({ modifiers: [ 'only' ], baseNames: false }); + + expect(testCaseNames).to.deep.equal([ + 'it.only', + 'test.only', + 'specify.only' + ]); + }); + + it('returns the list of all test case names', () => { + const testCaseNames = getTestCaseNames({ modifiers: [ 'skip', 'only' ] }); + + expect(testCaseNames).to.deep.equal([ + 'it', + 'test', + 'specify', + 'it.skip', + 'test.skip', + 'specify.skip', + 'xit', + 'xspecify', + 'it.only', + 'test.only', + 'specify.only' + ]); + }); + + it('returns the list of test case names only with modifiers applied', () => { + const testCaseNames = getTestCaseNames({ modifiers: [ 'skip', 'only' ], baseNames: false }); + + expect(testCaseNames).to.deep.equal([ + 'it.skip', + 'test.skip', + 'specify.skip', + 'xit', + 'xspecify', + 'it.only', + 'test.only', + 'specify.only' + ]); + }); + }); + + describe('suite names', () => { + it('returns the list of basic suite names when no options are provided', () => { + const suiteNames = getSuiteNames(); + + expect(suiteNames).to.deep.equal([ + 'describe', + 'context', + 'suite' + ]); + }); + + it('returns an empty list when no modifiers and no base names are wanted', () => { + const suiteNames = getSuiteNames({ baseNames: false }); + + expect(suiteNames).to.deep.equal([]); + }); + + it('always returns a new array', () => { + const suiteNames1 = getSuiteNames({ baseNames: false }); + const suiteNames2 = getSuiteNames({ baseNames: false }); + + expect(suiteNames1).to.deep.equal(suiteNames2); + expect(suiteNames1).to.not.equal(suiteNames2); + }); + + it('ignores invalid modifiers', () => { + const suiteNames = getSuiteNames({ modifiers: [ 'foo' ], baseNames: false }); + + expect(suiteNames).to.deep.equal([]); + }); + + it('returns the list of suite names with and without "skip" modifiers applied', () => { + const suiteNames = getSuiteNames({ modifiers: [ 'skip' ] }); + + expect(suiteNames).to.deep.equal([ + 'describe', + 'context', + 'suite', + 'describe.skip', + 'context.skip', + 'suite.skip', + 'xdescribe', + 'xcontext', + 'xsuite' + ]); + }); + + it('returns the list of suite names only with "skip" modifiers applied', () => { + const suiteNames = getSuiteNames({ modifiers: [ 'skip' ], baseNames: false }); + + expect(suiteNames).to.deep.equal([ + 'describe.skip', + 'context.skip', + 'suite.skip', + 'xdescribe', + 'xcontext', + 'xsuite' + ]); + }); + + it('returns the list of suite names with and without "only" modifiers applied', () => { + const suiteNames = getSuiteNames({ modifiers: [ 'only' ] }); + + expect(suiteNames).to.deep.equal([ + 'describe', + 'context', + 'suite', + 'describe.only', + 'context.only', + 'suite.only' + ]); + }); + + it('returns the list of suite names only with "only" modifiers applied', () => { + const suiteNames = getSuiteNames({ modifiers: [ 'only' ], baseNames: false }); + + expect(suiteNames).to.deep.equal([ + 'describe.only', + 'context.only', + 'suite.only' + ]); + }); + + it('returns the list of all suite names', () => { + const suiteNames = getSuiteNames({ modifiers: [ 'skip', 'only' ] }); + + expect(suiteNames).to.deep.equal([ + 'describe', + 'context', + 'suite', + 'describe.skip', + 'context.skip', + 'suite.skip', + 'xdescribe', + 'xcontext', + 'xsuite', + 'describe.only', + 'context.only', + 'suite.only' + ]); + }); + + it('returns the list of suite names names only with modifiers applied', () => { + const suiteNames = getSuiteNames({ modifiers: [ 'skip', 'only' ], baseNames: false }); + + expect(suiteNames).to.deep.equal([ + 'describe.skip', + 'context.skip', + 'suite.skip', + 'xdescribe', + 'xcontext', + 'xsuite', + 'describe.only', + 'context.only', + 'suite.only' + ]); + }); + + it('returns the additional suite names', () => { + const suiteNames = getSuiteNames({ additionalSuiteNames: [ 'myCustomDescribe' ] }); + + expect(suiteNames).to.deep.equal([ + 'describe', + 'context', + 'suite', + 'myCustomDescribe' + ]); + }); + + it('doesn’t return the additional suite names when base names shouldn’t be included', () => { + const suiteNames = getSuiteNames({ additionalSuiteNames: [ 'myCustomDescribe' ], baseNames: false }); + + expect(suiteNames).to.deep.equal([]); + }); + }); +});