/
bind.ts
128 lines (115 loc) · 3.47 KB
/
bind.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
import {Global} from '@jest/types';
import {ErrorWithStack} from 'jest-util';
import convertArrayTable from './table/array';
import convertTemplateTable from './table/template';
import {validateArrayTable, validateTemplateTableHeadings} from './validation';
export type EachTests = Array<{
title: string;
arguments: Array<unknown>;
}>;
type GlobalCallback = (
testName: string,
fn: Global.TestFn,
timeout?: number,
) => void;
type GlobalCallbackConcurrent = (
testName: string,
fn: Global.ConcurrentTestFn,
timeout?: number,
) => void;
export default (cb: GlobalCallback, supportsDone: boolean = true) => (
table: Global.EachTable,
...taggedTemplateData: Global.TemplateData
) =>
function eachBind(
title: string,
test: Global.EachTestFn,
timeout?: number,
): void {
try {
const tests = isArrayTable(taggedTemplateData)
? buildArrayTests(title, table)
: buildTemplateTests(title, table, taggedTemplateData);
return tests.forEach(row =>
cb(
row.title,
applyArguments(supportsDone, row.arguments, test),
timeout,
),
);
} catch (e) {
const error = new ErrorWithStack(e.message, eachBind);
return cb(title, () => {
throw error;
});
}
};
export const bindConcurrent = (
cb: GlobalCallbackConcurrent,
supportsDone: boolean = true,
) => (table: Global.EachTable, ...taggedTemplateData: Global.TemplateData) =>
function eachBind(
title: string,
test: Global.ConcurrentEachTestFn,
timeout?: number,
): void {
try {
const tests = isArrayTable(taggedTemplateData)
? buildArrayTests(title, table)
: buildTemplateTests(title, table, taggedTemplateData);
return tests.forEach(row =>
cb(
row.title,
applyArguments(supportsDone, row.arguments, test),
timeout,
),
);
} catch (e) {
const error = new ErrorWithStack(e.message, eachBind);
return cb(title, () => {
throw error;
});
}
};
const isArrayTable = (data: Global.TemplateData) => data.length === 0;
const buildArrayTests = (title: string, table: Global.EachTable): EachTests => {
validateArrayTable(table);
return convertArrayTable(title, table as Global.ArrayTable);
};
const buildTemplateTests = (
title: string,
table: Global.EachTable,
taggedTemplateData: Global.TemplateData,
): EachTests => {
const headings = getHeadingKeys(table[0] as string);
validateTemplateTableHeadings(headings, taggedTemplateData);
return convertTemplateTable(title, headings, taggedTemplateData);
};
const getHeadingKeys = (headings: string): Array<string> =>
headings.replace(/\s/g, '').split('|');
function applyArguments(
supportsDone: boolean,
params: Array<unknown>,
test: Global.ConcurrentEachTestFn,
): Global.ConcurrentEachTestFn;
function applyArguments(
supportsDone: boolean,
params: Array<unknown>,
test: Global.EachTestFn,
): Global.EachTestFn;
function applyArguments(
supportsDone: boolean,
params: Array<unknown>,
test: Global.ConcurrentEachTestFn | Global.EachTestFn,
): Global.ConcurrentEachTestFn | Global.EachTestFn {
return supportsDone && params.length < test.length
? (done: Global.DoneFn) => test(...params, done)
: () => test(...params);
}