@midscene/web 0.11.1 → 0.11.2

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.
Files changed (36) hide show
  1. package/dist/es/appium.js +84 -39
  2. package/dist/es/bridge-mode-browser.js +58 -19
  3. package/dist/es/bridge-mode.js +61 -43
  4. package/dist/es/chrome-extension.js +104 -51
  5. package/dist/es/index.js +291 -218
  6. package/dist/es/midscene-playground.js +56 -38
  7. package/dist/es/playground.js +56 -38
  8. package/dist/es/playwright.js +251 -203
  9. package/dist/es/puppeteer.js +85 -60
  10. package/dist/es/ui-utils.js +43 -0
  11. package/dist/lib/appium.js +84 -39
  12. package/dist/lib/bridge-mode-browser.js +58 -19
  13. package/dist/lib/bridge-mode.js +61 -43
  14. package/dist/lib/chrome-extension.js +104 -51
  15. package/dist/lib/index.js +291 -218
  16. package/dist/lib/midscene-playground.js +56 -38
  17. package/dist/lib/playground.js +56 -38
  18. package/dist/lib/playwright.js +251 -203
  19. package/dist/lib/puppeteer.js +85 -60
  20. package/dist/lib/ui-utils.js +43 -0
  21. package/dist/types/{tasks-d5a01262.d.ts → agent-ac363fa3.d.ts} +41 -41
  22. package/dist/types/appium.d.ts +2 -2
  23. package/dist/types/bridge-mode-browser.d.ts +2 -2
  24. package/dist/types/bridge-mode.d.ts +3 -3
  25. package/dist/types/{browser-7d5614fb.d.ts → browser-eae1a5c1.d.ts} +4 -4
  26. package/dist/types/chrome-extension.d.ts +3 -3
  27. package/dist/types/index.d.ts +8 -8
  28. package/dist/types/{page-77af8d5f.d.ts → page-cf0f892e.d.ts} +32 -6
  29. package/dist/types/playground.d.ts +3 -3
  30. package/dist/types/playwright.d.ts +12 -6
  31. package/dist/types/puppeteer.d.ts +2 -2
  32. package/dist/types/ui-utils.d.ts +6 -1
  33. package/dist/types/{utils-1a3bc661.d.ts → utils-9a29bfa0.d.ts} +1 -1
  34. package/dist/types/utils.d.ts +1 -1
  35. package/dist/types/yaml.d.ts +3 -3
  36. package/package.json +6 -6
