-
Notifications
You must be signed in to change notification settings - Fork 8.3k
/
Copy pathread_jest_help.mjs
131 lines (114 loc) · 3.86 KB
/
read_jest_help.mjs
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
129
130
131
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import Fsp from 'fs/promises';
import Path from 'path';
import { createFailError } from '@kbn/dev-cli-errors';
import { run } from '@kbn/dev-cli-runner';
import { REPO_ROOT } from '@kbn/repo-info';
const FLAGS_FILE = 'packages/kbn-test/src/jest/jest_flags.json';
function readStdin() {
return new Promise((resolve, reject) => {
let buffer = '';
let timer = setTimeout(() => {
reject(
createFailError('you must pipe the output of `yarn jest --help` to this script', {
showHelp: true,
})
);
}, 1000);
process.stdin
.on('data', (chunk) => {
if (timer) {
clearTimeout(timer);
timer = undefined;
}
buffer += chunk;
})
.on('end', () => resolve(buffer))
.on('error', reject);
});
}
run(
async ({ log }) => {
const lines = (await readStdin()).split('\n');
/** @type {{ string: string[], boolean: string[], alias: Record<string, string> }} */
const flags = { string: [], boolean: [], alias: {} };
/** @type {string | undefined} */
let currentFlag;
for (const line of lines) {
const flagMatch = line.match(/^\s+(?:-(\w), )?--(\w+)\s+/);
const typeMatch = line.match(/\[(boolean|string|array|number|choices: [^\]]+)\]/);
if (flagMatch && currentFlag) {
throw createFailError(`unable to determine type for flag [${currentFlag}]`);
}
if (flagMatch) {
currentFlag = flagMatch[2];
if (flagMatch[1]) {
flags.alias[flagMatch[1]] = flagMatch[2];
}
}
if (currentFlag && typeMatch) {
switch (typeMatch[1]) {
case 'string':
case 'array':
case 'number':
flags.string.push(currentFlag);
break;
case 'boolean':
flags.boolean.push(currentFlag);
break;
default:
if (typeMatch[1].startsWith('choices: ')) {
flags.string.push(currentFlag);
break;
}
throw createFailError(`unexpected flag type [${typeMatch[1]}]`);
}
currentFlag = undefined;
}
}
await Fsp.writeFile(
Path.resolve(REPO_ROOT, FLAGS_FILE),
JSON.stringify(
{
string: flags.string.sort(function (a, b) {
return a.localeCompare(b);
}),
boolean: flags.boolean.sort(function (a, b) {
return a.localeCompare(b);
}),
alias: Object.fromEntries(
Object.entries(flags.alias).sort(function (a, b) {
return a[0].localeCompare(b[0]);
})
),
},
null,
2
)
);
log.success('wrote jest flag info to', FLAGS_FILE);
log.warning('make sure you bootstrap to rebuild @kbn/test');
},
{
usage: `yarn jest --help | node scripts/read_jest_help.mjs`,
description: `
Jest no longer exposes the ability to parse CLI flags externally, so we use this
script to read the help output and convert it into parameters we can pass to getopts()
which will parse the flags similar to how Jest does it.
getopts() doesn't support things like enums, or number flags, but if we use the generated
config then it will at least interpret which flags are expected, which are invalid, and
allow us to determine the correct config path based on the provided path while passing
the rest of the args directly to jest.
`,
flags: {
allowUnexpected: true,
guessTypesForUnexpectedFlags: false,
},
}
);