/
template.ts
72 lines (63 loc) · 1.98 KB
/
template.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
import pretty from 'pretty-format';
import {isPrimitive} from 'jest-get-type';
import {Global} from '@jest/types';
import {EachTests} from '../bind';
type Template = {[key: string]: unknown};
type Templates = Array<Template>;
type Headings = Array<string>;
export default (
title: string,
headings: Headings,
row: Global.Row,
): EachTests => {
const table = convertRowToTable(row, headings);
const templates = convertTableToTemplates(table, headings);
return templates.map(template => ({
arguments: [template],
title: interpolate(title, template),
}));
};
const convertRowToTable = (row: Global.Row, headings: Headings): Global.Table =>
Array.from({length: row.length / headings.length}).map((_, index) =>
row.slice(
index * headings.length,
index * headings.length + headings.length,
),
);
const convertTableToTemplates = (
table: Global.Table,
headings: Headings,
): Templates =>
table.map(row =>
row.reduce<Template>(
(acc, value, index) => Object.assign(acc, {[headings[index]]: value}),
{},
),
);
const interpolate = (title: string, template: Template) =>
Object.keys(template)
.reduce(getMatchingKeyPaths(title), []) // aka flatMap
.reduce(replaceKeyPathWithValue(template), title);
const getMatchingKeyPaths = (title: string) => (
matches: Headings,
key: string,
) => matches.concat(title.match(new RegExp(`\\$${key}[\\.\\w]*`, 'g')) || []);
const replaceKeyPathWithValue = (template: Template) => (
title: string,
match: string,
) => {
const keyPath = match.replace('$', '').split('.');
const value = getPath(template, keyPath);
if (isPrimitive(value)) {
return title.replace(match, String(value));
}
return title.replace(match, pretty(value, {maxDepth: 1, min: true}));
};
const getPath = (
template: Template | any,
[head, ...tail]: Array<string>,
): any => {
if (!head || !template.hasOwnProperty || !template.hasOwnProperty(head))
return template;
return getPath(template[head], tail);
};