UNPKG

2.34 kBJavaScriptView Raw
1import { vsprintf } from 'sprintf-js';
2
3module.exports = forEach;
4
5/**
6 * Defines Mocha test cases for each given parameter.
7 * @param {Array} parameters
8 * @param {function} defaultIt - The 'it' function used in this function.
9 * If omitted, 'it' in global name space is used.
10 * @return {Object} The object which has a method to define test cases.
11 */
12function forEach(parameters, defaultIt = global.it) {
13 const it = makeTestCaseDefiner(parameters, defaultIt);
14 it.skip = makeParameterizedSkip(parameters, defaultIt);
15 it.only = makeParameterizedOnly(parameters, defaultIt);
16 return { it };
17}
18
19/**
20 * Create a function which define parameterized tests
21 * to be ignored.
22 * @private
23 */
24function makeParameterizedSkip(parameters, defaultIt) {
25 return makeTestCaseDefiner(
26 parameters,
27 defaultIt ? defaultIt.skip : undefined
28 );
29}
30
31/**
32 * Create a function which define exclusive parameterized tests.
33 * @private
34 */
35function makeParameterizedOnly(parameters, defaultIt) {
36 return function(title, test) {
37 const it = makeTestCaseDefiner(parameters, defaultIt);
38 global.describe.only('', () => it(title, test));
39 };
40}
41
42/**
43 * Create a function which defines test cases for
44 * each given parameter.
45 * @private
46 */
47function makeTestCaseDefiner(parameters, it) {
48 return function defineTestCases(title, test) {
49 const makeTitle = (typeof title === 'function')
50 ? title
51 : (...args) => vsprintf(title, args);
52
53 const arrayParams = parameters.map(param => {
54 return Array.isArray(param) ? param : [param];
55 });
56
57 const isAsync = isAsyncTest(arrayParams, test);
58 arrayParams.forEach((param, index) => {
59 it(
60 makeTitle(...[...param, index]),
61 makeTestBody(param, test, isAsync)
62 );
63 });
64 };
65}
66
67/**
68 * Wrap a given test function and convert it to
69 * a function passed to the `it`.
70 * @private
71 */
72function makeTestBody(param, test, isAsync) {
73 if (isAsync) {
74 return function(done) {
75 test.apply(this, param.concat(done));
76 };
77 }
78 return function() {
79 test.apply(this, param);
80 };
81}
82
83/**
84 * Return true if the testBody seems to be async.
85 * @private
86 */
87function isAsyncTest(parameters, test) {
88 const nLongestParam = parameters.reduce((n, param) => {
89 return Math.max(n, param.length);
90 }, 0);
91 return nLongestParam < test.length;
92}