@midscene/cli 1.13.1-beta-20260922030100.0 → 1.13.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/dist/es/framework/index.mjs +51 -31
- package/dist/es/framework/index.mjs.map +1 -1
- package/dist/es/index.mjs +66 -33
- package/dist/es/index.mjs.map +1 -1
- package/dist/lib/framework/index.js +51 -31
- package/dist/lib/framework/index.js.map +1 -1
- package/dist/lib/index.js +66 -33
- package/dist/lib/index.js.map +1 -1
- package/dist/types/framework/index.d.ts +2 -0
- package/package.json +10 -10
|
@@ -15,6 +15,7 @@ import { stripVTControlCharacters } from "node:util";
|
|
|
15
15
|
import node_process from "node:process";
|
|
16
16
|
import { createRequire } from "node:module";
|
|
17
17
|
import { pathToFileURL } from "node:url";
|
|
18
|
+
import { serializeError } from "@midscene/shared/agent-tools/error-formatter";
|
|
18
19
|
var __webpack_modules__ = {
|
|
19
20
|
"../../node_modules/.pnpm/ansi-styles@4.3.0/node_modules/ansi-styles/index.js" (module, __unused_rspack_exports, __webpack_require__) {
|
|
20
21
|
module = __webpack_require__.nmd(module);
|
|
@@ -2635,6 +2636,7 @@ function printExecutionPlan(config) {
|
|
|
2635
2636
|
console.log(` Continue on error: ${config.continueOnError}`);
|
|
2636
2637
|
console.log(` Retry: ${config.retry ?? 0}`);
|
|
2637
2638
|
console.log(` Share browser context: ${config.shareBrowserContext ?? false}`);
|
|
2639
|
+
console.log(` Reuse browser page: ${config.reusePage ?? false}`);
|
|
2638
2640
|
console.log(` Summary output: ${config.summary}`);
|
|
2639
2641
|
}
|
|
2640
2642
|
function printExecutionFinished() {
|
|
@@ -3329,11 +3331,22 @@ const assertBrowserContextUsage = (setupContext, allContexts, shareBrowserContex
|
|
|
3329
3331
|
}
|
|
3330
3332
|
if (setupContext && !shareBrowserContext && 'puppeteer-web' === resolveBatchRuntimeTarget(setupContext.executionConfig)) throw new Error(`Puppeteer Web setup "${setupContext.file}" requires shareBrowserContext: true so its browser state can be shared with the main files.`);
|
|
3331
3333
|
};
|
|
3332
|
-
const createSharedBrowserRuntime = async (browser, browserContextOptions)=>{
|
|
3334
|
+
const createSharedBrowserRuntime = async (browser, browserContextOptions, reusePage = false)=>{
|
|
3333
3335
|
const browserContext = await browser.createBrowserContext(browserContextOptions);
|
|
3334
|
-
|
|
3335
|
-
browserContext
|
|
3336
|
-
|
|
3336
|
+
try {
|
|
3337
|
+
const page = reusePage ? await browserContext.newPage() : void 0;
|
|
3338
|
+
return {
|
|
3339
|
+
browserContext,
|
|
3340
|
+
page
|
|
3341
|
+
};
|
|
3342
|
+
} catch (error) {
|
|
3343
|
+
try {
|
|
3344
|
+
await browserContext.close();
|
|
3345
|
+
} catch (cleanupError) {
|
|
3346
|
+
batchWarning('failed to close the shared browser context after page creation failed; preserving the original error', cleanupError);
|
|
3347
|
+
}
|
|
3348
|
+
throw error;
|
|
3349
|
+
}
|
|
3337
3350
|
};
|
|
3338
3351
|
class YamlBatchExecutor {
|
|
3339
3352
|
async run(options = {}) {
|
|
@@ -3418,10 +3431,11 @@ class YamlBatchExecutor {
|
|
|
3418
3431
|
sharedRuntime.current = null;
|
|
3419
3432
|
await staleRuntime.browserContext.close();
|
|
3420
3433
|
}
|
|
3421
|
-
sharedRuntime.current = await createSharedBrowserRuntime(browser, browserContextOptions);
|
|
3434
|
+
sharedRuntime.current = await createSharedBrowserRuntime(browser, browserContextOptions, this.config.reusePage);
|
|
3422
3435
|
for (const context of allContexts){
|
|
3423
3436
|
context.options.browser = browser;
|
|
3424
3437
|
context.options.browserContext = sharedRuntime.current.browserContext;
|
|
3438
|
+
if (sharedRuntime.current.page) context.options.page = sharedRuntime.current.page;
|
|
3425
3439
|
}
|
|
3426
3440
|
};
|
|
3427
3441
|
await resetSetupRuntime();
|
|
@@ -3701,6 +3715,8 @@ class YamlBatchExecutor {
|
|
|
3701
3715
|
}, (_, index)=>`batch-occurrence-${index + 1}`);
|
|
3702
3716
|
if (this.caseIds.length !== occurrenceCount) throw new Error(`Batch occurrence identity mismatch: expected ${occurrenceCount} case ID(s), received ${this.caseIds.length}`);
|
|
3703
3717
|
if (new Set(this.caseIds).size !== this.caseIds.length) throw new Error('Batch occurrence case IDs must be unique');
|
|
3718
|
+
if (config.reusePage && !config.shareBrowserContext) throw new Error('reusePage requires shareBrowserContext: true');
|
|
3719
|
+
if (config.reusePage && 1 !== config.concurrent) throw new Error('reusePage requires concurrent: 1');
|
|
3704
3720
|
}
|
|
3705
3721
|
}
|
|
3706
3722
|
async function runYamlBatch(config, options = {}) {
|
|
@@ -3950,27 +3966,23 @@ const createYamlProgressReporter = ()=>({
|
|
|
3950
3966
|
}
|
|
3951
3967
|
});
|
|
3952
3968
|
const RSTEST_YAML_CASE_IDS_META_KEY = 'midsceneYamlCaseIds';
|
|
3953
|
-
const formatRunError = (error)=>error.stack || `${error.name}: ${error.message}`;
|
|
3969
|
+
const formatRunError = (error)=>error.stack || `${error.name || 'Error'}: ${error.message}`;
|
|
3954
3970
|
const collectRunErrors = (result)=>{
|
|
3955
3971
|
const messages = [];
|
|
3956
3972
|
const push = (error, label)=>{
|
|
3957
3973
|
const formatted = formatRunError(error);
|
|
3958
3974
|
messages.push(label ? `${label}: ${formatted}` : formatted);
|
|
3959
3975
|
};
|
|
3960
|
-
for (const file of result.
|
|
3976
|
+
for (const file of result.results){
|
|
3961
3977
|
for (const error of file.errors ?? [])push(error, file.name || file.testPath);
|
|
3962
3978
|
for (const testResult of file.results ?? [])for (const error of testResult.errors ?? [])push(error, testResult.name);
|
|
3963
3979
|
}
|
|
3964
|
-
for (const error of result.unhandledErrors
|
|
3980
|
+
for (const error of result.unhandledErrors)push(error);
|
|
3965
3981
|
return Array.from(new Set(messages));
|
|
3966
3982
|
};
|
|
3967
3983
|
const rstest_runner_errorMessage = (error)=>error.message || error.name || 'YAML case failed';
|
|
3968
3984
|
const mapRunErrorsToCases = (project, result)=>{
|
|
3969
|
-
const
|
|
3970
|
-
item.caseId,
|
|
3971
|
-
item
|
|
3972
|
-
]));
|
|
3973
|
-
const knownCaseIds = new Set(casesById.keys());
|
|
3985
|
+
const knownCaseIds = new Set(project.cases.map((item)=>item.caseId));
|
|
3974
3986
|
const errors = new Map();
|
|
3975
3987
|
const add = (caseId, message)=>{
|
|
3976
3988
|
if (knownCaseIds.has(caseId) && message && !errors.has(caseId)) errors.set(caseId, message);
|
|
@@ -3993,7 +4005,7 @@ const mapRunErrorsToCases = (project, result)=>{
|
|
|
3993
4005
|
const value = testResult.meta?.[RSTEST_YAML_CASE_IDS_META_KEY];
|
|
3994
4006
|
return Array.isArray(value) ? value.filter((item)=>'string' == typeof item) : [];
|
|
3995
4007
|
};
|
|
3996
|
-
for (const file of result.
|
|
4008
|
+
for (const file of result.results){
|
|
3997
4009
|
const moduleCaseIds = findModuleCaseIds(file);
|
|
3998
4010
|
for (const error of file.errors ?? [])addCases(moduleCaseIds, rstest_runner_errorMessage(error));
|
|
3999
4011
|
for (const testResult of file.results ?? []){
|
|
@@ -4001,18 +4013,13 @@ const mapRunErrorsToCases = (project, result)=>{
|
|
|
4001
4013
|
for (const error of testResult.errors ?? [])addCases(caseIds.length ? caseIds : moduleCaseIds, rstest_runner_errorMessage(error));
|
|
4002
4014
|
}
|
|
4003
4015
|
}
|
|
4004
|
-
if (
|
|
4016
|
+
if (result.unhandledErrors.length) {
|
|
4005
4017
|
const message = rstest_runner_errorMessage(result.unhandledErrors[0]);
|
|
4006
|
-
for (const
|
|
4007
|
-
const item = casesById.get(caseId);
|
|
4008
|
-
if (!errors.has(caseId) || item && !existsSync(item.resultFile)) errors.set(caseId, message);
|
|
4009
|
-
}
|
|
4018
|
+
for (const item of project.cases)if (!errors.has(item.caseId) && !existsSync(item.resultFile)) errors.set(item.caseId, message);
|
|
4010
4019
|
}
|
|
4011
4020
|
return errors;
|
|
4012
4021
|
};
|
|
4013
|
-
const
|
|
4014
|
-
if (!project.cases.length) return;
|
|
4015
|
-
const caseErrors = mapRunErrorsToCases(project, result);
|
|
4022
|
+
const writePendingCaseFailures = (project, caseErrors)=>{
|
|
4016
4023
|
for (const item of project.cases){
|
|
4017
4024
|
if (existsSync(item.resultFile)) continue;
|
|
4018
4025
|
const error = caseErrors.get(item.caseId);
|
|
@@ -4034,13 +4041,13 @@ const recordUnreportedCaseFailures = (project, result)=>{
|
|
|
4034
4041
|
}
|
|
4035
4042
|
};
|
|
4036
4043
|
async function runRstestYamlProject(options) {
|
|
4037
|
-
const [{
|
|
4044
|
+
const [{ createRstest }, { rspack }] = await Promise.all([
|
|
4038
4045
|
import("@rstest/core/api"),
|
|
4039
4046
|
import(pathToFileURL(resolvePackageFromRstestCore('@rsbuild/core')).href)
|
|
4040
4047
|
]);
|
|
4041
4048
|
const { project } = options;
|
|
4042
4049
|
const maxConcurrency = void 0 !== project.maxConcurrency ? Math.max(1, project.maxConcurrency) : void 0;
|
|
4043
|
-
const
|
|
4050
|
+
const config = {
|
|
4044
4051
|
root: project.projectDir,
|
|
4045
4052
|
include: project.modules.map((item)=>item.id),
|
|
4046
4053
|
testEnvironment: 'node',
|
|
@@ -4071,18 +4078,31 @@ async function runRstestYamlProject(options) {
|
|
|
4071
4078
|
}
|
|
4072
4079
|
}
|
|
4073
4080
|
};
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
|
|
4081
|
+
let result;
|
|
4082
|
+
try {
|
|
4083
|
+
const rstest = await createRstest({
|
|
4084
|
+
cwd: options.cwd || project.projectDir,
|
|
4085
|
+
config
|
|
4086
|
+
});
|
|
4087
|
+
result = await rstest.run();
|
|
4088
|
+
} catch (error) {
|
|
4089
|
+
const serialized = serializeError(error);
|
|
4090
|
+
writePendingCaseFailures(project, new Map(project.cases.map((item)=>[
|
|
4091
|
+
item.caseId,
|
|
4092
|
+
serialized.message
|
|
4093
|
+
])));
|
|
4094
|
+
if ('pipe' !== options.stdio) console.error(`\nYAML execution failed:\n${formatRunError(serialized)}`);
|
|
4095
|
+
return 1;
|
|
4096
|
+
}
|
|
4097
|
+
const ok = 'pass' === result.status;
|
|
4098
|
+
if (!ok) {
|
|
4099
|
+
writePendingCaseFailures(project, mapRunErrorsToCases(project, result));
|
|
4080
4100
|
if ('pipe' !== options.stdio) {
|
|
4081
4101
|
const runErrors = collectRunErrors(result);
|
|
4082
4102
|
if (runErrors.length) console.error(`\nYAML execution failed:\n${runErrors.join('\n\n')}`);
|
|
4083
4103
|
}
|
|
4084
4104
|
}
|
|
4085
|
-
return
|
|
4105
|
+
return ok ? 0 : 1;
|
|
4086
4106
|
}
|
|
4087
4107
|
const defaultInProcessRunner = (config)=>new BatchRunner(config).run();
|
|
4088
4108
|
async function runConfigInMainProcess(config, commandOptions) {
|