@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
package/dist/es/index.mjs
CHANGED
|
@@ -19,6 +19,7 @@ import puppeteer from "puppeteer";
|
|
|
19
19
|
import { createYamlPlayer as yaml_runtime_createYamlPlayer } from "@midscene/test/internal/yaml-runtime";
|
|
20
20
|
import { stripVTControlCharacters } from "node:util";
|
|
21
21
|
import { createRequire } from "node:module";
|
|
22
|
+
import { serializeError } from "@midscene/shared/agent-tools/error-formatter";
|
|
22
23
|
import { globalModelConfigManager } from "@midscene/shared/env";
|
|
23
24
|
import { classifyWorkflowDocumentFormat } from "@midscene/core/internal/test-runner";
|
|
24
25
|
import * as __rspack_external_assert from "assert";
|
|
@@ -3022,7 +3023,9 @@ var __webpack_modules__ = {
|
|
|
3022
3023
|
module.exports = (string, columns, options)=>String(string).normalize().replace(/\r\n/g, '\n').split('\n').map((line)=>exec(line, columns, options)).join('\n');
|
|
3023
3024
|
},
|
|
3024
3025
|
"./src/index.ts" (__unused_rspack_module, __unused_rspack___webpack_exports__, __webpack_require__) {
|
|
3025
|
-
var package_namespaceObject =
|
|
3026
|
+
var package_namespaceObject = {
|
|
3027
|
+
rE: "1.13.1"
|
|
3028
|
+
};
|
|
3026
3029
|
var brace_expansion = __webpack_require__("../../node_modules/.pnpm/brace-expansion@2.0.1/node_modules/brace-expansion/index.js");
|
|
3027
3030
|
const MAX_PATTERN_LENGTH = 65536;
|
|
3028
3031
|
const assertValidPattern = (pattern)=>{
|
|
@@ -8602,6 +8605,7 @@ var __webpack_modules__ = {
|
|
|
8602
8605
|
continueOnError: false,
|
|
8603
8606
|
retry: 0,
|
|
8604
8607
|
shareBrowserContext: false,
|
|
8608
|
+
reusePage: false,
|
|
8605
8609
|
headed: false,
|
|
8606
8610
|
keepWindow: false,
|
|
8607
8611
|
dotenvOverride: false,
|
|
@@ -8676,6 +8680,10 @@ Usage:
|
|
|
8676
8680
|
type: 'boolean',
|
|
8677
8681
|
description: `Share a Puppeteer Web browser context across multiple yaml files, default is ${config_options_defaultConfig.shareBrowserContext}`
|
|
8678
8682
|
},
|
|
8683
|
+
'reuse-page': {
|
|
8684
|
+
type: 'boolean',
|
|
8685
|
+
description: `Reuse one Puppeteer Web page across sequential yaml files; requires --share-browser-context and --concurrent 1, default is ${config_options_defaultConfig.reusePage}`
|
|
8686
|
+
},
|
|
8679
8687
|
'dotenv-override': {
|
|
8680
8688
|
type: 'boolean',
|
|
8681
8689
|
description: `Whether the variables in the .env file override the global variables, the default is ${config_options_defaultConfig.dotenvOverride}`
|
|
@@ -8688,7 +8696,7 @@ Usage:
|
|
|
8688
8696
|
type: 'boolean',
|
|
8689
8697
|
description: 'Whether to dismiss the HarmonyOS keyboard after text input'
|
|
8690
8698
|
}
|
|
8691
|
-
}).version('version', 'Show version number', "1.13.1
|
|
8699
|
+
}).version('version', 'Show version number', "1.13.1").help().epilogue(`For complete list of configuration options, please visit:
|
|
8692
8700
|
• Web options: https://midscenejs.com/automate-with-scripts-in-yaml#the-web-part
|
|
8693
8701
|
• Android options: https://midscenejs.com/automate-with-scripts-in-yaml#the-android-part
|
|
8694
8702
|
• HarmonyOS options: https://midscenejs.com/automate-with-scripts-in-yaml#the-harmony-part
|
|
@@ -10864,6 +10872,7 @@ Native cases/steps Test projects use the midscene-test command.`).wrap(yargs().t
|
|
|
10864
10872
|
retry: configYaml.retry ?? config_options_defaultConfig.retry,
|
|
10865
10873
|
summary: configYaml.summary ?? defaultSummary,
|
|
10866
10874
|
shareBrowserContext: configYaml.shareBrowserContext ?? config_options_defaultConfig.shareBrowserContext,
|
|
10875
|
+
reusePage: configYaml.reusePage ?? config_options_defaultConfig.reusePage,
|
|
10867
10876
|
patterns: configYaml.files,
|
|
10868
10877
|
files,
|
|
10869
10878
|
setup,
|
|
@@ -10891,6 +10900,7 @@ Native cases/steps Test projects use the midscene-test command.`).wrap(yargs().t
|
|
|
10891
10900
|
setup = await resolveSetupFile(options.setup, basePath);
|
|
10892
10901
|
}
|
|
10893
10902
|
const shareBrowserContext = options?.shareBrowserContext ?? parsedConfig.shareBrowserContext;
|
|
10903
|
+
const reusePage = options?.reusePage ?? parsedConfig.reusePage;
|
|
10894
10904
|
return {
|
|
10895
10905
|
files,
|
|
10896
10906
|
setup,
|
|
@@ -10899,6 +10909,7 @@ Native cases/steps Test projects use the midscene-test command.`).wrap(yargs().t
|
|
|
10899
10909
|
retry: options?.retry ?? parsedConfig.retry,
|
|
10900
10910
|
summary: options?.summary ?? parsedConfig.summary,
|
|
10901
10911
|
shareBrowserContext,
|
|
10912
|
+
reusePage,
|
|
10902
10913
|
headed: finalHeaded,
|
|
10903
10914
|
keepWindow: keepWindow,
|
|
10904
10915
|
dotenvOverride: options?.dotenvOverride ?? parsedConfig.dotenvOverride,
|
|
@@ -10915,6 +10926,7 @@ Native cases/steps Test projects use the midscene-test command.`).wrap(yargs().t
|
|
|
10915
10926
|
const headed = options.headed ?? config_options_defaultConfig.headed;
|
|
10916
10927
|
const finalHeaded = keepWindow || headed;
|
|
10917
10928
|
const shareBrowserContext = options.shareBrowserContext ?? config_options_defaultConfig.shareBrowserContext;
|
|
10929
|
+
const reusePage = options.reusePage ?? config_options_defaultConfig.reusePage;
|
|
10918
10930
|
return {
|
|
10919
10931
|
files,
|
|
10920
10932
|
setup,
|
|
@@ -10923,6 +10935,7 @@ Native cases/steps Test projects use the midscene-test command.`).wrap(yargs().t
|
|
|
10923
10935
|
retry: options.retry ?? config_options_defaultConfig.retry,
|
|
10924
10936
|
summary: options.summary ?? defaultSummary,
|
|
10925
10937
|
shareBrowserContext,
|
|
10938
|
+
reusePage,
|
|
10926
10939
|
headed: finalHeaded,
|
|
10927
10940
|
keepWindow: keepWindow,
|
|
10928
10941
|
dotenvOverride: options.dotenvOverride ?? config_options_defaultConfig.dotenvOverride,
|
|
@@ -11194,6 +11207,7 @@ Native cases/steps Test projects use the midscene-test command.`).wrap(yargs().t
|
|
|
11194
11207
|
console.log(` Continue on error: ${config.continueOnError}`);
|
|
11195
11208
|
console.log(` Retry: ${config.retry ?? 0}`);
|
|
11196
11209
|
console.log(` Share browser context: ${config.shareBrowserContext ?? false}`);
|
|
11210
|
+
console.log(` Reuse browser page: ${config.reusePage ?? false}`);
|
|
11197
11211
|
console.log(` Summary output: ${config.summary}`);
|
|
11198
11212
|
}
|
|
11199
11213
|
function printExecutionFinished() {
|
|
@@ -11888,11 +11902,22 @@ Native cases/steps Test projects use the midscene-test command.`).wrap(yargs().t
|
|
|
11888
11902
|
}
|
|
11889
11903
|
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.`);
|
|
11890
11904
|
};
|
|
11891
|
-
const createSharedBrowserRuntime = async (browser, browserContextOptions)=>{
|
|
11905
|
+
const createSharedBrowserRuntime = async (browser, browserContextOptions, reusePage = false)=>{
|
|
11892
11906
|
const browserContext = await browser.createBrowserContext(browserContextOptions);
|
|
11893
|
-
|
|
11894
|
-
browserContext
|
|
11895
|
-
|
|
11907
|
+
try {
|
|
11908
|
+
const page = reusePage ? await browserContext.newPage() : void 0;
|
|
11909
|
+
return {
|
|
11910
|
+
browserContext,
|
|
11911
|
+
page
|
|
11912
|
+
};
|
|
11913
|
+
} catch (error) {
|
|
11914
|
+
try {
|
|
11915
|
+
await browserContext.close();
|
|
11916
|
+
} catch (cleanupError) {
|
|
11917
|
+
batchWarning('failed to close the shared browser context after page creation failed; preserving the original error', cleanupError);
|
|
11918
|
+
}
|
|
11919
|
+
throw error;
|
|
11920
|
+
}
|
|
11896
11921
|
};
|
|
11897
11922
|
class YamlBatchExecutor {
|
|
11898
11923
|
async run(options = {}) {
|
|
@@ -11977,10 +12002,11 @@ Native cases/steps Test projects use the midscene-test command.`).wrap(yargs().t
|
|
|
11977
12002
|
sharedRuntime.current = null;
|
|
11978
12003
|
await staleRuntime.browserContext.close();
|
|
11979
12004
|
}
|
|
11980
|
-
sharedRuntime.current = await createSharedBrowserRuntime(browser, browserContextOptions);
|
|
12005
|
+
sharedRuntime.current = await createSharedBrowserRuntime(browser, browserContextOptions, this.config.reusePage);
|
|
11981
12006
|
for (const context of allContexts){
|
|
11982
12007
|
context.options.browser = browser;
|
|
11983
12008
|
context.options.browserContext = sharedRuntime.current.browserContext;
|
|
12009
|
+
if (sharedRuntime.current.page) context.options.page = sharedRuntime.current.page;
|
|
11984
12010
|
}
|
|
11985
12011
|
};
|
|
11986
12012
|
await resetSetupRuntime();
|
|
@@ -12260,6 +12286,8 @@ Native cases/steps Test projects use the midscene-test command.`).wrap(yargs().t
|
|
|
12260
12286
|
}, (_, index)=>`batch-occurrence-${index + 1}`);
|
|
12261
12287
|
if (this.caseIds.length !== occurrenceCount) throw new Error(`Batch occurrence identity mismatch: expected ${occurrenceCount} case ID(s), received ${this.caseIds.length}`);
|
|
12262
12288
|
if (new Set(this.caseIds).size !== this.caseIds.length) throw new Error('Batch occurrence case IDs must be unique');
|
|
12289
|
+
if (config.reusePage && !config.shareBrowserContext) throw new Error('reusePage requires shareBrowserContext: true');
|
|
12290
|
+
if (config.reusePage && 1 !== config.concurrent) throw new Error('reusePage requires concurrent: 1');
|
|
12263
12291
|
}
|
|
12264
12292
|
}
|
|
12265
12293
|
async function runYamlBatch(config, options = {}) {
|
|
@@ -12503,27 +12531,23 @@ defineYamlBatchTest(test, testOptions);
|
|
|
12503
12531
|
}
|
|
12504
12532
|
});
|
|
12505
12533
|
const rstest_contract_RSTEST_YAML_CASE_IDS_META_KEY = 'midsceneYamlCaseIds';
|
|
12506
|
-
const formatRunError = (error)=>error.stack || `${error.name}: ${error.message}`;
|
|
12534
|
+
const formatRunError = (error)=>error.stack || `${error.name || 'Error'}: ${error.message}`;
|
|
12507
12535
|
const collectRunErrors = (result)=>{
|
|
12508
12536
|
const messages = [];
|
|
12509
12537
|
const push = (error, label)=>{
|
|
12510
12538
|
const formatted = formatRunError(error);
|
|
12511
12539
|
messages.push(label ? `${label}: ${formatted}` : formatted);
|
|
12512
12540
|
};
|
|
12513
|
-
for (const file of result.
|
|
12541
|
+
for (const file of result.results){
|
|
12514
12542
|
for (const error of file.errors ?? [])push(error, file.name || file.testPath);
|
|
12515
12543
|
for (const testResult of file.results ?? [])for (const error of testResult.errors ?? [])push(error, testResult.name);
|
|
12516
12544
|
}
|
|
12517
|
-
for (const error of result.unhandledErrors
|
|
12545
|
+
for (const error of result.unhandledErrors)push(error);
|
|
12518
12546
|
return Array.from(new Set(messages));
|
|
12519
12547
|
};
|
|
12520
12548
|
const rstest_runner_errorMessage = (error)=>error.message || error.name || 'YAML case failed';
|
|
12521
12549
|
const mapRunErrorsToCases = (project, result)=>{
|
|
12522
|
-
const
|
|
12523
|
-
item.caseId,
|
|
12524
|
-
item
|
|
12525
|
-
]));
|
|
12526
|
-
const knownCaseIds = new Set(casesById.keys());
|
|
12550
|
+
const knownCaseIds = new Set(project.cases.map((item)=>item.caseId));
|
|
12527
12551
|
const errors = new Map();
|
|
12528
12552
|
const add = (caseId, message)=>{
|
|
12529
12553
|
if (knownCaseIds.has(caseId) && message && !errors.has(caseId)) errors.set(caseId, message);
|
|
@@ -12546,7 +12570,7 @@ defineYamlBatchTest(test, testOptions);
|
|
|
12546
12570
|
const value = testResult.meta?.[rstest_contract_RSTEST_YAML_CASE_IDS_META_KEY];
|
|
12547
12571
|
return Array.isArray(value) ? value.filter((item)=>'string' == typeof item) : [];
|
|
12548
12572
|
};
|
|
12549
|
-
for (const file of result.
|
|
12573
|
+
for (const file of result.results){
|
|
12550
12574
|
const moduleCaseIds = findModuleCaseIds(file);
|
|
12551
12575
|
for (const error of file.errors ?? [])addCases(moduleCaseIds, rstest_runner_errorMessage(error));
|
|
12552
12576
|
for (const testResult of file.results ?? []){
|
|
@@ -12554,18 +12578,13 @@ defineYamlBatchTest(test, testOptions);
|
|
|
12554
12578
|
for (const error of testResult.errors ?? [])addCases(caseIds.length ? caseIds : moduleCaseIds, rstest_runner_errorMessage(error));
|
|
12555
12579
|
}
|
|
12556
12580
|
}
|
|
12557
|
-
if (
|
|
12581
|
+
if (result.unhandledErrors.length) {
|
|
12558
12582
|
const message = rstest_runner_errorMessage(result.unhandledErrors[0]);
|
|
12559
|
-
for (const
|
|
12560
|
-
const item = casesById.get(caseId);
|
|
12561
|
-
if (!errors.has(caseId) || item && !(0, __rspack_external_node_fs_5ea92f0c.existsSync)(item.resultFile)) errors.set(caseId, message);
|
|
12562
|
-
}
|
|
12583
|
+
for (const item of project.cases)if (!errors.has(item.caseId) && !(0, __rspack_external_node_fs_5ea92f0c.existsSync)(item.resultFile)) errors.set(item.caseId, message);
|
|
12563
12584
|
}
|
|
12564
12585
|
return errors;
|
|
12565
12586
|
};
|
|
12566
|
-
const
|
|
12567
|
-
if (!project.cases.length) return;
|
|
12568
|
-
const caseErrors = mapRunErrorsToCases(project, result);
|
|
12587
|
+
const writePendingCaseFailures = (project, caseErrors)=>{
|
|
12569
12588
|
for (const item of project.cases){
|
|
12570
12589
|
if ((0, __rspack_external_node_fs_5ea92f0c.existsSync)(item.resultFile)) continue;
|
|
12571
12590
|
const error = caseErrors.get(item.caseId);
|
|
@@ -12587,13 +12606,13 @@ defineYamlBatchTest(test, testOptions);
|
|
|
12587
12606
|
}
|
|
12588
12607
|
};
|
|
12589
12608
|
async function runRstestYamlProject(options) {
|
|
12590
|
-
const [{
|
|
12609
|
+
const [{ createRstest }, { rspack }] = await Promise.all([
|
|
12591
12610
|
import("@rstest/core/api"),
|
|
12592
12611
|
import(pathToFileURL(resolvePackageFromRstestCore('@rsbuild/core')).href)
|
|
12593
12612
|
]);
|
|
12594
12613
|
const { project } = options;
|
|
12595
12614
|
const maxConcurrency = void 0 !== project.maxConcurrency ? Math.max(1, project.maxConcurrency) : void 0;
|
|
12596
|
-
const
|
|
12615
|
+
const config = {
|
|
12597
12616
|
root: project.projectDir,
|
|
12598
12617
|
include: project.modules.map((item)=>item.id),
|
|
12599
12618
|
testEnvironment: 'node',
|
|
@@ -12624,18 +12643,31 @@ defineYamlBatchTest(test, testOptions);
|
|
|
12624
12643
|
}
|
|
12625
12644
|
}
|
|
12626
12645
|
};
|
|
12627
|
-
|
|
12628
|
-
|
|
12629
|
-
|
|
12630
|
-
|
|
12631
|
-
|
|
12632
|
-
|
|
12646
|
+
let result;
|
|
12647
|
+
try {
|
|
12648
|
+
const rstest = await createRstest({
|
|
12649
|
+
cwd: options.cwd || project.projectDir,
|
|
12650
|
+
config
|
|
12651
|
+
});
|
|
12652
|
+
result = await rstest.run();
|
|
12653
|
+
} catch (error) {
|
|
12654
|
+
const serialized = serializeError(error);
|
|
12655
|
+
writePendingCaseFailures(project, new Map(project.cases.map((item)=>[
|
|
12656
|
+
item.caseId,
|
|
12657
|
+
serialized.message
|
|
12658
|
+
])));
|
|
12659
|
+
if ('pipe' !== options.stdio) console.error(`\nYAML execution failed:\n${formatRunError(serialized)}`);
|
|
12660
|
+
return 1;
|
|
12661
|
+
}
|
|
12662
|
+
const ok = 'pass' === result.status;
|
|
12663
|
+
if (!ok) {
|
|
12664
|
+
writePendingCaseFailures(project, mapRunErrorsToCases(project, result));
|
|
12633
12665
|
if ('pipe' !== options.stdio) {
|
|
12634
12666
|
const runErrors = collectRunErrors(result);
|
|
12635
12667
|
if (runErrors.length) console.error(`\nYAML execution failed:\n${runErrors.join('\n\n')}`);
|
|
12636
12668
|
}
|
|
12637
12669
|
}
|
|
12638
|
-
return
|
|
12670
|
+
return ok ? 0 : 1;
|
|
12639
12671
|
}
|
|
12640
12672
|
const defaultInProcessRunner = (config)=>new BatchRunner(config).run();
|
|
12641
12673
|
async function runConfigInMainProcess(config, commandOptions) {
|
|
@@ -12928,6 +12960,7 @@ defineYamlBatchTest(test, testOptions);
|
|
|
12928
12960
|
retry: options.retry,
|
|
12929
12961
|
summary: options.summary,
|
|
12930
12962
|
shareBrowserContext: options['share-browser-context'],
|
|
12963
|
+
reusePage: options['reuse-page'],
|
|
12931
12964
|
headed: options.headed,
|
|
12932
12965
|
keepWindow: options['keep-window'],
|
|
12933
12966
|
dotenvOverride: options['dotenv-override'],
|