@@ -328,16 +328,13 @@ var require_dayjs_min = __commonJS({
328
328
  // src/playwright/index.ts
329
329
  var playwright_exports = {};
330
330
  __export(playwright_exports, {
331
- PlaywrightAgent: () => PageAgent,
331
+ PlaywrightAgent: () => PlaywrightAgent,
332
332
  PlaywrightAiFixture: () => PlaywrightAiFixture,
333
333
  PlaywrightWebPage: () => WebPage,
334
334
  overrideAIConfig: () => import_env4.overrideAIConfig
335
335
  });
336
336
  module.exports = __toCommonJS(playwright_exports);
337
337
 
338
- // src/playwright/ai-fixture.ts
339
- var import_node_crypto = require("crypto");
340
-
341
338
  // src/common/agent.ts
342
339
  var import_core2 = require("@midscene/core");
343
340
  var import_constants2 = require("@midscene/shared/constants");
@@ -3367,7 +3364,9 @@ var TaskCache = class {
3367
3364
  if (!this.midscenePkgInfo) {
3368
3365
  return void 0;
3369
3366
  }
3370
- if (jsonData.pkgName !== this.midscenePkgInfo.name || jsonData.pkgVersion !== this.midscenePkgInfo.version) {
3367
+ const jsonDataPkgVersion = jsonData.pkgVersion.split(".");
3368
+ const midscenePkgInfoPkgVersion = this.midscenePkgInfo.version.split(".");
3369
+ if (jsonDataPkgVersion[0] !== midscenePkgInfoPkgVersion[0] || jsonDataPkgVersion[1] !== midscenePkgInfoPkgVersion[1]) {
3371
3370
  return void 0;
3372
3371
  }
3373
3372
  return jsonData;
@@ -3401,6 +3400,56 @@ var TaskCache = class {
3401
3400
  }
3402
3401
  };
3403
3402
 
3403
+ // src/common/ui-utils.ts
3404
+ function typeStr(task) {
3405
+ return task.subType ? `${task.type} / ${task.subType || ""}` : task.type;
3406
+ }
3407
+ function getKeyCommands(value) {
3408
+ const keys = Array.isArray(value) ? value : [value];
3409
+ return keys.reduce((acc, k) => {
3410
+ const includeMeta = keys.includes("Meta") || keys.includes("Control");
3411
+ if (includeMeta && (k === "a" || k === "A")) {
3412
+ return acc.concat([{ key: k, command: "SelectAll" }]);
3413
+ }
3414
+ if (includeMeta && (k === "c" || k === "C")) {
3415
+ return acc.concat([{ key: k, command: "Copy" }]);
3416
+ }
3417
+ if (includeMeta && (k === "v" || k === "V")) {
3418
+ return acc.concat([{ key: k, command: "Paste" }]);
3419
+ }
3420
+ return acc.concat([{ key: k }]);
3421
+ }, []);
3422
+ }
3423
+ function paramStr(task) {
3424
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
3425
+ let value;
3426
+ if (task.type === "Planning") {
3427
+ value = (_a = task == null ? void 0 : task.param) == null ? void 0 : _a.userPrompt;
3428
+ }
3429
+ if (task.type === "Insight") {
3430
+ value = ((_b = task == null ? void 0 : task.param) == null ? void 0 : _b.prompt) || ((_c = task == null ? void 0 : task.param) == null ? void 0 : _c.id) || ((_d = task == null ? void 0 : task.param) == null ? void 0 : _d.dataDemand) || ((_e = task == null ? void 0 : task.param) == null ? void 0 : _e.assertion);
3431
+ }
3432
+ if (task.type === "Action") {
3433
+ const sleepMs = (_f = task == null ? void 0 : task.param) == null ? void 0 : _f.timeMs;
3434
+ const scrollType = (_g = task == null ? void 0 : task.param) == null ? void 0 : _g.scrollType;
3435
+ if (sleepMs) {
3436
+ value = `${sleepMs}ms`;
3437
+ } else if (scrollType) {
3438
+ const scrollDirection = (_h = task == null ? void 0 : task.param) == null ? void 0 : _h.direction;
3439
+ const scrollDistance = (_i = task == null ? void 0 : task.param) == null ? void 0 : _i.distance;
3440
+ value = `${scrollDirection || "down"}, ${scrollType || "once"}, ${scrollDistance || "distance-not-set"}`;
3441
+ } else {
3442
+ value = ((_j = task == null ? void 0 : task.param) == null ? void 0 : _j.value) || ((_k = task == null ? void 0 : task.param) == null ? void 0 : _k.scrollType);
3443
+ }
3444
+ if (!value) {
3445
+ value = task.thought;
3446
+ }
3447
+ }
3448
+ if (typeof value === "undefined")
3449
+ return "";
3450
+ return typeof value === "string" ? value : JSON.stringify(value, void 0, 2);
3451
+ }
3452
+
3404
3453
  // src/common/tasks.ts
3405
3454
  var PageTaskExecutor = class {
3406
3455
  constructor(page, insight, opts) {
@@ -3614,8 +3663,8 @@ var PageTaskExecutor = class {
3614
3663
  thought: plan2.thought,
3615
3664
  locate: plan2.locate,
3616
3665
  executor: async (taskParam) => {
3617
- (0, import_node_assert3.default)(taskParam == null ? void 0 : taskParam.value, "No key to press");
3618
- await this.page.keyboard.press(taskParam.value);
3666
+ const keys = getKeyCommands(taskParam.value);
3667
+ await this.page.keyboard.press(keys);
3619
3668
  }
3620
3669
  };
3621
3670
  tasks.push(taskActionKeyboardPress);
@@ -4023,7 +4072,7 @@ var PageTaskExecutor = class {
4023
4072
  const cacheGroup = this.taskCache.getCacheGroupByPrompt(userPrompt);
4024
4073
  const isCompleted = false;
4025
4074
  let currentActionNumber = 0;
4026
- const maxActionNumber = 20;
4075
+ const maxActionNumber = 40;
4027
4076
  while (!isCompleted && currentActionNumber < maxActionNumber) {
4028
4077
  currentActionNumber++;
4029
4078
  const planningTask = this.planningTaskToGoal(
@@ -4243,40 +4292,6 @@ var WebElementInfo = class {
4243
4292
  }
4244
4293
  };
4245
4294
 
4246
- // src/common/ui-utils.ts
4247
- function typeStr(task) {
4248
- return task.subType ? `${task.type} / ${task.subType || ""}` : task.type;
4249
- }
4250
- function paramStr(task) {
4251
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
4252
- let value;
4253
- if (task.type === "Planning") {
4254
- value = (_a = task == null ? void 0 : task.param) == null ? void 0 : _a.userPrompt;
4255
- }
4256
- if (task.type === "Insight") {
4257
- value = ((_b = task == null ? void 0 : task.param) == null ? void 0 : _b.prompt) || ((_c = task == null ? void 0 : task.param) == null ? void 0 : _c.id) || ((_d = task == null ? void 0 : task.param) == null ? void 0 : _d.dataDemand) || ((_e = task == null ? void 0 : task.param) == null ? void 0 : _e.assertion);
4258
- }
4259
- if (task.type === "Action") {
4260
- const sleepMs = (_f = task == null ? void 0 : task.param) == null ? void 0 : _f.timeMs;
4261
- const scrollType = (_g = task == null ? void 0 : task.param) == null ? void 0 : _g.scrollType;
4262
- if (sleepMs) {
4263
- value = `${sleepMs}ms`;
4264
- } else if (scrollType) {
4265
- const scrollDirection = (_h = task == null ? void 0 : task.param) == null ? void 0 : _h.direction;
4266
- const scrollDistance = (_i = task == null ? void 0 : task.param) == null ? void 0 : _i.distance;
4267
- value = `${scrollDirection || "down"}, ${scrollType || "once"}, ${scrollDistance || "distance-not-set"}`;
4268
- } else {
4269
- value = ((_j = task == null ? void 0 : task.param) == null ? void 0 : _j.value) || ((_k = task == null ? void 0 : task.param) == null ? void 0 : _k.scrollType);
4270
- }
4271
- if (!value) {
4272
- value = task.thought;
4273
- }
4274
- }
4275
- if (typeof value === "undefined")
4276
- return "";
4277
- return typeof value === "string" ? value : JSON.stringify(value, void 0, 2);
4278
- }
4279
-
4280
4295
  // src/common/utils.ts
4281
4296
  var import_node_assert4 = __toESM(require("assert"));
4282
4297
  var import_node_fs3 = require("fs");
@@ -4569,160 +4584,6 @@ ${errors}`);
4569
4584
  }
4570
4585
  };
4571
4586
 
4572
- // src/playwright/ai-fixture.ts
4573
- var import_test = require("@playwright/test");
4574
- var groupAndCaseForTest = (testInfo) => {
4575
- let taskFile;
4576
- let taskTitle;
4577
- const titlePath = [...testInfo.titlePath];
4578
- if (titlePath.length > 1) {
4579
- taskTitle = titlePath.pop() || "unnamed";
4580
- taskFile = `${titlePath.join(" > ")}`;
4581
- } else if (titlePath.length === 1) {
4582
- taskTitle = titlePath[0];
4583
- taskFile = `${taskTitle}`;
4584
- } else {
4585
- taskTitle = "unnamed";
4586
- taskFile = "unnamed";
4587
- }
4588
- return { taskFile, taskTitle };
4589
- };
4590
- var midsceneAgentKeyId = "_midsceneAgentId";
4591
- var midsceneDumpAnnotationId = "MIDSCENE_DUMP_ANNOTATION";
4592
- var PlaywrightAiFixture = () => {
4593
- const pageAgentMap = {};
4594
- const agentForPage = (page, testInfo) => {
4595
- let idForPage = page[midsceneAgentKeyId];
4596
- if (!idForPage) {
4597
- idForPage = (0, import_node_crypto.randomUUID)();
4598
- page[midsceneAgentKeyId] = idForPage;
4599
- const { testId } = testInfo;
4600
- const { taskFile, taskTitle } = groupAndCaseForTest(testInfo);
4601
- pageAgentMap[idForPage] = new PageAgent(new WebPage(page), {
4602
- testId: `playwright-${testId}-${idForPage}`,
4603
- cacheId: `${taskFile}(${taskTitle})`,
4604
- groupName: taskTitle,
4605
- groupDescription: taskFile,
4606
- generateReport: false
4607
- // we will generate it in the reporter
4608
- });
4609
- }
4610
- return pageAgentMap[idForPage];
4611
- };
4612
- const updateDumpAnnotation = (test2, dump2) => {
4613
- const currentAnnotation = test2.annotations.find((item) => {
4614
- return item.type === midsceneDumpAnnotationId;
4615
- });
4616
- if (currentAnnotation) {
4617
- currentAnnotation.description = dump2;
4618
- } else {
4619
- test2.annotations.push({
4620
- type: midsceneDumpAnnotationId,
4621
- description: dump2
4622
- });
4623
- }
4624
- };
4625
- return {
4626
- ai: async ({ page }, use, testInfo) => {
4627
- const agent = agentForPage(page, testInfo);
4628
- await use(
4629
- async (taskPrompt, opts) => {
4630
- return new Promise((resolve, reject) => {
4631
- import_test.test.step(`ai - ${taskPrompt}`, async () => {
4632
- await waitForNetworkIdle(page);
4633
- const actionType = (opts == null ? void 0 : opts.type) || "action";
4634
- try {
4635
- const result = await agent.ai(taskPrompt, actionType);
4636
- resolve(result);
4637
- } catch (error) {
4638
- reject(error);
4639
- }
4640
- });
4641
- });
4642
- }
4643
- );
4644
- updateDumpAnnotation(testInfo, agent.dumpDataString());
4645
- },
4646
- aiAction: async ({ page }, use, testInfo) => {
4647
- const agent = agentForPage(page, testInfo);
4648
- await use(async (taskPrompt) => {
4649
- return new Promise((resolve, reject) => {
4650
- import_test.test.step(`aiAction - ${taskPrompt}`, async () => {
4651
- await waitForNetworkIdle(page);
4652
- try {
4653
- const result = await agent.aiAction(taskPrompt);
4654
- resolve(result);
4655
- } catch (error) {
4656
- reject(error);
4657
- }
4658
- });
4659
- });
4660
- });
4661
- updateDumpAnnotation(testInfo, agent.dumpDataString());
4662
- },
4663
- aiQuery: async ({ page }, use, testInfo) => {
4664
- const agent = agentForPage(page, testInfo);
4665
- await use(async (demand) => {
4666
- return new Promise((resolve, reject) => {
4667
- import_test.test.step(`aiQuery - ${JSON.stringify(demand)}`, async () => {
4668
- await waitForNetworkIdle(page);
4669
- try {
4670
- const result = await agent.aiQuery(demand);
4671
- resolve(result);
4672
- } catch (error) {
4673
- reject(error);
4674
- }
4675
- });
4676
- });
4677
- });
4678
- updateDumpAnnotation(testInfo, agent.dumpDataString());
4679
- },
4680
- aiAssert: async ({ page }, use, testInfo) => {
4681
- const agent = agentForPage(page, testInfo);
4682
- await use(async (assertion, errorMsg) => {
4683
- return new Promise((resolve, reject) => {
4684
- import_test.test.step(`aiAssert - ${assertion}`, async () => {
4685
- await waitForNetworkIdle(page);
4686
- try {
4687
- await agent.aiAssert(assertion, errorMsg);
4688
- resolve(null);
4689
- } catch (error) {
4690
- reject(error);
4691
- }
4692
- });
4693
- });
4694
- });
4695
- updateDumpAnnotation(testInfo, agent.dumpDataString());
4696
- },
4697
- aiWaitFor: async ({ page }, use, testInfo) => {
4698
- const agent = agentForPage(page, testInfo);
4699
- await use(async (assertion, opt) => {
4700
- return new Promise((resolve, reject) => {
4701
- import_test.test.step(`aiWaitFor - ${assertion}`, async () => {
4702
- await waitForNetworkIdle(page);
4703
- try {
4704
- await agent.aiWaitFor(assertion, opt);
4705
- resolve(null);
4706
- } catch (error) {
4707
- reject(error);
4708
- }
4709
- });
4710
- });
4711
- });
4712
- updateDumpAnnotation(testInfo, agent.dumpDataString());
4713
- }
4714
- };
4715
- };
4716
- async function waitForNetworkIdle(page, timeout = 2e4) {
4717
- try {
4718
- await page.waitForLoadState("networkidle", { timeout });
4719
- } catch (error) {
4720
- console.warn(
4721
- `Network idle timeout exceeded: ${error instanceof Error ? error.message : String(error)}`
4722
- );
4723
- }
4724
- }
4725
-
4726
4587
  // src/puppeteer/base-page.ts
4727
4588
  var import_utils9 = require("@midscene/core/utils");
4728
4589
  var import_extractor2 = require("@midscene/shared/extractor");
@@ -4738,12 +4599,19 @@ var Page = class {
4738
4599
  this.underlyingPage = underlyingPage;
4739
4600
  this.pageType = pageType;
4740
4601
  }
4602
+ async waitForNavigation() {
4603
+ if (this.pageType === "puppeteer" || this.pageType === "playwright") {
4604
+ await this.underlyingPage.waitForSelector("html");
4605
+ }
4606
+ }
4741
4607
  // @deprecated
4742
4608
  async getElementsInfo() {
4609
+ await this.waitForNavigation();
4743
4610
  const tree = await this.getElementsNodeTree();
4744
4611
  return (0, import_extractor2.treeToList)(tree);
4745
4612
  }
4746
4613
  async getElementsNodeTree() {
4614
+ await this.waitForNavigation();
4747
4615
  const scripts = await getExtraReturnLogic(true);
4748
4616
  const captureElementSnapshot = await this.evaluate(scripts);
4749
4617
  return captureElementSnapshot;
@@ -4764,6 +4632,7 @@ var Page = class {
4764
4632
  async screenshotBase64() {
4765
4633
  const imgType = "jpeg";
4766
4634
  const path2 = (0, import_utils9.getTmpFile)(imgType);
4635
+ await this.waitForNavigation();
4767
4636
  await this.underlyingPage.screenshot({
4768
4637
  path: path2,
4769
4638
  type: imgType,
@@ -4821,13 +4690,14 @@ var Page = class {
4821
4690
  get keyboard() {
4822
4691
  return {
4823
4692
  type: async (text) => this.underlyingPage.keyboard.type(text, { delay: 80 }),
4824
- press: async (key) => {
4825
- const keys = Array.isArray(key) ? key : [key];
4826
- for (const key2 of keys) {
4827
- await this.underlyingPage.keyboard.down(key2);
4693
+ press: async (action) => {
4694
+ const keys = Array.isArray(action) ? action : [action];
4695
+ for (const k of keys) {
4696
+ const commands = k.command ? [k.command] : [];
4697
+ await this.underlyingPage.keyboard.down(k.key, { commands });
4828
4698
  }
4829
- for (const key2 of [...keys].reverse()) {
4830
- await this.underlyingPage.keyboard.up(key2);
4699
+ for (const k of [...keys].reverse()) {
4700
+ await this.underlyingPage.keyboard.up(k.key);
4831
4701
  }
4832
4702
  },
4833
4703
  down: async (key) => {
@@ -4862,7 +4732,7 @@ var Page = class {
4862
4732
  await this.underlyingPage.keyboard.up("Control");
4863
4733
  }
4864
4734
  await (0, import_utils9.sleep)(100);
4865
- await this.keyboard.press("Backspace");
4735
+ await this.keyboard.press([{ key: "Backspace" }]);
4866
4736
  }
4867
4737
  async moveToPoint(point) {
4868
4738
  if (point) {
@@ -4923,8 +4793,186 @@ var WebPage = class extends Page {
4923
4793
  }
4924
4794
  };
4925
4795
 
4796
+ // src/playwright/ai-fixture.ts
4797
+ var import_node_crypto = require("crypto");
4798
+ var import_test = require("@playwright/test");
4799
+ var groupAndCaseForTest = (testInfo) => {
4800
+ let taskFile;
4801
+ let taskTitle;
4802
+ const titlePath = [...testInfo.titlePath];
4803
+ if (titlePath.length > 1) {
4804
+ taskTitle = titlePath.pop() || "unnamed";
4805
+ taskFile = `${titlePath.join(" > ")}`;
4806
+ } else if (titlePath.length === 1) {
4807
+ taskTitle = titlePath[0];
4808
+ taskFile = `${taskTitle}`;
4809
+ } else {
4810
+ taskTitle = "unnamed";
4811
+ taskFile = "unnamed";
4812
+ }
4813
+ return { taskFile, taskTitle };
4814
+ };
4815
+ var midsceneAgentKeyId = "_midsceneAgentId";
4816
+ var midsceneDumpAnnotationId = "MIDSCENE_DUMP_ANNOTATION";
4817
+ var PlaywrightAiFixture = (options) => {
4818
+ const { forceSameTabNavigation = true } = options != null ? options : {};
4819
+ const pageAgentMap = {};
4820
+ const agentForPage = (page, testInfo) => {
4821
+ let idForPage = page[midsceneAgentKeyId];
4822
+ if (!idForPage) {
4823
+ idForPage = (0, import_node_crypto.randomUUID)();
4824
+ page[midsceneAgentKeyId] = idForPage;
4825
+ const { testId } = testInfo;
4826
+ const { taskFile, taskTitle } = groupAndCaseForTest(testInfo);
4827
+ pageAgentMap[idForPage] = new PlaywrightAgent(page, {
4828
+ testId: `playwright-${testId}-${idForPage}`,
4829
+ forceSameTabNavigation,
4830
+ cacheId: `${taskFile}(${taskTitle})`,
4831
+ groupName: taskTitle,
4832
+ groupDescription: taskFile,
4833
+ generateReport: false
4834
+ // we will generate it in the reporter
4835
+ });
4836
+ }
4837
+ return pageAgentMap[idForPage];
4838
+ };
4839
+ const updateDumpAnnotation = (test2, dump2) => {
4840
+ const currentAnnotation = test2.annotations.find((item) => {
4841
+ return item.type === midsceneDumpAnnotationId;
4842
+ });
4843
+ if (currentAnnotation) {
4844
+ currentAnnotation.description = dump2;
4845
+ } else {
4846
+ test2.annotations.push({
4847
+ type: midsceneDumpAnnotationId,
4848
+ description: dump2
4849
+ });
4850
+ }
4851
+ };
4852
+ return {
4853
+ ai: async ({ page }, use, testInfo) => {
4854
+ const agent = agentForPage(page, testInfo);
4855
+ await use(
4856
+ async (taskPrompt, opts) => {
4857
+ return new Promise((resolve, reject) => {
4858
+ const { type: type2 = "action" } = opts || {};
4859
+ import_test.test.step(`ai - ${taskPrompt}`, async () => {
4860
+ await waitForNetworkIdle(page);
4861
+ try {
4862
+ const result = await agent.ai(taskPrompt, type2);
4863
+ resolve(result);
4864
+ } catch (error) {
4865
+ reject(error);
4866
+ }
4867
+ });
4868
+ });
4869
+ }
4870
+ );
4871
+ updateDumpAnnotation(testInfo, agent.dumpDataString());
4872
+ },
4873
+ aiAction: async ({ page }, use, testInfo) => {
4874
+ const agent = agentForPage(page, testInfo);
4875
+ await use(async (taskPrompt) => {
4876
+ return new Promise((resolve, reject) => {
4877
+ import_test.test.step(`aiAction - ${taskPrompt}`, async () => {
4878
+ await waitForNetworkIdle(page);
4879
+ try {
4880
+ const result = await agent.aiAction(taskPrompt);
4881
+ resolve(result);
4882
+ } catch (error) {
4883
+ reject(error);
4884
+ }
4885
+ });
4886
+ });
4887
+ });
4888
+ updateDumpAnnotation(testInfo, agent.dumpDataString());
4889
+ },
4890
+ aiQuery: async ({ page }, use, testInfo) => {
4891
+ const agent = agentForPage(page, testInfo);
4892
+ await use(async (demand) => {
4893
+ return new Promise((resolve, reject) => {
4894
+ import_test.test.step(`aiQuery - ${JSON.stringify(demand)}`, async () => {
4895
+ await waitForNetworkIdle(page);
4896
+ try {
4897
+ const result = await agent.aiQuery(demand);
4898
+ resolve(result);
4899
+ } catch (error) {
4900
+ reject(error);
4901
+ }
4902
+ });
4903
+ });
4904
+ });
4905
+ updateDumpAnnotation(testInfo, agent.dumpDataString());
4906
+ },
4907
+ aiAssert: async ({ page }, use, testInfo) => {
4908
+ const agent = agentForPage(page, testInfo);
4909
+ await use(async (assertion, errorMsg) => {
4910
+ return new Promise((resolve, reject) => {
4911
+ import_test.test.step(`aiAssert - ${assertion}`, async () => {
4912
+ await waitForNetworkIdle(page);
4913
+ try {
4914
+ await agent.aiAssert(assertion, errorMsg);
4915
+ resolve(null);
4916
+ } catch (error) {
4917
+ reject(error);
4918
+ }
4919
+ });
4920
+ });
4921
+ });
4922
+ updateDumpAnnotation(testInfo, agent.dumpDataString());
4923
+ },
4924
+ aiWaitFor: async ({ page }, use, testInfo) => {
4925
+ const agent = agentForPage(page, testInfo);
4926
+ await use(async (assertion, opt) => {
4927
+ return new Promise((resolve, reject) => {
4928
+ import_test.test.step(`aiWaitFor - ${assertion}`, async () => {
4929
+ await waitForNetworkIdle(page);
4930
+ try {
4931
+ await agent.aiWaitFor(assertion, opt);
4932
+ resolve(null);
4933
+ } catch (error) {
4934
+ reject(error);
4935
+ }
4936
+ });
4937
+ });
4938
+ });
4939
+ updateDumpAnnotation(testInfo, agent.dumpDataString());
4940
+ }
4941
+ };
4942
+ };
4943
+ async function waitForNetworkIdle(page, timeout = 2e4) {
4944
+ try {
4945
+ await page.waitForLoadState("networkidle", { timeout });
4946
+ } catch (error) {
4947
+ console.warn(
4948
+ `Network idle timeout exceeded: ${error instanceof Error ? error.message : String(error)}`
4949
+ );
4950
+ }
4951
+ }
4952
+
4926
4953
  // src/playwright/index.ts
4927
4954
  var import_env4 = require("@midscene/core/env");
4955
+ var PlaywrightAgent = class extends PageAgent {
4956
+ constructor(page, opts) {
4957
+ const webPage = new WebPage(page);
4958
+ super(webPage, opts);
4959
+ const { forceSameTabNavigation = true } = opts != null ? opts : {};
4960
+ if (forceSameTabNavigation) {
4961
+ page.on("popup", async (popup) => {
4962
+ if (!popup) {
4963
+ console.warn(
4964
+ "got a popup event, but the popup is not ready yet, skip"
4965
+ );
4966
+ return;
4967
+ }
4968
+ const url = await popup.url();
4969
+ console.log(`Popup opened: ${url}`);
4970
+ await popup.close();
4971
+ await page.goto(url);
4972
+ });
4973
+ }
4974
+ }
4975
+ };
4928
4976
  // Annotate the CommonJS export names for ESM import in node:
4929
4977
  0 && (module.exports = {
4930
4978
  PlaywrightAgent,