@rstest/core 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +11 -0
- package/bin/rstest.js +20 -0
- package/dist/285.js +98 -0
- package/dist/353.js +488 -0
- package/dist/355.js +96 -0
- package/dist/629.js +80 -0
- package/dist/64.js +1735 -0
- package/dist/72.js +1309 -0
- package/dist/773.js +1709 -0
- package/dist/813.js +137 -0
- package/dist/973.js +482 -0
- package/dist/992.js +485 -0
- package/dist/cli.js +3685 -0
- package/dist/node.js +0 -0
- package/dist/public.js +4 -0
- package/dist/worker.js +5727 -0
- package/dist/worker.js.LICENSE.txt +28 -0
- package/dist-types/cli.d.ts +3 -0
- package/dist-types/node.d.ts +368 -0
- package/dist-types/public.d.ts +850 -0
- package/dist-types/worker.d.ts +646 -0
- package/globals.d.ts +13 -0
- package/importMeta.d.ts +3 -0
- package/package.json +85 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023-present Bytedance, Inc. and its affiliates.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<picture>
|
|
2
|
+
<img alt="Rstest Banner" src="https://assets.rspack.rs/rstest/rstest-banner.png">
|
|
3
|
+
</picture>
|
|
4
|
+
|
|
5
|
+
# Rstest
|
|
6
|
+
|
|
7
|
+
Rstest is a testing framework powered by Rspack.
|
|
8
|
+
|
|
9
|
+
## 📖 License
|
|
10
|
+
|
|
11
|
+
Rstest is licensed under the [MIT License](https://github.com/web-infra-dev/rstest/blob/main/LICENSE).
|
package/bin/rstest.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import nodeModule from 'node:module';
|
|
3
|
+
|
|
4
|
+
// enable on-disk code caching of all modules loaded by Node.js
|
|
5
|
+
// requires Nodejs >= 22.8.0
|
|
6
|
+
const { enableCompileCache } = nodeModule;
|
|
7
|
+
if (enableCompileCache) {
|
|
8
|
+
try {
|
|
9
|
+
enableCompileCache();
|
|
10
|
+
} catch {
|
|
11
|
+
// ignore errors
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async function main() {
|
|
16
|
+
const { runCLI } = await import('../dist/cli.js');
|
|
17
|
+
runCLI();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
main();
|
package/dist/285.js
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
export const __webpack_ids__ = [
|
|
2
|
+
"285"
|
|
3
|
+
];
|
|
4
|
+
export const __webpack_modules__ = {
|
|
5
|
+
"./src/core/listTests.ts": function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
6
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
7
|
+
listTests: ()=>listTests
|
|
8
|
+
});
|
|
9
|
+
var node_fs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("node:fs");
|
|
10
|
+
var node_path__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("node:path");
|
|
11
|
+
var _pool__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./src/pool/index.ts");
|
|
12
|
+
var _utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__("./src/utils/index.ts");
|
|
13
|
+
var _rsbuild__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__("./src/core/rsbuild.ts");
|
|
14
|
+
async function listTests(context, fileFilters, { filesOnly, json }) {
|
|
15
|
+
const { normalizedConfig: { include, exclude, root, name, setupFiles: setups, includeSource }, rootPath } = context;
|
|
16
|
+
const testEntries = await (0, _utils__WEBPACK_IMPORTED_MODULE_3__.GL)({
|
|
17
|
+
include,
|
|
18
|
+
exclude,
|
|
19
|
+
root,
|
|
20
|
+
fileFilters,
|
|
21
|
+
includeSource
|
|
22
|
+
});
|
|
23
|
+
const globTestSourceEntries = async ()=>testEntries;
|
|
24
|
+
const setupFiles = (0, _utils__WEBPACK_IMPORTED_MODULE_3__.aA)(setups, rootPath);
|
|
25
|
+
const rsbuildInstance = await (0, _rsbuild__WEBPACK_IMPORTED_MODULE_4__.z)(context, globTestSourceEntries, setupFiles);
|
|
26
|
+
const getRsbuildStats = await (0, _rsbuild__WEBPACK_IMPORTED_MODULE_4__.r)({
|
|
27
|
+
name,
|
|
28
|
+
globTestSourceEntries,
|
|
29
|
+
setupFiles,
|
|
30
|
+
rsbuildInstance,
|
|
31
|
+
rootPath
|
|
32
|
+
});
|
|
33
|
+
const { entries, setupEntries, assetFiles, sourceMaps, close, getSourcemap } = await getRsbuildStats();
|
|
34
|
+
const pool = await (0, _pool__WEBPACK_IMPORTED_MODULE_2__.K)({
|
|
35
|
+
entries,
|
|
36
|
+
sourceMaps,
|
|
37
|
+
setupEntries,
|
|
38
|
+
assetFiles,
|
|
39
|
+
context
|
|
40
|
+
});
|
|
41
|
+
const list = await pool.collectTests();
|
|
42
|
+
const tests = [];
|
|
43
|
+
const traverseTests = (test)=>{
|
|
44
|
+
if ([
|
|
45
|
+
'skip',
|
|
46
|
+
'todo'
|
|
47
|
+
].includes(test.runMode)) return;
|
|
48
|
+
if ('case' === test.type) tests.push({
|
|
49
|
+
file: test.testPath,
|
|
50
|
+
name: (0, _utils__WEBPACK_IMPORTED_MODULE_3__.Yz)(test)
|
|
51
|
+
});
|
|
52
|
+
else for (const child of test.tests)traverseTests(child);
|
|
53
|
+
};
|
|
54
|
+
const hasError = list.some((file)=>file.errors?.length);
|
|
55
|
+
if (hasError) {
|
|
56
|
+
const { printError } = await Promise.all([
|
|
57
|
+
__webpack_require__.e("973"),
|
|
58
|
+
__webpack_require__.e("355")
|
|
59
|
+
]).then(__webpack_require__.bind(__webpack_require__, "./src/utils/error.ts"));
|
|
60
|
+
process.exitCode = 1;
|
|
61
|
+
for (const file of list){
|
|
62
|
+
const relativePath = (0, node_path__WEBPACK_IMPORTED_MODULE_1__.relative)(rootPath, file.testPath);
|
|
63
|
+
if (file.errors?.length) {
|
|
64
|
+
_utils__WEBPACK_IMPORTED_MODULE_3__.kg.log(`${_utils__WEBPACK_IMPORTED_MODULE_3__.$_.bgRed(' FAIL ')} ${relativePath}`);
|
|
65
|
+
for (const error of file.errors)await printError(error, getSourcemap, rootPath);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
await close();
|
|
69
|
+
await pool.close();
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
for (const file of list){
|
|
73
|
+
if (filesOnly) {
|
|
74
|
+
tests.push({
|
|
75
|
+
file: file.testPath
|
|
76
|
+
});
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
for (const test of file.tests)traverseTests(test);
|
|
80
|
+
}
|
|
81
|
+
if (json && 'false' !== json) {
|
|
82
|
+
const content = JSON.stringify(tests, null, 2);
|
|
83
|
+
if (true !== json && 'true' !== json) {
|
|
84
|
+
const jsonPath = (0, node_path__WEBPACK_IMPORTED_MODULE_1__.isAbsolute)(json) ? json : (0, node_path__WEBPACK_IMPORTED_MODULE_1__.join)(rootPath, json);
|
|
85
|
+
(0, node_fs__WEBPACK_IMPORTED_MODULE_0__.mkdirSync)((0, node_path__WEBPACK_IMPORTED_MODULE_1__.dirname)(jsonPath), {
|
|
86
|
+
recursive: true
|
|
87
|
+
});
|
|
88
|
+
(0, node_fs__WEBPACK_IMPORTED_MODULE_0__.writeFileSync)(jsonPath, content);
|
|
89
|
+
} else _utils__WEBPACK_IMPORTED_MODULE_3__.kg.log(content);
|
|
90
|
+
} else for (const test of tests){
|
|
91
|
+
const shortPath = (0, node_path__WEBPACK_IMPORTED_MODULE_1__.relative)(rootPath, test.file);
|
|
92
|
+
_utils__WEBPACK_IMPORTED_MODULE_3__.kg.log(test.name ? `${_utils__WEBPACK_IMPORTED_MODULE_3__.$_.dim(`${shortPath} > `)}${test.name}` : (0, _utils__WEBPACK_IMPORTED_MODULE_3__.aj)(shortPath));
|
|
93
|
+
}
|
|
94
|
+
await close();
|
|
95
|
+
await pool.close();
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
};
|
package/dist/353.js
ADDED
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
export const __webpack_ids__ = [
|
|
2
|
+
"353"
|
|
3
|
+
];
|
|
4
|
+
export const __webpack_modules__ = {
|
|
5
|
+
"../../node_modules/.pnpm/stacktrace-parser@0.1.11/node_modules/stacktrace-parser/dist/stack-trace-parser.esm.js": function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
6
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
7
|
+
Q: ()=>parse
|
|
8
|
+
});
|
|
9
|
+
var UNKNOWN_FUNCTION = '<unknown>';
|
|
10
|
+
function parse(stackString) {
|
|
11
|
+
var lines = stackString.split('\n');
|
|
12
|
+
return lines.reduce(function(stack, line) {
|
|
13
|
+
var parseResult = parseChrome(line) || parseWinjs(line) || parseGecko(line) || parseNode(line) || parseJSC(line);
|
|
14
|
+
if (parseResult) stack.push(parseResult);
|
|
15
|
+
return stack;
|
|
16
|
+
}, []);
|
|
17
|
+
}
|
|
18
|
+
var chromeRe = /^\s*at (.*?) ?\(((?:file|https?|blob|chrome-extension|native|eval|webpack|rsc|<anonymous>|\/|[a-z]:\\|\\\\).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i;
|
|
19
|
+
var chromeEvalRe = /\((\S*)(?::(\d+))(?::(\d+))\)/;
|
|
20
|
+
function parseChrome(line) {
|
|
21
|
+
var parts = chromeRe.exec(line);
|
|
22
|
+
if (!parts) return null;
|
|
23
|
+
var isNative = parts[2] && 0 === parts[2].indexOf('native');
|
|
24
|
+
var isEval = parts[2] && 0 === parts[2].indexOf('eval');
|
|
25
|
+
var submatch = chromeEvalRe.exec(parts[2]);
|
|
26
|
+
if (isEval && null != submatch) {
|
|
27
|
+
parts[2] = submatch[1];
|
|
28
|
+
parts[3] = submatch[2];
|
|
29
|
+
parts[4] = submatch[3];
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
file: isNative ? null : parts[2],
|
|
33
|
+
methodName: parts[1] || UNKNOWN_FUNCTION,
|
|
34
|
+
arguments: isNative ? [
|
|
35
|
+
parts[2]
|
|
36
|
+
] : [],
|
|
37
|
+
lineNumber: parts[3] ? +parts[3] : null,
|
|
38
|
+
column: parts[4] ? +parts[4] : null
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
var winjsRe = /^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx|https?|webpack|rsc|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i;
|
|
42
|
+
function parseWinjs(line) {
|
|
43
|
+
var parts = winjsRe.exec(line);
|
|
44
|
+
if (!parts) return null;
|
|
45
|
+
return {
|
|
46
|
+
file: parts[2],
|
|
47
|
+
methodName: parts[1] || UNKNOWN_FUNCTION,
|
|
48
|
+
arguments: [],
|
|
49
|
+
lineNumber: +parts[3],
|
|
50
|
+
column: parts[4] ? +parts[4] : null
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
var geckoRe = /^\s*(.*?)(?:\((.*?)\))?(?:^|@)((?:file|https?|blob|chrome|webpack|rsc|resource|\[native).*?|[^@]*bundle)(?::(\d+))?(?::(\d+))?\s*$/i;
|
|
54
|
+
var geckoEvalRe = /(\S+) line (\d+)(?: > eval line \d+)* > eval/i;
|
|
55
|
+
function parseGecko(line) {
|
|
56
|
+
var parts = geckoRe.exec(line);
|
|
57
|
+
if (!parts) return null;
|
|
58
|
+
var isEval = parts[3] && parts[3].indexOf(' > eval') > -1;
|
|
59
|
+
var submatch = geckoEvalRe.exec(parts[3]);
|
|
60
|
+
if (isEval && null != submatch) {
|
|
61
|
+
parts[3] = submatch[1];
|
|
62
|
+
parts[4] = submatch[2];
|
|
63
|
+
parts[5] = null;
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
file: parts[3],
|
|
67
|
+
methodName: parts[1] || UNKNOWN_FUNCTION,
|
|
68
|
+
arguments: parts[2] ? parts[2].split(',') : [],
|
|
69
|
+
lineNumber: parts[4] ? +parts[4] : null,
|
|
70
|
+
column: parts[5] ? +parts[5] : null
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
var javaScriptCoreRe = /^\s*(?:([^@]*)(?:\((.*?)\))?@)?(\S.*?):(\d+)(?::(\d+))?\s*$/i;
|
|
74
|
+
function parseJSC(line) {
|
|
75
|
+
var parts = javaScriptCoreRe.exec(line);
|
|
76
|
+
if (!parts) return null;
|
|
77
|
+
return {
|
|
78
|
+
file: parts[3],
|
|
79
|
+
methodName: parts[1] || UNKNOWN_FUNCTION,
|
|
80
|
+
arguments: [],
|
|
81
|
+
lineNumber: +parts[4],
|
|
82
|
+
column: parts[5] ? +parts[5] : null
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
var nodeRe = /^\s*at (?:((?:\[object object\])?[^\\/]+(?: \[as \S+\])?) )?\(?(.*?):(\d+)(?::(\d+))?\)?\s*$/i;
|
|
86
|
+
function parseNode(line) {
|
|
87
|
+
var parts = nodeRe.exec(line);
|
|
88
|
+
if (!parts) return null;
|
|
89
|
+
return {
|
|
90
|
+
file: parts[2],
|
|
91
|
+
methodName: parts[1] || UNKNOWN_FUNCTION,
|
|
92
|
+
arguments: [],
|
|
93
|
+
lineNumber: +parts[3],
|
|
94
|
+
column: parts[4] ? +parts[4] : null
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
"./src/core/index.ts": function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
99
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
100
|
+
createRstest: ()=>createRstest
|
|
101
|
+
});
|
|
102
|
+
var manager_ = __webpack_require__("@vitest/snapshot/manager");
|
|
103
|
+
var external_std_env_ = __webpack_require__("std-env");
|
|
104
|
+
var src_config = __webpack_require__("./src/config.ts");
|
|
105
|
+
var external_pathe_ = __webpack_require__("pathe");
|
|
106
|
+
var stack_trace_parser_esm = __webpack_require__("../../node_modules/.pnpm/stacktrace-parser@0.1.11/node_modules/stacktrace-parser/dist/stack-trace-parser.esm.js");
|
|
107
|
+
var utils = __webpack_require__("./src/utils/index.ts");
|
|
108
|
+
var external_node_util_ = __webpack_require__("node:util");
|
|
109
|
+
const DEFAULT_RENDER_INTERVAL_MS = 1000;
|
|
110
|
+
const ESC = '\x1B[';
|
|
111
|
+
const CLEAR_LINE = `${ESC}K`;
|
|
112
|
+
const MOVE_CURSOR_ONE_ROW_UP = `${ESC}1A`;
|
|
113
|
+
const SYNC_START = `${ESC}?2026h`;
|
|
114
|
+
const SYNC_END = `${ESC}?2026l`;
|
|
115
|
+
class WindowRenderer {
|
|
116
|
+
options;
|
|
117
|
+
streams;
|
|
118
|
+
buffer = [];
|
|
119
|
+
renderInterval = void 0;
|
|
120
|
+
renderScheduled = false;
|
|
121
|
+
windowHeight = 0;
|
|
122
|
+
finished = false;
|
|
123
|
+
cleanups = [];
|
|
124
|
+
constructor(options){
|
|
125
|
+
this.options = {
|
|
126
|
+
interval: DEFAULT_RENDER_INTERVAL_MS,
|
|
127
|
+
...options
|
|
128
|
+
};
|
|
129
|
+
this.streams = {
|
|
130
|
+
output: options.logger.outputStream.write.bind(options.logger.outputStream),
|
|
131
|
+
error: options.logger.errorStream.write.bind(options.logger.errorStream)
|
|
132
|
+
};
|
|
133
|
+
this.cleanups.push(this.interceptStream(process.stdout, 'output'), this.interceptStream(process.stderr, 'error'));
|
|
134
|
+
this.start();
|
|
135
|
+
}
|
|
136
|
+
start() {
|
|
137
|
+
this.finished = false;
|
|
138
|
+
this.renderInterval = setInterval(()=>this.schedule(), this.options.interval).unref();
|
|
139
|
+
}
|
|
140
|
+
stop() {
|
|
141
|
+
this.cleanups.splice(0).map((fn)=>fn());
|
|
142
|
+
clearInterval(this.renderInterval);
|
|
143
|
+
}
|
|
144
|
+
finish() {
|
|
145
|
+
this.finished = true;
|
|
146
|
+
this.flushBuffer();
|
|
147
|
+
clearInterval(this.renderInterval);
|
|
148
|
+
}
|
|
149
|
+
schedule() {
|
|
150
|
+
if (!this.renderScheduled) {
|
|
151
|
+
this.renderScheduled = true;
|
|
152
|
+
this.flushBuffer();
|
|
153
|
+
setTimeout(()=>{
|
|
154
|
+
this.renderScheduled = false;
|
|
155
|
+
}, 100).unref();
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
flushBuffer() {
|
|
159
|
+
if (0 === this.buffer.length) return this.render();
|
|
160
|
+
let current;
|
|
161
|
+
for (const next of this.buffer.splice(0)){
|
|
162
|
+
if (!current) {
|
|
163
|
+
current = next;
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
if (current.type !== next.type) {
|
|
167
|
+
this.render(current.message, current.type);
|
|
168
|
+
current = next;
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
current.message += next.message;
|
|
172
|
+
}
|
|
173
|
+
if (current) this.render(current?.message, current?.type);
|
|
174
|
+
}
|
|
175
|
+
render(message, type = 'output') {
|
|
176
|
+
if (this.finished) {
|
|
177
|
+
this.clearWindow();
|
|
178
|
+
return this.write(message || '', type);
|
|
179
|
+
}
|
|
180
|
+
const windowContent = this.options.getWindow();
|
|
181
|
+
const rowCount = getRenderedRowCount(windowContent, this.options.logger.getColumns());
|
|
182
|
+
let padding = this.windowHeight - rowCount;
|
|
183
|
+
if (padding > 0 && message) padding -= getRenderedRowCount([
|
|
184
|
+
message
|
|
185
|
+
], this.options.logger.getColumns());
|
|
186
|
+
this.write(SYNC_START);
|
|
187
|
+
this.clearWindow();
|
|
188
|
+
if (message) this.write(message, type);
|
|
189
|
+
if (padding > 0) this.write('\n'.repeat(padding));
|
|
190
|
+
this.write(windowContent.join('\n'));
|
|
191
|
+
this.write(SYNC_END);
|
|
192
|
+
this.windowHeight = rowCount + Math.max(0, padding);
|
|
193
|
+
}
|
|
194
|
+
clearWindow() {
|
|
195
|
+
if (0 === this.windowHeight) return;
|
|
196
|
+
this.write(CLEAR_LINE);
|
|
197
|
+
for(let i = 1; i < this.windowHeight; i++)this.write(`${MOVE_CURSOR_ONE_ROW_UP}${CLEAR_LINE}`);
|
|
198
|
+
this.windowHeight = 0;
|
|
199
|
+
}
|
|
200
|
+
interceptStream(stream, type) {
|
|
201
|
+
const original = stream.write;
|
|
202
|
+
stream.write = (chunk, _, callback)=>{
|
|
203
|
+
if (chunk) if (this.finished) this.write(chunk.toString(), type);
|
|
204
|
+
else this.buffer.push({
|
|
205
|
+
type,
|
|
206
|
+
message: chunk.toString()
|
|
207
|
+
});
|
|
208
|
+
callback?.();
|
|
209
|
+
};
|
|
210
|
+
return function restore() {
|
|
211
|
+
stream.write = original;
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
write(message, type = 'output') {
|
|
215
|
+
this.streams[type](message);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
function getRenderedRowCount(rows, columns) {
|
|
219
|
+
let count = 0;
|
|
220
|
+
for (const row of rows){
|
|
221
|
+
const text = (0, external_node_util_.stripVTControlCharacters)(row);
|
|
222
|
+
count += Math.max(1, Math.ceil(text.length / columns));
|
|
223
|
+
}
|
|
224
|
+
return count;
|
|
225
|
+
}
|
|
226
|
+
class StatusRenderer {
|
|
227
|
+
rootPath;
|
|
228
|
+
renderer;
|
|
229
|
+
runningModules = new Set();
|
|
230
|
+
constructor(rootPath){
|
|
231
|
+
this.rootPath = rootPath;
|
|
232
|
+
this.renderer = new WindowRenderer({
|
|
233
|
+
getWindow: ()=>this.getContent(),
|
|
234
|
+
logger: {
|
|
235
|
+
outputStream: process.stdout,
|
|
236
|
+
errorStream: process.stderr,
|
|
237
|
+
getColumns: ()=>'columns' in process.stdout ? process.stdout.columns : 80
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
getContent() {
|
|
242
|
+
const summary = [];
|
|
243
|
+
for (const module of this.runningModules){
|
|
244
|
+
const relativePath = (0, external_pathe_.relative)(this.rootPath, module);
|
|
245
|
+
summary.push(`${utils.$_.bgYellow(utils.$_.bold(' RUNS '))} ${(0, utils.aj)(relativePath)}`);
|
|
246
|
+
}
|
|
247
|
+
summary.push('');
|
|
248
|
+
return summary;
|
|
249
|
+
}
|
|
250
|
+
addRunningModule(testPath) {
|
|
251
|
+
this.runningModules.add(testPath);
|
|
252
|
+
this.renderer?.schedule();
|
|
253
|
+
}
|
|
254
|
+
removeRunningModule(testPath) {
|
|
255
|
+
this.runningModules.delete(testPath);
|
|
256
|
+
this.renderer?.schedule();
|
|
257
|
+
}
|
|
258
|
+
clear() {
|
|
259
|
+
this.runningModules.clear();
|
|
260
|
+
this.renderer?.finish();
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
const getSummaryStatusString = (tasks, name = 'tests', showTotal = true)=>{
|
|
264
|
+
if (0 === tasks.length) return utils.$_.dim(`no ${name}`);
|
|
265
|
+
const passed = tasks.filter((result)=>'pass' === result.status);
|
|
266
|
+
const failed = tasks.filter((result)=>'fail' === result.status);
|
|
267
|
+
const skipped = tasks.filter((result)=>'skip' === result.status);
|
|
268
|
+
const todo = tasks.filter((result)=>'todo' === result.status);
|
|
269
|
+
const status = [
|
|
270
|
+
failed.length ? utils.$_.bold(utils.$_.red(`${failed.length} failed`)) : null,
|
|
271
|
+
passed.length ? utils.$_.bold(utils.$_.green(`${passed.length} passed`)) : null,
|
|
272
|
+
skipped.length ? utils.$_.yellow(`${skipped.length} skipped`) : null,
|
|
273
|
+
todo.length ? utils.$_.gray(`${todo.length} todo`) : null
|
|
274
|
+
].filter(Boolean);
|
|
275
|
+
return status.join(utils.$_.dim(' | ')) + (showTotal && status.length > 1 ? utils.$_.gray(` (${tasks.length})`) : '');
|
|
276
|
+
};
|
|
277
|
+
const printSnapshotSummaryLog = (snapshots, rootDir)=>{
|
|
278
|
+
const summary = [];
|
|
279
|
+
if (snapshots.added) summary.push(utils.$_.bold(utils.$_.green(`${snapshots.added} written`)));
|
|
280
|
+
if (snapshots.unmatched) summary.push(utils.$_.bold(utils.$_.red(`${snapshots.unmatched} failed`)));
|
|
281
|
+
if (snapshots.updated) summary.push(utils.$_.bold(utils.$_.green(`${snapshots.updated} updated `)));
|
|
282
|
+
if (snapshots.filesRemoved) if (snapshots.didUpdate) summary.push(utils.$_.bold(utils.$_.green(`${snapshots.filesRemoved} files removed `)));
|
|
283
|
+
else summary.push(utils.$_.bold(utils.$_.yellow(`${snapshots.filesRemoved} files obsolete `)));
|
|
284
|
+
const POINTER = "\u279C";
|
|
285
|
+
if (snapshots.filesRemovedList?.length) {
|
|
286
|
+
const [head, ...tail] = snapshots.filesRemovedList;
|
|
287
|
+
summary.push(`${utils.$_.gray(POINTER)} ${(0, utils.Ps)(rootDir, head)}`);
|
|
288
|
+
for (const key of tail)summary.push(` ${(0, utils.Ps)(rootDir, key)}`);
|
|
289
|
+
}
|
|
290
|
+
if (snapshots.unchecked) {
|
|
291
|
+
if (snapshots.didUpdate) summary.push(utils.$_.bold(utils.$_.green(`${snapshots.unchecked} removed`)));
|
|
292
|
+
else summary.push(utils.$_.bold(utils.$_.yellow(`${snapshots.unchecked} obsolete`)));
|
|
293
|
+
for (const uncheckedFile of snapshots.uncheckedKeysByFile){
|
|
294
|
+
summary.push(`${utils.$_.gray(POINTER)} ${(0, utils.Ps)(rootDir, uncheckedFile.filePath)}`);
|
|
295
|
+
for (const key of uncheckedFile.keys)summary.push(` ${key}`);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
for (const [index, snapshot] of summary.entries()){
|
|
299
|
+
const title = 0 === index ? 'Snapshots' : '';
|
|
300
|
+
utils.kg.log(`${utils.$_.gray(title.padStart(12))} ${snapshot}`);
|
|
301
|
+
}
|
|
302
|
+
};
|
|
303
|
+
const printSummaryLog = ({ results, testResults, snapshotSummary, duration, rootPath })=>{
|
|
304
|
+
utils.kg.log('');
|
|
305
|
+
printSnapshotSummaryLog(snapshotSummary, rootPath);
|
|
306
|
+
utils.kg.log(`${utils.$_.gray('Test Files'.padStart(11))} ${getSummaryStatusString(results)}`);
|
|
307
|
+
utils.kg.log(`${utils.$_.gray('Tests'.padStart(11))} ${getSummaryStatusString(testResults)}`);
|
|
308
|
+
utils.kg.log(`${utils.$_.gray('Duration'.padStart(11))} ${(0, utils.AS)(duration.totalTime)} ${utils.$_.gray(`(build ${(0, utils.AS)(duration.buildTime)}, tests ${(0, utils.AS)(duration.testTime)})`)}`);
|
|
309
|
+
utils.kg.log('');
|
|
310
|
+
};
|
|
311
|
+
const printSummaryErrorLogs = async ({ testResults, results, rootPath, getSourcemap })=>{
|
|
312
|
+
const failedTests = [
|
|
313
|
+
...results.filter((i)=>'fail' === i.status && i.errors?.length),
|
|
314
|
+
...testResults.filter((i)=>'fail' === i.status)
|
|
315
|
+
];
|
|
316
|
+
if (0 === failedTests.length) return;
|
|
317
|
+
utils.kg.log('');
|
|
318
|
+
utils.kg.log(utils.$_.bold('Summary of all failing tests:'));
|
|
319
|
+
utils.kg.log('');
|
|
320
|
+
for (const test of failedTests){
|
|
321
|
+
const relativePath = external_pathe_["default"].relative(rootPath, test.testPath);
|
|
322
|
+
const nameStr = (0, utils.Yz)(test);
|
|
323
|
+
utils.kg.log(`${utils.$_.bgRed(' FAIL ')} ${(0, utils.aj)(relativePath)} ${nameStr.length ? `${utils.$_.dim(utils.Qd)} ${nameStr}` : ''}`);
|
|
324
|
+
if (test.errors) {
|
|
325
|
+
const { printError } = await Promise.all([
|
|
326
|
+
__webpack_require__.e("973"),
|
|
327
|
+
__webpack_require__.e("355")
|
|
328
|
+
]).then(__webpack_require__.bind(__webpack_require__, "./src/utils/error.ts"));
|
|
329
|
+
for (const error of test.errors)await printError(error, getSourcemap, rootPath);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
};
|
|
333
|
+
const statusStr = {
|
|
334
|
+
fail: "\u2717",
|
|
335
|
+
pass: "\u2713",
|
|
336
|
+
todo: '-',
|
|
337
|
+
skip: '-'
|
|
338
|
+
};
|
|
339
|
+
const statusColorfulStr = {
|
|
340
|
+
fail: utils.$_.red(statusStr.fail),
|
|
341
|
+
pass: utils.$_.green(statusStr.pass),
|
|
342
|
+
todo: utils.$_.gray(statusStr.todo),
|
|
343
|
+
skip: utils.$_.gray(statusStr.skip)
|
|
344
|
+
};
|
|
345
|
+
class DefaultReporter {
|
|
346
|
+
rootPath;
|
|
347
|
+
config;
|
|
348
|
+
options = {};
|
|
349
|
+
statusRenderer;
|
|
350
|
+
constructor({ rootPath, options, config }){
|
|
351
|
+
this.rootPath = rootPath;
|
|
352
|
+
this.config = config;
|
|
353
|
+
this.options = options;
|
|
354
|
+
if (!external_std_env_.isCI) this.statusRenderer = new StatusRenderer(rootPath);
|
|
355
|
+
}
|
|
356
|
+
onTestFileStart(test) {
|
|
357
|
+
this.statusRenderer?.addRunningModule(test.testPath);
|
|
358
|
+
}
|
|
359
|
+
onTestFileResult(test) {
|
|
360
|
+
this.statusRenderer?.removeRunningModule(test.testPath);
|
|
361
|
+
const relativePath = (0, external_pathe_.relative)(this.rootPath, test.testPath);
|
|
362
|
+
const { slowTestThreshold } = this.config;
|
|
363
|
+
let title = ` ${utils.$_.bold(statusColorfulStr[test.status])} ${(0, utils.aj)(relativePath)}`;
|
|
364
|
+
const formatDuration = (duration)=>utils.$_[duration > slowTestThreshold ? 'yellow' : 'green'](`${(0, utils.AS)(duration, false)}`);
|
|
365
|
+
title += ` ${utils.$_.gray(`(${test.results.length})`)}`;
|
|
366
|
+
const isTooSlow = test.duration && test.duration > slowTestThreshold;
|
|
367
|
+
if (isTooSlow) title += ` ${formatDuration(test.duration)}`;
|
|
368
|
+
utils.kg.log(title);
|
|
369
|
+
if ('fail' !== test.status && !isTooSlow) return;
|
|
370
|
+
const showAllCases = isTooSlow && !test.results.some((result)=>(result.duration || 0) > slowTestThreshold);
|
|
371
|
+
for (const result of test.results){
|
|
372
|
+
const isSlowCase = (result.duration || 0) > slowTestThreshold;
|
|
373
|
+
if (!showAllCases && 'fail' !== result.status && !isSlowCase) continue;
|
|
374
|
+
const icon = isSlowCase && 'pass' === result.status ? utils.$_.yellow(statusStr[result.status]) : statusColorfulStr[result.status];
|
|
375
|
+
const nameStr = (0, utils.Yz)(result);
|
|
376
|
+
const duration = void 0 !== result.duration ? ` (${(0, utils.AS)(result.duration, false)})` : '';
|
|
377
|
+
console.log(` ${icon} ${nameStr}${utils.$_.gray(duration)}`);
|
|
378
|
+
if (result.errors) for (const error of result.errors)console.error(utils.$_.red(` ${error.message}`));
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
onTestCaseResult(_result) {}
|
|
382
|
+
onUserConsoleLog(log) {
|
|
383
|
+
const shouldLog = this.config.onConsoleLog?.(log.content) ?? true;
|
|
384
|
+
if (!shouldLog) return;
|
|
385
|
+
const titles = [
|
|
386
|
+
log.name
|
|
387
|
+
];
|
|
388
|
+
const testPath = (0, external_pathe_.relative)(this.rootPath, log.testPath);
|
|
389
|
+
if (log.trace) {
|
|
390
|
+
const [frame] = (0, stack_trace_parser_esm.Q)(log.trace);
|
|
391
|
+
const filePath = (0, external_pathe_.relative)(this.rootPath, frame.file || '');
|
|
392
|
+
if (filePath !== testPath) titles.push((0, utils.aj)(testPath));
|
|
393
|
+
titles.push((0, utils.aj)(filePath) + utils.$_.gray(`:${frame.lineNumber}:${frame.column}`));
|
|
394
|
+
} else titles.push((0, utils.aj)(testPath));
|
|
395
|
+
utils.kg.log(titles.join(utils.$_.gray(' | ')));
|
|
396
|
+
utils.kg.log(log.content);
|
|
397
|
+
utils.kg.log('');
|
|
398
|
+
}
|
|
399
|
+
async onExit() {
|
|
400
|
+
this.statusRenderer?.clear();
|
|
401
|
+
}
|
|
402
|
+
async onTestRunEnd({ results, testResults, duration, getSourcemap, snapshotSummary }) {
|
|
403
|
+
this.statusRenderer?.clear();
|
|
404
|
+
if (false === this.options.summary) return;
|
|
405
|
+
await printSummaryErrorLogs({
|
|
406
|
+
testResults,
|
|
407
|
+
results,
|
|
408
|
+
rootPath: this.rootPath,
|
|
409
|
+
getSourcemap
|
|
410
|
+
});
|
|
411
|
+
printSummaryLog({
|
|
412
|
+
results,
|
|
413
|
+
testResults,
|
|
414
|
+
duration,
|
|
415
|
+
rootPath: this.rootPath,
|
|
416
|
+
snapshotSummary
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
var helper = __webpack_require__("./src/utils/helper.ts");
|
|
421
|
+
const reportersMap = {
|
|
422
|
+
default: DefaultReporter
|
|
423
|
+
};
|
|
424
|
+
function createReporters(reporters, initOptions = {}) {
|
|
425
|
+
const result = (0, helper.XQ)(reporters).map((reporter)=>{
|
|
426
|
+
if ('string' == typeof reporter || Array.isArray(reporter)) {
|
|
427
|
+
const [name, options = {}] = (0, helper.XQ)(reporter);
|
|
428
|
+
if (name in reportersMap) {
|
|
429
|
+
const Reporter = reportersMap[name];
|
|
430
|
+
return new Reporter({
|
|
431
|
+
...initOptions,
|
|
432
|
+
options
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
throw new Error(`Reporter ${reporter} not found. Please install it or use a built-in reporter.`);
|
|
436
|
+
}
|
|
437
|
+
return reporter;
|
|
438
|
+
});
|
|
439
|
+
return result;
|
|
440
|
+
}
|
|
441
|
+
function createContext(options, userConfig) {
|
|
442
|
+
const { cwd, command } = options;
|
|
443
|
+
const rootPath = userConfig.root ? (0, helper.ZY)(cwd, userConfig.root) : cwd;
|
|
444
|
+
const rstestConfig = (0, src_config.hY)(userConfig);
|
|
445
|
+
const reporters = 'list' !== command ? createReporters(rstestConfig.reporters, {
|
|
446
|
+
rootPath,
|
|
447
|
+
config: rstestConfig
|
|
448
|
+
}) : [];
|
|
449
|
+
const snapshotManager = new manager_.SnapshotManager({
|
|
450
|
+
updateSnapshot: rstestConfig.update ? 'all' : external_std_env_.isCI ? 'none' : 'new'
|
|
451
|
+
});
|
|
452
|
+
return {
|
|
453
|
+
command,
|
|
454
|
+
version: "0.0.1",
|
|
455
|
+
rootPath,
|
|
456
|
+
reporters,
|
|
457
|
+
snapshotManager,
|
|
458
|
+
originalConfig: userConfig,
|
|
459
|
+
normalizedConfig: rstestConfig
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
function createRstest(config, command, fileFilters) {
|
|
463
|
+
const context = createContext({
|
|
464
|
+
cwd: process.cwd(),
|
|
465
|
+
command
|
|
466
|
+
}, config);
|
|
467
|
+
const runTests = async ()=>{
|
|
468
|
+
const { runTests } = await Promise.all([
|
|
469
|
+
__webpack_require__.e("992"),
|
|
470
|
+
__webpack_require__.e("629")
|
|
471
|
+
]).then(__webpack_require__.bind(__webpack_require__, "./src/core/runTests.ts"));
|
|
472
|
+
await runTests(context, fileFilters);
|
|
473
|
+
};
|
|
474
|
+
const listTests = async (options)=>{
|
|
475
|
+
const { listTests } = await Promise.all([
|
|
476
|
+
__webpack_require__.e("992"),
|
|
477
|
+
__webpack_require__.e("285")
|
|
478
|
+
]).then(__webpack_require__.bind(__webpack_require__, "./src/core/listTests.ts"));
|
|
479
|
+
await listTests(context, fileFilters, options);
|
|
480
|
+
};
|
|
481
|
+
return {
|
|
482
|
+
context,
|
|
483
|
+
runTests,
|
|
484
|
+
listTests
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
};
|