@rstest/core 0.9.2 → 0.9.3
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.md +1 -1
- package/dist/0~8843.js +5 -5
- package/dist/0~browserLoader.js +8 -8
- package/dist/0~browser~1.js +31 -31
- package/dist/0~checkThresholds.js +5 -5
- package/dist/{0~esm.js → 0~chokidar.js} +61 -18
- package/dist/0~console.js +7 -7
- package/dist/0~generate.js +4 -0
- package/dist/0~listTests.js +2 -2
- package/dist/0~mergeReports.js +127 -0
- package/dist/0~restart.js +3 -3
- package/dist/0~runTests.js +41 -41
- package/dist/1949.js +27 -11
- package/dist/255.js +3 -3
- package/dist/3145.js +160 -81
- package/dist/4411.js +3 -3
- package/dist/6830.js +43 -28
- package/dist/7552.js +82 -65
- package/dist/7704.js +2 -2
- package/dist/browser-runtime/723.js +142 -93
- package/dist/browser-runtime/index.d.ts +40 -5
- package/dist/browser.d.ts +40 -5
- package/dist/globalSetupWorker.js +4 -2
- package/dist/index.d.ts +53 -6
- package/dist/worker.d.ts +30 -3
- package/dist/worker.js +2 -2
- package/package.json +19 -18
- /package/dist/{0~esm.js.LICENSE.txt → 0~chokidar.js.LICENSE.txt} +0 -0
package/dist/3145.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import "node:module";
|
|
2
2
|
import { __webpack_require__ } from "./rslib-runtime.js";
|
|
3
|
-
import node_fs, { existsSync, readFileSync, statSync } from "node:fs";
|
|
3
|
+
import node_fs, { existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
|
|
4
4
|
import { loadConfig, mergeRsbuildConfig } from "@rsbuild/core";
|
|
5
5
|
import { stripVTControlCharacters } from "node:util";
|
|
6
6
|
import promises from "node:fs/promises";
|
|
7
7
|
import node_path, { dirname as external_node_path_dirname, resolve as external_node_path_resolve } from "node:path";
|
|
8
8
|
import { createRequire } from "node:module";
|
|
9
9
|
import node_process from "node:process";
|
|
10
|
-
import { basename, isTTY, dirname as pathe_M_eThtNZ_dirname, resolve as pathe_M_eThtNZ_resolve, relative, getAbsolutePath, join, bgColor, formatRootStr, determineAgent, logger as logger_logger, castArray, dist_m, prettyTime, isDebug, color, isAbsolute, getTaskNameWithPrefix, normalize, formatError } from "./6830.js";
|
|
10
|
+
import { basename, isTTY, dirname as pathe_M_eThtNZ_dirname, resolve as pathe_M_eThtNZ_resolve, relative, getAbsolutePath, join, bgColor, formatRootStr, determineAgent, logger as logger_logger, castArray, dist_m, prettyTime, isDebug, color as logger_color, isAbsolute, getTaskNameWithPrefix, normalize, formatError } from "./6830.js";
|
|
11
11
|
import { isDynamicPattern, glob, DEFAULT_CONFIG_NAME, prettyTestPath, globalApis, TEMP_RSTEST_OUTPUT_DIR_GLOB, formatTestPath, filterProjects, DEFAULT_CONFIG_EXTENSIONS, TS_CONFIG_FILE } from "./4411.js";
|
|
12
12
|
import { posix } from "./7011.js";
|
|
13
13
|
import { parse as stack_trace_parser_esm_parse } from "./1672.js";
|
|
@@ -587,7 +587,7 @@ function prepareCli() {
|
|
|
587
587
|
if (!npm_execpath || npm_execpath.includes('npx-cli.js') || npm_execpath.includes('.bun')) logger_logger.log();
|
|
588
588
|
}
|
|
589
589
|
function showRstest() {
|
|
590
|
-
logger_logger.greet(" Rstest v0.9.
|
|
590
|
+
logger_logger.greet(" Rstest v0.9.3");
|
|
591
591
|
logger_logger.log('');
|
|
592
592
|
}
|
|
593
593
|
const applyCommonOptions = (cli)=>{
|
|
@@ -638,7 +638,7 @@ const runRest = async ({ options, filters, command })=>{
|
|
|
638
638
|
function setupCommands() {
|
|
639
639
|
const cli = cac('rstest');
|
|
640
640
|
cli.help();
|
|
641
|
-
cli.version("0.9.
|
|
641
|
+
cli.version("0.9.3");
|
|
642
642
|
applyCommonOptions(cli);
|
|
643
643
|
cli.command('[...filters]', 'run tests').option('-w, --watch', 'Run tests in watch mode').action(async (filters, options)=>{
|
|
644
644
|
if (!determineAgent().isAgent) showRstest();
|
|
@@ -692,6 +692,27 @@ function setupCommands() {
|
|
|
692
692
|
process.exit(1);
|
|
693
693
|
}
|
|
694
694
|
});
|
|
695
|
+
cli.command('merge-reports [path]', 'Merge blob reports from multiple shards into a unified report').option('--cleanup', 'Remove blob reports directory after merging').action(async (path, options)=>{
|
|
696
|
+
if (!determineAgent().isAgent) showRstest();
|
|
697
|
+
try {
|
|
698
|
+
const { initCli } = await Promise.resolve(init_namespaceObject);
|
|
699
|
+
const { config, configFilePath, projects } = await initCli(options);
|
|
700
|
+
const { createRstest } = await Promise.resolve(src_core_namespaceObject);
|
|
701
|
+
const rstest = createRstest({
|
|
702
|
+
config,
|
|
703
|
+
configFilePath,
|
|
704
|
+
projects
|
|
705
|
+
}, 'merge-reports', []);
|
|
706
|
+
await rstest.mergeReports({
|
|
707
|
+
path,
|
|
708
|
+
cleanup: options.cleanup
|
|
709
|
+
});
|
|
710
|
+
} catch (err) {
|
|
711
|
+
logger_logger.error('Failed to merge reports.');
|
|
712
|
+
logger_logger.error(formatError(err));
|
|
713
|
+
process.exit(1);
|
|
714
|
+
}
|
|
715
|
+
});
|
|
695
716
|
cli.command('init [project]', 'Initialize rstest configuration').option('--yes', 'Use default options (non-interactive)').action(async (project, options)=>{
|
|
696
717
|
try {
|
|
697
718
|
let selectedProject = project;
|
|
@@ -709,7 +730,7 @@ function setupCommands() {
|
|
|
709
730
|
]
|
|
710
731
|
});
|
|
711
732
|
if (isCancel(selected)) {
|
|
712
|
-
console.log(
|
|
733
|
+
console.log(logger_color.yellow('Operation cancelled.'));
|
|
713
734
|
process.exit(0);
|
|
714
735
|
}
|
|
715
736
|
selectedProject = selected;
|
|
@@ -736,7 +757,7 @@ const resolveConfigPath = (root, customConfig)=>{
|
|
|
736
757
|
if (customConfig) {
|
|
737
758
|
const customConfigPath = isAbsolute(customConfig) ? customConfig : join(root, customConfig);
|
|
738
759
|
if (node_fs.existsSync(customConfigPath)) return customConfigPath;
|
|
739
|
-
throw `Cannot find config file: ${
|
|
760
|
+
throw `Cannot find config file: ${logger_color.dim(customConfigPath)}`;
|
|
740
761
|
}
|
|
741
762
|
const configFilePath = findConfig(join(root, DEFAULT_CONFIG_NAME));
|
|
742
763
|
if (configFilePath) return configFilePath;
|
|
@@ -758,18 +779,29 @@ async function config_loadConfig({ cwd = process.cwd(), path, envMode, configLoa
|
|
|
758
779
|
loader: configLoader
|
|
759
780
|
});
|
|
760
781
|
let config = content;
|
|
761
|
-
|
|
762
|
-
const extendsConfig = 'function' == typeof config.extends ? await config.extends(Object.freeze({
|
|
763
|
-
...config
|
|
764
|
-
})) : config.extends;
|
|
765
|
-
delete extendsConfig.projects;
|
|
766
|
-
config = mergeRstestConfig(extendsConfig, config);
|
|
767
|
-
}
|
|
782
|
+
config = await resolveExtends(config);
|
|
768
783
|
return {
|
|
769
784
|
content: config,
|
|
770
785
|
filePath: configFilePath
|
|
771
786
|
};
|
|
772
787
|
}
|
|
788
|
+
const resolveExtendEntry = async (entry, userConfig)=>{
|
|
789
|
+
const resolved = 'function' == typeof entry ? await entry(userConfig) : entry;
|
|
790
|
+
if ('projects' in resolved) {
|
|
791
|
+
const { projects: _projects, ...rest } = resolved;
|
|
792
|
+
return rest;
|
|
793
|
+
}
|
|
794
|
+
return resolved;
|
|
795
|
+
};
|
|
796
|
+
const resolveExtends = async (config)=>{
|
|
797
|
+
if (!config.extends) return config;
|
|
798
|
+
const userConfig = Object.freeze({
|
|
799
|
+
...config
|
|
800
|
+
});
|
|
801
|
+
const extendsEntries = castArray(config.extends);
|
|
802
|
+
const resolvedExtends = await Promise.all(extendsEntries.map((entry)=>resolveExtendEntry(entry, userConfig)));
|
|
803
|
+
return mergeRstestConfig(...resolvedExtends, config);
|
|
804
|
+
};
|
|
773
805
|
const mergeProjectConfig = (...configs)=>mergeRstestConfig(...configs);
|
|
774
806
|
const mergeRstestConfig = (...configs)=>configs.reduce((result, config)=>{
|
|
775
807
|
const merged = mergeRsbuildConfig(result, {
|
|
@@ -848,7 +880,8 @@ const createDefaultConfig = ()=>({
|
|
|
848
880
|
provider: 'playwright',
|
|
849
881
|
browser: 'chromium',
|
|
850
882
|
headless: dist_m,
|
|
851
|
-
strictPort: false
|
|
883
|
+
strictPort: false,
|
|
884
|
+
providerOptions: {}
|
|
852
885
|
},
|
|
853
886
|
coverage: {
|
|
854
887
|
exclude: [
|
|
@@ -872,7 +905,8 @@ const createDefaultConfig = ()=>({
|
|
|
872
905
|
],
|
|
873
906
|
reportsDirectory: './coverage',
|
|
874
907
|
clean: true,
|
|
875
|
-
reportOnFailure: false
|
|
908
|
+
reportOnFailure: false,
|
|
909
|
+
allowExternal: false
|
|
876
910
|
}
|
|
877
911
|
});
|
|
878
912
|
const withDefaultConfig = (config)=>{
|
|
@@ -895,7 +929,8 @@ const withDefaultConfig = (config)=>{
|
|
|
895
929
|
headless: merged.browser?.headless ?? dist_m,
|
|
896
930
|
port: merged.browser?.port,
|
|
897
931
|
strictPort: merged.browser?.strictPort ?? false,
|
|
898
|
-
viewport: merged.browser?.viewport
|
|
932
|
+
viewport: merged.browser?.viewport,
|
|
933
|
+
providerOptions: merged.browser?.providerOptions ?? {}
|
|
899
934
|
};
|
|
900
935
|
return {
|
|
901
936
|
...merged,
|
|
@@ -947,7 +982,11 @@ function mergeWithCLIOptions(config, options) {
|
|
|
947
982
|
if (void 0 !== options.bail && ('number' == typeof options.bail || 'boolean' == typeof options.bail)) config.bail = Number(options.bail);
|
|
948
983
|
if (void 0 !== options.coverage) {
|
|
949
984
|
config.coverage ??= {};
|
|
950
|
-
config.coverage.enabled = options.coverage;
|
|
985
|
+
if ('boolean' == typeof options.coverage) config.coverage.enabled = options.coverage;
|
|
986
|
+
else {
|
|
987
|
+
if (void 0 !== options.coverage.enabled) config.coverage.enabled = options.coverage.enabled;
|
|
988
|
+
if (void 0 !== options.coverage.allowExternal) config.coverage.allowExternal = options.coverage.allowExternal;
|
|
989
|
+
}
|
|
951
990
|
}
|
|
952
991
|
if (options.exclude) config.exclude = castArray(options.exclude);
|
|
953
992
|
if (options.include) config.include = castArray(options.include);
|
|
@@ -1032,16 +1071,9 @@ async function resolveProjects({ config, root, options }) {
|
|
|
1032
1071
|
await Promise.all((rstestConfig.projects || []).map(async (p)=>{
|
|
1033
1072
|
if ('object' == typeof p) {
|
|
1034
1073
|
const projectRoot = p.root ? formatRootStr(p.root, root) : root;
|
|
1035
|
-
|
|
1074
|
+
const projectConfig = await resolveExtends({
|
|
1036
1075
|
...p
|
|
1037
|
-
};
|
|
1038
|
-
if (projectConfig.extends) {
|
|
1039
|
-
const extendsConfig = 'function' == typeof projectConfig.extends ? await projectConfig.extends(Object.freeze({
|
|
1040
|
-
...projectConfig
|
|
1041
|
-
})) : projectConfig.extends;
|
|
1042
|
-
delete extendsConfig.projects;
|
|
1043
|
-
projectConfig = mergeRstestConfig(extendsConfig, projectConfig);
|
|
1044
|
-
}
|
|
1076
|
+
});
|
|
1045
1077
|
projectConfigs.push({
|
|
1046
1078
|
config: mergeWithCLIOptions({
|
|
1047
1079
|
root: projectRoot,
|
|
@@ -1088,8 +1120,8 @@ async function resolveProjects({ config, root, options }) {
|
|
|
1088
1120
|
const projects = await getProjects(config, root).then((p)=>filterProjects(p, options));
|
|
1089
1121
|
if (!projects.length) {
|
|
1090
1122
|
let errorMsg = `No projects found, please make sure you have at least one valid project.
|
|
1091
|
-
${
|
|
1092
|
-
if (options.project) errorMsg += `\n${
|
|
1123
|
+
${logger_color.gray('projects:')} ${JSON.stringify(config.projects, null, 2)}`;
|
|
1124
|
+
if (options.project) errorMsg += `\n${logger_color.gray('projectName filter:')} ${JSON.stringify(options.project, null, 2)}`;
|
|
1093
1125
|
throw errorMsg;
|
|
1094
1126
|
}
|
|
1095
1127
|
const names = new Set();
|
|
@@ -1195,53 +1227,53 @@ function addSnapshotResult(summary, result) {
|
|
|
1195
1227
|
summary.total += result.added + result.matched + result.unmatched + result.updated;
|
|
1196
1228
|
}
|
|
1197
1229
|
const getSummaryStatusString = (tasks, name = 'tests', showTotal = true)=>{
|
|
1198
|
-
if (0 === tasks.length) return
|
|
1230
|
+
if (0 === tasks.length) return logger_color.dim(`no ${name}`);
|
|
1199
1231
|
const passed = tasks.filter((result)=>'pass' === result.status);
|
|
1200
1232
|
const failed = tasks.filter((result)=>'fail' === result.status);
|
|
1201
1233
|
const skipped = tasks.filter((result)=>'skip' === result.status);
|
|
1202
1234
|
const todo = tasks.filter((result)=>'todo' === result.status);
|
|
1203
1235
|
const status = [
|
|
1204
|
-
failed.length ?
|
|
1205
|
-
passed.length ?
|
|
1206
|
-
skipped.length ?
|
|
1207
|
-
todo.length ?
|
|
1236
|
+
failed.length ? logger_color.bold(logger_color.red(`${failed.length} failed`)) : null,
|
|
1237
|
+
passed.length ? logger_color.bold(logger_color.green(`${passed.length} passed`)) : null,
|
|
1238
|
+
skipped.length ? logger_color.yellow(`${skipped.length} skipped`) : null,
|
|
1239
|
+
todo.length ? logger_color.gray(`${todo.length} todo`) : null
|
|
1208
1240
|
].filter(Boolean);
|
|
1209
|
-
return status.join(
|
|
1241
|
+
return status.join(logger_color.dim(' | ')) + (showTotal && status.length > 1 ? logger_color.gray(` (${tasks.length})`) : '');
|
|
1210
1242
|
};
|
|
1211
1243
|
const printSnapshotSummaryLog = (snapshots, rootDir)=>{
|
|
1212
1244
|
const summary = [];
|
|
1213
|
-
if (snapshots.added) summary.push(
|
|
1214
|
-
if (snapshots.unmatched) summary.push(
|
|
1215
|
-
if (snapshots.updated) summary.push(
|
|
1216
|
-
if (snapshots.filesRemoved) if (snapshots.didUpdate) summary.push(
|
|
1217
|
-
else summary.push(
|
|
1245
|
+
if (snapshots.added) summary.push(logger_color.bold(logger_color.green(`${snapshots.added} written`)));
|
|
1246
|
+
if (snapshots.unmatched) summary.push(logger_color.bold(logger_color.red(`${snapshots.unmatched} failed`)));
|
|
1247
|
+
if (snapshots.updated) summary.push(logger_color.bold(logger_color.green(`${snapshots.updated} updated `)));
|
|
1248
|
+
if (snapshots.filesRemoved) if (snapshots.didUpdate) summary.push(logger_color.bold(logger_color.green(`${snapshots.filesRemoved} files removed `)));
|
|
1249
|
+
else summary.push(logger_color.bold(logger_color.yellow(`${snapshots.filesRemoved} files obsolete `)));
|
|
1218
1250
|
if (snapshots.filesRemovedList?.length) {
|
|
1219
1251
|
const [head, ...tail] = snapshots.filesRemovedList;
|
|
1220
|
-
summary.push(`${
|
|
1252
|
+
summary.push(`${logger_color.gray("➜")} ${formatTestPath(rootDir, head)}`);
|
|
1221
1253
|
for (const key of tail)summary.push(` ${formatTestPath(rootDir, key)}`);
|
|
1222
1254
|
}
|
|
1223
1255
|
if (snapshots.unchecked) {
|
|
1224
|
-
if (snapshots.didUpdate) summary.push(
|
|
1225
|
-
else summary.push(
|
|
1256
|
+
if (snapshots.didUpdate) summary.push(logger_color.bold(logger_color.green(`${snapshots.unchecked} removed`)));
|
|
1257
|
+
else summary.push(logger_color.bold(logger_color.yellow(`${snapshots.unchecked} obsolete`)));
|
|
1226
1258
|
for (const uncheckedFile of snapshots.uncheckedKeysByFile){
|
|
1227
|
-
summary.push(`${
|
|
1259
|
+
summary.push(`${logger_color.gray("➜")} ${formatTestPath(rootDir, uncheckedFile.filePath)}`);
|
|
1228
1260
|
for (const key of uncheckedFile.keys)summary.push(` ${key}`);
|
|
1229
1261
|
}
|
|
1230
1262
|
}
|
|
1231
1263
|
for (const [index, snapshot] of summary.entries()){
|
|
1232
1264
|
const title = 0 === index ? 'Snapshots' : '';
|
|
1233
|
-
logger_logger.log(`${
|
|
1265
|
+
logger_logger.log(`${logger_color.gray(title.padStart(12))} ${snapshot}`);
|
|
1234
1266
|
}
|
|
1235
1267
|
};
|
|
1236
|
-
const TestFileSummaryLabel =
|
|
1237
|
-
const TestSummaryLabel =
|
|
1238
|
-
const DurationLabel =
|
|
1268
|
+
const TestFileSummaryLabel = logger_color.gray('Test Files'.padStart(11));
|
|
1269
|
+
const TestSummaryLabel = logger_color.gray('Tests'.padStart(11));
|
|
1270
|
+
const DurationLabel = logger_color.gray('Duration'.padStart(11));
|
|
1239
1271
|
const printSummaryLog = ({ results, testResults, snapshotSummary, duration, rootPath })=>{
|
|
1240
1272
|
logger_logger.log('');
|
|
1241
1273
|
printSnapshotSummaryLog(snapshotSummary, rootPath);
|
|
1242
1274
|
logger_logger.log(`${TestFileSummaryLabel} ${getSummaryStatusString(results)}`);
|
|
1243
1275
|
logger_logger.log(`${TestSummaryLabel} ${getSummaryStatusString(testResults)}`);
|
|
1244
|
-
logger_logger.log(`${DurationLabel} ${prettyTime(duration.totalTime)} ${
|
|
1276
|
+
logger_logger.log(`${DurationLabel} ${prettyTime(duration.totalTime)} ${logger_color.gray(`(build ${prettyTime(duration.buildTime)}, tests ${prettyTime(duration.testTime)})`)}`);
|
|
1245
1277
|
logger_logger.log('');
|
|
1246
1278
|
};
|
|
1247
1279
|
const printSummaryErrorLogs = async ({ testResults, results, rootPath, unhandledErrors, getSourcemap, filterRerunTestPaths })=>{
|
|
@@ -1251,7 +1283,7 @@ const printSummaryErrorLogs = async ({ testResults, results, rootPath, unhandled
|
|
|
1251
1283
|
];
|
|
1252
1284
|
if (0 === failedTests.length && !unhandledErrors?.length) return;
|
|
1253
1285
|
logger_logger.stderr('');
|
|
1254
|
-
logger_logger.stderr(
|
|
1286
|
+
logger_logger.stderr(logger_color.bold('Summary of all failing tests:'));
|
|
1255
1287
|
logger_logger.stderr('');
|
|
1256
1288
|
const { printError } = await Promise.resolve(error_namespaceObject);
|
|
1257
1289
|
for (const error of unhandledErrors || []){
|
|
@@ -1261,7 +1293,7 @@ const printSummaryErrorLogs = async ({ testResults, results, rootPath, unhandled
|
|
|
1261
1293
|
for (const test of failedTests){
|
|
1262
1294
|
const relativePath = posix.relative(rootPath, test.testPath);
|
|
1263
1295
|
const nameStr = getTaskNameWithPrefix(test);
|
|
1264
|
-
logger_logger.stderr(`${bgColor('bgRed', ' FAIL ')} ${prettyTestPath(relativePath)} ${nameStr.length ? `${
|
|
1296
|
+
logger_logger.stderr(`${bgColor('bgRed', ' FAIL ')} ${prettyTestPath(relativePath)} ${nameStr.length ? `${logger_color.dim(">")} ${nameStr}` : ''}`);
|
|
1265
1297
|
if (test.errors) {
|
|
1266
1298
|
const { printError } = await Promise.resolve(error_namespaceObject);
|
|
1267
1299
|
for (const error of test.errors)await printError(error, getSourcemap, rootPath);
|
|
@@ -1418,14 +1450,14 @@ class StatusRenderer {
|
|
|
1418
1450
|
const relativePath = relative(this.rootPath, module);
|
|
1419
1451
|
summary.push(`${bgColor('bgYellow', ' RUNS ')} ${prettyTestPath(relativePath)}`);
|
|
1420
1452
|
if (runningTests.length && shouldDisplayRunningTests(runningTests)) {
|
|
1421
|
-
let caseLog = ` ${
|
|
1422
|
-
if (runningTests.length > 1) caseLog +=
|
|
1453
|
+
let caseLog = ` ${logger_color.gray("➜")} ${getTaskNameWithPrefix(runningTests[0])} ${logger_color.magenta(prettyTime(now - runningTests[0].startTime))}`;
|
|
1454
|
+
if (runningTests.length > 1) caseLog += logger_color.gray(` and ${runningTests.length - 1} more cases`);
|
|
1423
1455
|
summary.push(caseLog);
|
|
1424
1456
|
}
|
|
1425
1457
|
}
|
|
1426
1458
|
summary.push('');
|
|
1427
1459
|
if (0 === testModules.length) summary.push(`${TestFileSummaryLabel} ${runningModules.size} total`);
|
|
1428
|
-
else summary.push(`${TestFileSummaryLabel} ${getSummaryStatusString(testModules, '', false)} ${
|
|
1460
|
+
else summary.push(`${TestFileSummaryLabel} ${getSummaryStatusString(testModules, '', false)} ${logger_color.dim('|')} ${runningModules.size + testModules.length} total`);
|
|
1429
1461
|
const testResults = Array.from(runningModules.values()).flatMap(({ results })=>results).concat(testModules.flatMap((mod)=>mod.results));
|
|
1430
1462
|
if (testResults.length) summary.push(`${TestSummaryLabel} ${getSummaryStatusString(testResults, '', false)}`);
|
|
1431
1463
|
summary.push(`${DurationLabel} ${prettyTime(Date.now() - this.startTime)}`);
|
|
@@ -1453,10 +1485,10 @@ const statusStr = {
|
|
|
1453
1485
|
skip: '-'
|
|
1454
1486
|
};
|
|
1455
1487
|
const statusColor = {
|
|
1456
|
-
fail:
|
|
1457
|
-
pass:
|
|
1458
|
-
todo:
|
|
1459
|
-
skip:
|
|
1488
|
+
fail: logger_color.red,
|
|
1489
|
+
pass: logger_color.green,
|
|
1490
|
+
todo: logger_color.gray,
|
|
1491
|
+
skip: logger_color.gray
|
|
1460
1492
|
};
|
|
1461
1493
|
const statusColorfulStr = {
|
|
1462
1494
|
fail: statusColor.fail(statusStr.fail),
|
|
@@ -1467,23 +1499,23 @@ const statusColorfulStr = {
|
|
|
1467
1499
|
const logCase = (result, options)=>{
|
|
1468
1500
|
const isSlowCase = (result.duration || 0) > options.slowTestThreshold;
|
|
1469
1501
|
if (options.hideSkippedTests && 'skip' === result.status) return;
|
|
1470
|
-
const icon = isSlowCase && 'pass' === result.status ?
|
|
1502
|
+
const icon = isSlowCase && 'pass' === result.status ? logger_color.yellow(statusStr[result.status]) : statusColorfulStr[result.status];
|
|
1471
1503
|
const nameStr = getTaskNameWithPrefix(result);
|
|
1472
1504
|
const duration = void 0 !== result.duration ? ` (${prettyTime(result.duration)})` : '';
|
|
1473
|
-
const retry = result.retryCount ?
|
|
1474
|
-
const heap = result.heap ? ` ${
|
|
1475
|
-
logger_logger.log(` ${icon} ${nameStr}${
|
|
1476
|
-
if (result.errors) for (const error of result.errors)logger_logger.log(
|
|
1505
|
+
const retry = result.retryCount ? logger_color.yellow(` (retry x${result.retryCount})`) : '';
|
|
1506
|
+
const heap = result.heap ? ` ${logger_color.magenta(formatHeapUsed(result.heap))}` : '';
|
|
1507
|
+
logger_logger.log(` ${icon} ${nameStr}${logger_color.gray(duration)}${retry}${heap}`);
|
|
1508
|
+
if (result.errors) for (const error of result.errors)logger_logger.log(logger_color.red(` ${error.message}`));
|
|
1477
1509
|
};
|
|
1478
1510
|
const formatHeapUsed = (heap)=>`${Math.floor(heap / 1024 / 1024)} MB heap used`;
|
|
1479
1511
|
const logFileTitle = (test, relativePath, alwaysShowTime = false, showProjectName = false)=>{
|
|
1480
|
-
let title = ` ${
|
|
1512
|
+
let title = ` ${logger_color.bold(statusColorfulStr[test.status])}`;
|
|
1481
1513
|
if (showProjectName && test.project) title += ` ${statusColor[test.status](`[${test.project}]`)}`;
|
|
1482
1514
|
title += ` ${prettyTestPath(relativePath)}`;
|
|
1483
|
-
const formatDuration = (duration)=>
|
|
1484
|
-
title += ` ${
|
|
1515
|
+
const formatDuration = (duration)=>logger_color.green(prettyTime(duration));
|
|
1516
|
+
title += ` ${logger_color.gray(`(${test.results.length})`)}`;
|
|
1485
1517
|
if (alwaysShowTime) title += ` ${formatDuration(test.duration)}`;
|
|
1486
|
-
if (test.heap) title += ` ${
|
|
1518
|
+
if (test.heap) title += ` ${logger_color.magenta(formatHeapUsed(test.heap))}`;
|
|
1487
1519
|
logger_logger.log(title);
|
|
1488
1520
|
};
|
|
1489
1521
|
class DefaultReporter {
|
|
@@ -1538,7 +1570,7 @@ class DefaultReporter {
|
|
|
1538
1570
|
} else titles.push(testPath);
|
|
1539
1571
|
const logOutput = 'stdout' === log.type ? logger_logger.log : logger_logger.stderr;
|
|
1540
1572
|
logOutput('');
|
|
1541
|
-
logOutput(`${log.name}${
|
|
1573
|
+
logOutput(`${log.name}${logger_color.gray(logger_color.dim(` | ${titles.join(logger_color.gray(logger_color.dim(' | ')))}`))}`);
|
|
1542
1574
|
logOutput(log.content);
|
|
1543
1575
|
logOutput('');
|
|
1544
1576
|
}
|
|
@@ -1565,6 +1597,44 @@ class DefaultReporter {
|
|
|
1565
1597
|
});
|
|
1566
1598
|
}
|
|
1567
1599
|
}
|
|
1600
|
+
const DEFAULT_OUTPUT_DIR = '.rstest-reports';
|
|
1601
|
+
class BlobReporter {
|
|
1602
|
+
config;
|
|
1603
|
+
outputDir;
|
|
1604
|
+
consoleLogs = [];
|
|
1605
|
+
constructor({ rootPath, config, options }){
|
|
1606
|
+
this.config = config;
|
|
1607
|
+
this.outputDir = options?.outputDir ? join(rootPath, options.outputDir) : join(rootPath, DEFAULT_OUTPUT_DIR);
|
|
1608
|
+
}
|
|
1609
|
+
onUserConsoleLog(log) {
|
|
1610
|
+
this.consoleLogs.push(log);
|
|
1611
|
+
}
|
|
1612
|
+
async onTestRunEnd({ results, testResults, duration, snapshotSummary, unhandledErrors }) {
|
|
1613
|
+
const shard = this.config.shard;
|
|
1614
|
+
const fileName = shard ? `blob-${shard.index}-${shard.count}.json` : 'blob.json';
|
|
1615
|
+
const blobData = {
|
|
1616
|
+
version: "0.9.3",
|
|
1617
|
+
shard: shard ? {
|
|
1618
|
+
index: shard.index,
|
|
1619
|
+
count: shard.count
|
|
1620
|
+
} : void 0,
|
|
1621
|
+
results,
|
|
1622
|
+
testResults,
|
|
1623
|
+
duration,
|
|
1624
|
+
snapshotSummary,
|
|
1625
|
+
unhandledErrors: unhandledErrors?.map((e)=>({
|
|
1626
|
+
message: e.message,
|
|
1627
|
+
stack: e.stack,
|
|
1628
|
+
name: e.name
|
|
1629
|
+
})),
|
|
1630
|
+
consoleLogs: this.consoleLogs.length > 0 ? this.consoleLogs : void 0
|
|
1631
|
+
};
|
|
1632
|
+
mkdirSync(this.outputDir, {
|
|
1633
|
+
recursive: true
|
|
1634
|
+
});
|
|
1635
|
+
writeFileSync(join(this.outputDir, fileName), JSON.stringify(blobData), 'utf-8');
|
|
1636
|
+
}
|
|
1637
|
+
}
|
|
1568
1638
|
class GithubActionsReporter {
|
|
1569
1639
|
onWritePath;
|
|
1570
1640
|
rootPath;
|
|
@@ -1619,15 +1689,15 @@ function escapeData(s) {
|
|
|
1619
1689
|
}
|
|
1620
1690
|
function ansiRegex({ onlyFirst = false } = {}) {
|
|
1621
1691
|
const ST = '(?:\\u0007|\\u001B\\u005C|\\u009C)';
|
|
1622
|
-
const
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
].join('|');
|
|
1692
|
+
const osc = `(?:\\u001B\\][\\s\\S]*?${ST})`;
|
|
1693
|
+
const csi = '[\\u001B\\u009B][[\\]()#;?]*(?:\\d{1,4}(?:[;:]\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]';
|
|
1694
|
+
const pattern = `${osc}|${csi}`;
|
|
1626
1695
|
return new RegExp(pattern, onlyFirst ? void 0 : 'g');
|
|
1627
1696
|
}
|
|
1628
1697
|
const regex = ansiRegex();
|
|
1629
1698
|
function stripAnsi(string) {
|
|
1630
1699
|
if ('string' != typeof string) throw new TypeError(`Expected a \`string\`, got \`${typeof string}\``);
|
|
1700
|
+
if (!string.includes('\u001B') && !string.includes('\u009B')) return string;
|
|
1631
1701
|
return string.replace(regex, '');
|
|
1632
1702
|
}
|
|
1633
1703
|
const schemeRegex = /^[\w+.-]+:\/\//;
|
|
@@ -1941,7 +2011,7 @@ const hintNotDefinedError = (message)=>{
|
|
|
1941
2011
|
'jest',
|
|
1942
2012
|
'vitest'
|
|
1943
2013
|
].includes(varName)) return message.replace(`${varName} is not defined`, `${varName} is not defined. Did you mean rstest?`);
|
|
1944
|
-
if ('React' === varName) return message.replace(`${varName} is not defined`, `${varName} is not defined. Did you forget to install "${
|
|
2014
|
+
if ('React' === varName) return message.replace(`${varName} is not defined`, `${varName} is not defined. Did you forget to install "${logger_color.yellow('@rsbuild/plugin-react')}" plugin?`);
|
|
1945
2015
|
}
|
|
1946
2016
|
return message;
|
|
1947
2017
|
};
|
|
@@ -1951,14 +2021,14 @@ async function error_printError(error, getSourcemap, rootPath) {
|
|
|
1951
2021
|
const tips = [
|
|
1952
2022
|
'Error: not support import `vitest` in Rstest test environment.\n',
|
|
1953
2023
|
'Solution:',
|
|
1954
|
-
` - Update your code to use imports from "${
|
|
2024
|
+
` - Update your code to use imports from "${logger_color.yellow('@rstest/core')}" instead of "${logger_color.yellow('vitest')}".`,
|
|
1955
2025
|
' - Enable `globals` configuration and use global API.'
|
|
1956
2026
|
];
|
|
1957
|
-
logger_logger.stderr(`${
|
|
2027
|
+
logger_logger.stderr(`${logger_color.red(tips.join('\n'))}\n`);
|
|
1958
2028
|
return;
|
|
1959
2029
|
}
|
|
1960
2030
|
if (error.message.includes('is not defined')) error.message = hintNotDefinedError(error.message);
|
|
1961
|
-
logger_logger.stderr(`${
|
|
2031
|
+
logger_logger.stderr(`${logger_color.red(logger_color.bold(errorName))}${logger_color.red(`: ${error.message}`)}\n`);
|
|
1962
2032
|
if (error.diff) {
|
|
1963
2033
|
logger_logger.stderr(error.diff);
|
|
1964
2034
|
logger_logger.stderr('');
|
|
@@ -1969,7 +2039,7 @@ async function error_printError(error, getSourcemap, rootPath) {
|
|
|
1969
2039
|
fullStack: error.fullStack,
|
|
1970
2040
|
getSourcemap
|
|
1971
2041
|
});
|
|
1972
|
-
if (!stackFrames.length && !(error.fullStack || isDebug()) && !error.stack.endsWith(error.message)) logger_logger.stderr(
|
|
2042
|
+
if (!stackFrames.length && !(error.fullStack || isDebug()) && !error.stack.endsWith(error.message)) logger_logger.stderr(logger_color.gray("No error stack found, set 'DEBUG=rstest' to show fullStack."));
|
|
1973
2043
|
if (stackFrames[0]) await printCodeFrame(stackFrames[0]);
|
|
1974
2044
|
printStack(stackFrames, rootPath);
|
|
1975
2045
|
}
|
|
@@ -1996,7 +2066,7 @@ function formatStack(frame, rootPath) {
|
|
|
1996
2066
|
return '<unknown>' !== frame.methodName ? `at ${frame.methodName} (${formatTestPath(rootPath, frame.file)}:${frame.lineNumber}:${frame.column})` : `at ${formatTestPath(rootPath, frame.file)}:${frame.lineNumber}:${frame.column}`;
|
|
1997
2067
|
}
|
|
1998
2068
|
function printStack(stackFrames, rootPath) {
|
|
1999
|
-
for (const frame of stackFrames)logger_logger.stderr(
|
|
2069
|
+
for (const frame of stackFrames)logger_logger.stderr(logger_color.gray(` ${formatStack(frame, rootPath)}`));
|
|
2000
2070
|
stackFrames.length && logger_logger.stderr('');
|
|
2001
2071
|
}
|
|
2002
2072
|
const stackIgnores = [
|
|
@@ -3201,7 +3271,7 @@ class MdReporter {
|
|
|
3201
3271
|
}
|
|
3202
3272
|
renderFrontMatter(lines) {
|
|
3203
3273
|
const frontMatter = {
|
|
3204
|
-
tool: "@rstest/core@0.9.
|
|
3274
|
+
tool: "@rstest/core@0.9.3",
|
|
3205
3275
|
timestamp: new Date().toISOString()
|
|
3206
3276
|
};
|
|
3207
3277
|
if (this.options.header.env) frontMatter.runtime = {
|
|
@@ -3575,7 +3645,7 @@ class Rstest {
|
|
|
3575
3645
|
updateSnapshot: rstestConfig.update ? 'all' : dist_m ? 'none' : 'new'
|
|
3576
3646
|
});
|
|
3577
3647
|
this.snapshotManager = snapshotManager;
|
|
3578
|
-
this.version = "0.9.
|
|
3648
|
+
this.version = "0.9.3";
|
|
3579
3649
|
this.rootPath = rootPath;
|
|
3580
3650
|
this.originalConfig = userConfig;
|
|
3581
3651
|
this.normalizedConfig = rstestConfig;
|
|
@@ -3628,6 +3698,9 @@ class Rstest {
|
|
|
3628
3698
|
options: {
|
|
3629
3699
|
showProjectName: projects.length > 1
|
|
3630
3700
|
}
|
|
3701
|
+
}).filter((r)=>{
|
|
3702
|
+
if ('merge-reports' === command && r instanceof BlobReporter) return false;
|
|
3703
|
+
return true;
|
|
3631
3704
|
}) : [];
|
|
3632
3705
|
this.reporters = reporters;
|
|
3633
3706
|
}
|
|
@@ -3652,7 +3725,8 @@ const reportersMap = {
|
|
|
3652
3725
|
verbose: VerboseReporter,
|
|
3653
3726
|
'github-actions': GithubActionsReporter,
|
|
3654
3727
|
junit: JUnitReporter,
|
|
3655
|
-
md: MdReporter
|
|
3728
|
+
md: MdReporter,
|
|
3729
|
+
blob: BlobReporter
|
|
3656
3730
|
};
|
|
3657
3731
|
function createReporters(reporters, initConfig = {}) {
|
|
3658
3732
|
const result = castArray(reporters).map((reporter)=>{
|
|
@@ -3693,10 +3767,15 @@ function core_createRstest({ config, projects, configFilePath }, command, fileFi
|
|
|
3693
3767
|
const { listTests } = await import("./0~listTests.js");
|
|
3694
3768
|
return listTests(context, options);
|
|
3695
3769
|
};
|
|
3770
|
+
const mergeReports = async (options)=>{
|
|
3771
|
+
const { mergeReports } = await import("./0~mergeReports.js");
|
|
3772
|
+
await mergeReports(context, options);
|
|
3773
|
+
};
|
|
3696
3774
|
return {
|
|
3697
3775
|
context,
|
|
3698
3776
|
runTests,
|
|
3699
|
-
listTests
|
|
3777
|
+
listTests,
|
|
3778
|
+
mergeReports
|
|
3700
3779
|
};
|
|
3701
3780
|
}
|
|
3702
3781
|
function defineConfig(config) {
|
package/dist/4411.js
CHANGED
|
@@ -5,7 +5,7 @@ import node_fs, * as __rspack_external_node_fs_5ea92f0c from "node:fs";
|
|
|
5
5
|
import node_path, { basename, dirname, normalize, posix, relative as external_node_path_relative, resolve, sep } from "node:path";
|
|
6
6
|
import { fileURLToPath } from "url";
|
|
7
7
|
import { createRequire } from "module";
|
|
8
|
-
import { logger as logger_logger, parsePosix, color, castArray } from "./6830.js";
|
|
8
|
+
import { logger as logger_logger, parsePosix, color as logger_color, castArray } from "./6830.js";
|
|
9
9
|
import { posix as dist_posix } from "./7011.js";
|
|
10
10
|
__webpack_require__.add({
|
|
11
11
|
"../../node_modules/.pnpm/picomatch@4.0.3/node_modules/picomatch/index.js" (module, __unused_rspack_exports, __webpack_require__) {
|
|
@@ -2266,7 +2266,7 @@ const getTestEntries = async ({ include, exclude, rootPath, projectRoot, fileFil
|
|
|
2266
2266
|
};
|
|
2267
2267
|
const prettyTestPath = (testPath)=>{
|
|
2268
2268
|
const { dir, base } = parsePosix(testPath);
|
|
2269
|
-
return `${'.' !== dir ?
|
|
2269
|
+
return `${'.' !== dir ? logger_color.gray(`${dir}/`) : ''}${logger_color.cyan(base)}`;
|
|
2270
2270
|
};
|
|
2271
2271
|
const formatTestPath = (root, testFilePath)=>{
|
|
2272
2272
|
let testPath = testFilePath;
|
|
@@ -2304,7 +2304,7 @@ async function resolveShardedEntries(context) {
|
|
|
2304
2304
|
const shardedEntries = getShardedFiles(allTestEntriesBeforeSharding, shard);
|
|
2305
2305
|
const totalTestFileCount = allTestEntriesBeforeSharding.length;
|
|
2306
2306
|
const testFilesInShardCount = shardedEntries.length;
|
|
2307
|
-
logger_logger.log(
|
|
2307
|
+
logger_logger.log(logger_color.green(`Running shard ${shard.index} of ${shard.count} (${testFilesInShardCount} of ${totalTestFileCount} test files)\n`));
|
|
2308
2308
|
const shardedEntriesByProject = new Map();
|
|
2309
2309
|
for (const { project, alias, testPath } of shardedEntries){
|
|
2310
2310
|
if (!shardedEntriesByProject.has(project)) shardedEntriesByProject.set(project, {});
|