@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/lib/index.js CHANGED
@@ -3270,6 +3270,7 @@ var __webpack_modules__ = {
3270
3270
  console.log(` Continue on error: ${config.continueOnError}`);
3271
3271
  console.log(` Retry: ${config.retry ?? 0}`);
3272
3272
  console.log(` Share browser context: ${config.shareBrowserContext ?? false}`);
3273
+ console.log(` Reuse browser page: ${config.reusePage ?? false}`);
3273
3274
  console.log(` Summary output: ${config.summary}`);
3274
3275
  }
3275
3276
  function printExecutionFinished() {
@@ -3973,11 +3974,22 @@ var __webpack_modules__ = {
3973
3974
  }
3974
3975
  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.`);
3975
3976
  };
3976
- const createSharedBrowserRuntime = async (browser, browserContextOptions)=>{
3977
+ const createSharedBrowserRuntime = async (browser, browserContextOptions, reusePage = false)=>{
3977
3978
  const browserContext = await browser.createBrowserContext(browserContextOptions);
3978
- return {
3979
- browserContext
3980
- };
3979
+ try {
3980
+ const page = reusePage ? await browserContext.newPage() : void 0;
3981
+ return {
3982
+ browserContext,
3983
+ page
3984
+ };
3985
+ } catch (error) {
3986
+ try {
3987
+ await browserContext.close();
3988
+ } catch (cleanupError) {
3989
+ batchWarning('failed to close the shared browser context after page creation failed; preserving the original error', cleanupError);
3990
+ }
3991
+ throw error;
3992
+ }
3981
3993
  };
3982
3994
  class YamlBatchExecutor {
3983
3995
  async run(options = {}) {
@@ -4062,10 +4074,11 @@ var __webpack_modules__ = {
4062
4074
  sharedRuntime.current = null;
4063
4075
  await staleRuntime.browserContext.close();
4064
4076
  }
4065
- sharedRuntime.current = await createSharedBrowserRuntime(browser, browserContextOptions);
4077
+ sharedRuntime.current = await createSharedBrowserRuntime(browser, browserContextOptions, this.config.reusePage);
4066
4078
  for (const context of allContexts){
4067
4079
  context.options.browser = browser;
4068
4080
  context.options.browserContext = sharedRuntime.current.browserContext;
4081
+ if (sharedRuntime.current.page) context.options.page = sharedRuntime.current.page;
4069
4082
  }
4070
4083
  };
4071
4084
  await resetSetupRuntime();
@@ -4345,6 +4358,8 @@ var __webpack_modules__ = {
4345
4358
  }, (_, index)=>`batch-occurrence-${index + 1}`);
4346
4359
  if (this.caseIds.length !== occurrenceCount) throw new Error(`Batch occurrence identity mismatch: expected ${occurrenceCount} case ID(s), received ${this.caseIds.length}`);
4347
4360
  if (new Set(this.caseIds).size !== this.caseIds.length) throw new Error('Batch occurrence case IDs must be unique');
4361
+ if (config.reusePage && !config.shareBrowserContext) throw new Error('reusePage requires shareBrowserContext: true');
4362
+ if (config.reusePage && 1 !== config.concurrent) throw new Error('reusePage requires concurrent: 1');
4348
4363
  }
4349
4364
  }
4350
4365
  async function runYamlBatch(config, options = {}) {
@@ -4577,29 +4592,26 @@ defineYamlBatchTest(test, testOptions);
4577
4592
  };
4578
4593
  }
4579
4594
  var external_node_url_ = __webpack_require__("node:url");
4595
+ const error_formatter_namespaceObject = require("@midscene/shared/agent-tools/error-formatter");
4580
4596
  var progress_reporter = __webpack_require__("./src/framework/progress-reporter.ts");
4581
4597
  var rstest_contract = __webpack_require__("./src/framework/rstest-contract.ts");
4582
- const formatRunError = (error)=>error.stack || `${error.name}: ${error.message}`;
4598
+ const formatRunError = (error)=>error.stack || `${error.name || 'Error'}: ${error.message}`;
4583
4599
  const collectRunErrors = (result)=>{
4584
4600
  const messages = [];
4585
4601
  const push = (error, label)=>{
4586
4602
  const formatted = formatRunError(error);
4587
4603
  messages.push(label ? `${label}: ${formatted}` : formatted);
4588
4604
  };
4589
- for (const file of result.files ?? []){
4605
+ for (const file of result.results){
4590
4606
  for (const error of file.errors ?? [])push(error, file.name || file.testPath);
4591
4607
  for (const testResult of file.results ?? [])for (const error of testResult.errors ?? [])push(error, testResult.name);
4592
4608
  }
4593
- for (const error of result.unhandledErrors ?? [])push(error);
4609
+ for (const error of result.unhandledErrors)push(error);
4594
4610
  return Array.from(new Set(messages));
4595
4611
  };
4596
4612
  const rstest_runner_errorMessage = (error)=>error.message || error.name || 'YAML case failed';
4597
4613
  const mapRunErrorsToCases = (project, result)=>{
4598
- const casesById = new Map(project.cases.map((item)=>[
4599
- item.caseId,
4600
- item
4601
- ]));
4602
- const knownCaseIds = new Set(casesById.keys());
4614
+ const knownCaseIds = new Set(project.cases.map((item)=>item.caseId));
4603
4615
  const errors = new Map();
4604
4616
  const add = (caseId, message)=>{
4605
4617
  if (knownCaseIds.has(caseId) && message && !errors.has(caseId)) errors.set(caseId, message);
@@ -4622,7 +4634,7 @@ defineYamlBatchTest(test, testOptions);
4622
4634
  const value = testResult.meta?.[rstest_contract.k];
4623
4635
  return Array.isArray(value) ? value.filter((item)=>'string' == typeof item) : [];
4624
4636
  };
4625
- for (const file of result.files ?? []){
4637
+ for (const file of result.results){
4626
4638
  const moduleCaseIds = findModuleCaseIds(file);
4627
4639
  for (const error of file.errors ?? [])addCases(moduleCaseIds, rstest_runner_errorMessage(error));
4628
4640
  for (const testResult of file.results ?? []){
@@ -4630,18 +4642,13 @@ defineYamlBatchTest(test, testOptions);
4630
4642
  for (const error of testResult.errors ?? [])addCases(caseIds.length ? caseIds : moduleCaseIds, rstest_runner_errorMessage(error));
4631
4643
  }
4632
4644
  }
4633
- if (1 === project.modules.length && result.unhandledErrors?.length) {
4645
+ if (result.unhandledErrors.length) {
4634
4646
  const message = rstest_runner_errorMessage(result.unhandledErrors[0]);
4635
- for (const caseId of project.modules[0].caseIds){
4636
- const item = casesById.get(caseId);
4637
- if (!errors.has(caseId) || item && !(0, external_node_fs_.existsSync)(item.resultFile)) errors.set(caseId, message);
4638
- }
4647
+ for (const item of project.cases)if (!errors.has(item.caseId) && !(0, external_node_fs_.existsSync)(item.resultFile)) errors.set(item.caseId, message);
4639
4648
  }
4640
4649
  return errors;
4641
4650
  };
4642
- const recordUnreportedCaseFailures = (project, result)=>{
4643
- if (!project.cases.length) return;
4644
- const caseErrors = mapRunErrorsToCases(project, result);
4651
+ const writePendingCaseFailures = (project, caseErrors)=>{
4645
4652
  for (const item of project.cases){
4646
4653
  if ((0, external_node_fs_.existsSync)(item.resultFile)) continue;
4647
4654
  const error = caseErrors.get(item.caseId);
@@ -4663,13 +4670,13 @@ defineYamlBatchTest(test, testOptions);
4663
4670
  }
4664
4671
  };
4665
4672
  async function runRstestYamlProject(options) {
4666
- const [{ runRstest }, { rspack }] = await Promise.all([
4673
+ const [{ createRstest }, { rspack }] = await Promise.all([
4667
4674
  import("@rstest/core/api"),
4668
4675
  import((0, external_node_url_.pathToFileURL)(resolvePackageFromRstestCore('@rsbuild/core')).href)
4669
4676
  ]);
4670
4677
  const { project } = options;
4671
4678
  const maxConcurrency = void 0 !== project.maxConcurrency ? Math.max(1, project.maxConcurrency) : void 0;
4672
- const inlineConfig = {
4679
+ const config = {
4673
4680
  root: project.projectDir,
4674
4681
  include: project.modules.map((item)=>item.id),
4675
4682
  testEnvironment: 'node',
@@ -4700,18 +4707,31 @@ defineYamlBatchTest(test, testOptions);
4700
4707
  }
4701
4708
  }
4702
4709
  };
4703
- const result = await runRstest({
4704
- cwd: options.cwd || project.projectDir,
4705
- inlineConfig
4706
- });
4707
- if (!result.ok) {
4708
- recordUnreportedCaseFailures(project, result);
4710
+ let result;
4711
+ try {
4712
+ const rstest = await createRstest({
4713
+ cwd: options.cwd || project.projectDir,
4714
+ config
4715
+ });
4716
+ result = await rstest.run();
4717
+ } catch (error) {
4718
+ const serialized = (0, error_formatter_namespaceObject.serializeError)(error);
4719
+ writePendingCaseFailures(project, new Map(project.cases.map((item)=>[
4720
+ item.caseId,
4721
+ serialized.message
4722
+ ])));
4723
+ if ('pipe' !== options.stdio) console.error(`\nYAML execution failed:\n${formatRunError(serialized)}`);
4724
+ return 1;
4725
+ }
4726
+ const ok = 'pass' === result.status;
4727
+ if (!ok) {
4728
+ writePendingCaseFailures(project, mapRunErrorsToCases(project, result));
4709
4729
  if ('pipe' !== options.stdio) {
4710
4730
  const runErrors = collectRunErrors(result);
4711
4731
  if (runErrors.length) console.error(`\nYAML execution failed:\n${runErrors.join('\n\n')}`);
4712
4732
  }
4713
4733
  }
4714
- return result.ok ? 0 : 1;
4734
+ return ok ? 0 : 1;
4715
4735
  }
4716
4736
  const defaultInProcessRunner = (config)=>new BatchRunner(config).run();
4717
4737
  async function runConfigInMainProcess(config, commandOptions) {
@@ -4793,7 +4813,9 @@ defineYamlBatchTest(test, testOptions);
4793
4813
  "use strict";
4794
4814
  var core_ = __webpack_require__("@midscene/core");
4795
4815
  const cli_namespaceObject = require("@midscene/shared/cli");
4796
- var package_namespaceObject = JSON.parse('{"rE":"1.13.1-beta-20260922030100.0"}');
4816
+ var package_namespaceObject = {
4817
+ rE: "1.13.1"
4818
+ };
4797
4819
  var external_node_fs_ = __webpack_require__("node:fs");
4798
4820
  var external_node_fs_namespaceObject = /*#__PURE__*/ __webpack_require__.t(external_node_fs_, 2);
4799
4821
  var external_node_path_ = __webpack_require__("node:path");
@@ -10384,6 +10406,7 @@ defineYamlBatchTest(test, testOptions);
10384
10406
  continueOnError: false,
10385
10407
  retry: 0,
10386
10408
  shareBrowserContext: false,
10409
+ reusePage: false,
10387
10410
  headed: false,
10388
10411
  keepWindow: false,
10389
10412
  dotenvOverride: false,
@@ -10458,6 +10481,10 @@ Usage:
10458
10481
  type: 'boolean',
10459
10482
  description: `Share a Puppeteer Web browser context across multiple yaml files, default is ${config_options_defaultConfig.shareBrowserContext}`
10460
10483
  },
10484
+ 'reuse-page': {
10485
+ type: 'boolean',
10486
+ description: `Reuse one Puppeteer Web page across sequential yaml files; requires --share-browser-context and --concurrent 1, default is ${config_options_defaultConfig.reusePage}`
10487
+ },
10461
10488
  'dotenv-override': {
10462
10489
  type: 'boolean',
10463
10490
  description: `Whether the variables in the .env file override the global variables, the default is ${config_options_defaultConfig.dotenvOverride}`
@@ -10470,7 +10497,7 @@ Usage:
10470
10497
  type: 'boolean',
10471
10498
  description: 'Whether to dismiss the HarmonyOS keyboard after text input'
10472
10499
  }
10473
- }).version('version', 'Show version number', "1.13.1-beta-20260922030100.0").help().epilogue(`For complete list of configuration options, please visit:
10500
+ }).version('version', 'Show version number', "1.13.1").help().epilogue(`For complete list of configuration options, please visit:
10474
10501
  • Web options: https://midscenejs.com/automate-with-scripts-in-yaml#the-web-part
10475
10502
  • Android options: https://midscenejs.com/automate-with-scripts-in-yaml#the-android-part
10476
10503
  • HarmonyOS options: https://midscenejs.com/automate-with-scripts-in-yaml#the-harmony-part
@@ -12649,6 +12676,7 @@ Native cases/steps Test projects use the midscene-test command.`).wrap(yargs().t
12649
12676
  retry: configYaml.retry ?? config_options_defaultConfig.retry,
12650
12677
  summary: configYaml.summary ?? defaultSummary,
12651
12678
  shareBrowserContext: configYaml.shareBrowserContext ?? config_options_defaultConfig.shareBrowserContext,
12679
+ reusePage: configYaml.reusePage ?? config_options_defaultConfig.reusePage,
12652
12680
  patterns: configYaml.files,
12653
12681
  files,
12654
12682
  setup,
@@ -12676,6 +12704,7 @@ Native cases/steps Test projects use the midscene-test command.`).wrap(yargs().t
12676
12704
  setup = await resolveSetupFile(options.setup, basePath);
12677
12705
  }
12678
12706
  const shareBrowserContext = options?.shareBrowserContext ?? parsedConfig.shareBrowserContext;
12707
+ const reusePage = options?.reusePage ?? parsedConfig.reusePage;
12679
12708
  return {
12680
12709
  files,
12681
12710
  setup,
@@ -12684,6 +12713,7 @@ Native cases/steps Test projects use the midscene-test command.`).wrap(yargs().t
12684
12713
  retry: options?.retry ?? parsedConfig.retry,
12685
12714
  summary: options?.summary ?? parsedConfig.summary,
12686
12715
  shareBrowserContext,
12716
+ reusePage,
12687
12717
  headed: finalHeaded,
12688
12718
  keepWindow: keepWindow,
12689
12719
  dotenvOverride: options?.dotenvOverride ?? parsedConfig.dotenvOverride,
@@ -12700,6 +12730,7 @@ Native cases/steps Test projects use the midscene-test command.`).wrap(yargs().t
12700
12730
  const headed = options.headed ?? config_options_defaultConfig.headed;
12701
12731
  const finalHeaded = keepWindow || headed;
12702
12732
  const shareBrowserContext = options.shareBrowserContext ?? config_options_defaultConfig.shareBrowserContext;
12733
+ const reusePage = options.reusePage ?? config_options_defaultConfig.reusePage;
12703
12734
  return {
12704
12735
  files,
12705
12736
  setup,
@@ -12708,6 +12739,7 @@ Native cases/steps Test projects use the midscene-test command.`).wrap(yargs().t
12708
12739
  retry: options.retry ?? config_options_defaultConfig.retry,
12709
12740
  summary: options.summary ?? defaultSummary,
12710
12741
  shareBrowserContext,
12742
+ reusePage,
12711
12743
  headed: finalHeaded,
12712
12744
  keepWindow: keepWindow,
12713
12745
  dotenvOverride: options.dotenvOverride ?? config_options_defaultConfig.dotenvOverride,
@@ -12969,6 +13001,7 @@ Native cases/steps Test projects use the midscene-test command.`).wrap(yargs().t
12969
13001
  retry: options.retry,
12970
13002
  summary: options.summary,
12971
13003
  shareBrowserContext: options['share-browser-context'],
13004
+ reusePage: options['reuse-page'],
12972
13005
  headed: options.headed,
12973
13006
  keepWindow: options['keep-window'],
12974
13007
  dotenvOverride: options['dotenv-override'],