@midscene/shared 0.18.1-beta-20250611082446.0 → 0.18.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.
@@ -1,3 +1,6 @@
1
+ declare const PLAYWRIGHT_EXAMPLE_CODE = "\n// Reference the following code to generate Midscene test cases\n// The following is test code for Midscene AI, for reference\n// The following is Playwright syntax, you can use Playwright to assist in test generation\nIMPORTANT: Follow these exact type signatures for AI functions:\n\n// Type signatures for AI functions:\naiInput(value: string, locator: string): Promise<void>\naiTap(locator: string): Promise<void> \naiAssert(assertion: string): Promise<void>\naiQuery<T>(queryObject: Record<string, string>): Promise<T> // Extracts data from page based on descriptions\n\n// examples:\n// Reference the following code to generate Midscene test cases\n// The following is test code for Midscene AI, for reference\n// The following is Playwright syntax, you can use Playwright to assist in test generation\nimport { test as base } from '@playwright/test';\nimport type { PlayWrightAiFixtureType } from '@midscene/web/playwright';\nimport { PlaywrightAiFixture } from '@midscene/web/playwright';\n\nexport const test = base.extend<PlayWrightAiFixtureType>(PlaywrightAiFixture({\n waitForNetworkIdleTimeout: 2000, // optional, the timeout for waiting for network idle between each action, default is 2000ms\n }));\n\n\ntest.beforeEach(async ({ page }) => {\n await page.goto('https://www.xxx.com/');\n await page.setViewportSize({ width: 1920, height: 1080 });\n});\n\ntest('ai shop', async ({\n aiInput,\n aiAssert,\n aiQuery,\n aiKeyboardPress,\n aiHover,\n aiTap,\n agentForPage,\n page,\n}) => {\n // login\n await aiAssert('The page shows the login interface');\n await aiInput('user_name', 'in user name input');\n await aiInput('password', 'in password input');\n await aiKeyboardPress('Enter', 'Login Button');\n\n // check the login success\n await aiWaitFor('The page shows that the loading is complete');\n await aiAssert('The current page shows the product detail page');\n\n // check the product info\n const dataA = await aiQuery({\n userInfo: 'User information in the format {name: string}',\n theFirstProductInfo: 'The first product info in the format {name: string, price: number}',\n });\n expect(dataA.theFirstProductInfo.name).toBe('xxx');\n expect(dataA.theFirstProductInfo.price).toBe(100);\n\n\n // add to cart\n await aiTap('click add to cart button');\n \n await aiTap('click right top cart icon');\n await aiAssert('The cart icon shows the number 1');\n});\n";
2
+ declare const YAML_EXAMPLE_CODE = "\n1. Format:\n\ntarget:\n url: \"starting_url\"\n viewportWidth: 1280\n viewportHeight: 960\n\ntasks:\n - name: \"descriptive task name\"\n flow:\n - aiTap: \"element description\"\n - aiInput: 'text value'\n locate: 'input field description'\n - aiScroll:\n direction: down/up\n scrollType: untilBottom/untilTop/page\n - aiAssert: \"expected state\"\n - sleep: milliseconds\n\n2. Action Types:\n- aiTap: for clicks (natural language targeting)\n- aiInput: for text input with 'locate' field\n- aiScroll: with direction and scrollType\n- aiAssert: for validations\n- sleep: for delays (milliseconds)\n\n3. Best Practices:\n- Group related actions into logical tasks\n- Use natural language descriptions\n- Add deepThink: true for complex interactions\n- Keep task names concise but descriptive\n";
3
+
1
4
  declare const TEXT_SIZE_THRESHOLD = 9;
2
5
  declare const TEXT_MAX_SIZE = 40;
3
6
  declare const CONTAINER_MINI_HEIGHT = 3;
@@ -18,4 +21,4 @@ declare const DEFAULT_WAIT_FOR_NETWORK_IDLE_TIMEOUT = 2000;
18
21
  declare const DEFAULT_WAIT_FOR_NETWORK_IDLE_TIME = 300;
19
22
  declare const DEFAULT_WAIT_FOR_NETWORK_IDLE_CONCURRENCY = 2;
20
23
 
21
- export { CONTAINER_MINI_HEIGHT, CONTAINER_MINI_WIDTH, DEFAULT_WAIT_FOR_NAVIGATION_TIMEOUT, DEFAULT_WAIT_FOR_NETWORK_IDLE_CONCURRENCY, DEFAULT_WAIT_FOR_NETWORK_IDLE_TIME, DEFAULT_WAIT_FOR_NETWORK_IDLE_TIMEOUT, NodeType, PLAYGROUND_SERVER_PORT, SCRCPY_SERVER_PORT, TEXT_MAX_SIZE, TEXT_SIZE_THRESHOLD };
24
+ export { CONTAINER_MINI_HEIGHT, CONTAINER_MINI_WIDTH, DEFAULT_WAIT_FOR_NAVIGATION_TIMEOUT, DEFAULT_WAIT_FOR_NETWORK_IDLE_CONCURRENCY, DEFAULT_WAIT_FOR_NETWORK_IDLE_TIME, DEFAULT_WAIT_FOR_NETWORK_IDLE_TIMEOUT, NodeType, PLAYGROUND_SERVER_PORT, PLAYWRIGHT_EXAMPLE_CODE, SCRCPY_SERVER_PORT, TEXT_MAX_SIZE, TEXT_SIZE_THRESHOLD, YAML_EXAMPLE_CODE };
@@ -1,3 +1,104 @@
1
+ // src/constants/example-code.ts
2
+ var PLAYWRIGHT_EXAMPLE_CODE = `
3
+ // Reference the following code to generate Midscene test cases
4
+ // The following is test code for Midscene AI, for reference
5
+ // The following is Playwright syntax, you can use Playwright to assist in test generation
6
+ IMPORTANT: Follow these exact type signatures for AI functions:
7
+
8
+ // Type signatures for AI functions:
9
+ aiInput(value: string, locator: string): Promise<void>
10
+ aiTap(locator: string): Promise<void>
11
+ aiAssert(assertion: string): Promise<void>
12
+ aiQuery<T>(queryObject: Record<string, string>): Promise<T> // Extracts data from page based on descriptions
13
+
14
+ // examples:
15
+ // Reference the following code to generate Midscene test cases
16
+ // The following is test code for Midscene AI, for reference
17
+ // The following is Playwright syntax, you can use Playwright to assist in test generation
18
+ import { test as base } from '@playwright/test';
19
+ import type { PlayWrightAiFixtureType } from '@midscene/web/playwright';
20
+ import { PlaywrightAiFixture } from '@midscene/web/playwright';
21
+
22
+ export const test = base.extend<PlayWrightAiFixtureType>(PlaywrightAiFixture({
23
+ waitForNetworkIdleTimeout: 2000, // optional, the timeout for waiting for network idle between each action, default is 2000ms
24
+ }));
25
+
26
+
27
+ test.beforeEach(async ({ page }) => {
28
+ await page.goto('https://www.xxx.com/');
29
+ await page.setViewportSize({ width: 1920, height: 1080 });
30
+ });
31
+
32
+ test('ai shop', async ({
33
+ aiInput,
34
+ aiAssert,
35
+ aiQuery,
36
+ aiKeyboardPress,
37
+ aiHover,
38
+ aiTap,
39
+ agentForPage,
40
+ page,
41
+ }) => {
42
+ // login
43
+ await aiAssert('The page shows the login interface');
44
+ await aiInput('user_name', 'in user name input');
45
+ await aiInput('password', 'in password input');
46
+ await aiKeyboardPress('Enter', 'Login Button');
47
+
48
+ // check the login success
49
+ await aiWaitFor('The page shows that the loading is complete');
50
+ await aiAssert('The current page shows the product detail page');
51
+
52
+ // check the product info
53
+ const dataA = await aiQuery({
54
+ userInfo: 'User information in the format {name: string}',
55
+ theFirstProductInfo: 'The first product info in the format {name: string, price: number}',
56
+ });
57
+ expect(dataA.theFirstProductInfo.name).toBe('xxx');
58
+ expect(dataA.theFirstProductInfo.price).toBe(100);
59
+
60
+
61
+ // add to cart
62
+ await aiTap('click add to cart button');
63
+
64
+ await aiTap('click right top cart icon');
65
+ await aiAssert('The cart icon shows the number 1');
66
+ });
67
+ `;
68
+ var YAML_EXAMPLE_CODE = `
69
+ 1. Format:
70
+
71
+ target:
72
+ url: "starting_url"
73
+ viewportWidth: 1280
74
+ viewportHeight: 960
75
+
76
+ tasks:
77
+ - name: "descriptive task name"
78
+ flow:
79
+ - aiTap: "element description"
80
+ - aiInput: 'text value'
81
+ locate: 'input field description'
82
+ - aiScroll:
83
+ direction: down/up
84
+ scrollType: untilBottom/untilTop/page
85
+ - aiAssert: "expected state"
86
+ - sleep: milliseconds
87
+
88
+ 2. Action Types:
89
+ - aiTap: for clicks (natural language targeting)
90
+ - aiInput: for text input with 'locate' field
91
+ - aiScroll: with direction and scrollType
92
+ - aiAssert: for validations
93
+ - sleep: for delays (milliseconds)
94
+
95
+ 3. Best Practices:
96
+ - Group related actions into logical tasks
97
+ - Use natural language descriptions
98
+ - Add deepThink: true for complex interactions
99
+ - Keep task names concise but descriptive
100
+ `;
101
+
1
102
  // src/constants/index.ts
2
103
  var TEXT_SIZE_THRESHOLD = 9;
3
104
  var TEXT_MAX_SIZE = 40;
@@ -28,7 +129,9 @@ export {
28
129
  DEFAULT_WAIT_FOR_NETWORK_IDLE_TIMEOUT,
29
130
  NodeType,
30
131
  PLAYGROUND_SERVER_PORT,
132
+ PLAYWRIGHT_EXAMPLE_CODE,
31
133
  SCRCPY_SERVER_PORT,
32
134
  TEXT_MAX_SIZE,
33
- TEXT_SIZE_THRESHOLD
135
+ TEXT_SIZE_THRESHOLD,
136
+ YAML_EXAMPLE_CODE
34
137
  };
@@ -110,40 +110,12 @@ var debugMode = false;
110
110
  function setDebugMode(mode) {
111
111
  debugMode = mode;
112
112
  }
113
- function getDebugMode() {
114
- return debugMode;
115
- }
116
113
  function logger(..._msg) {
117
114
  if (!debugMode) {
118
115
  return;
119
116
  }
120
117
  console.log(..._msg);
121
118
  }
122
- var taskIdKey = "_midscene_retrieve_task_id";
123
- function selectorForValue(val) {
124
- return `[${taskIdKey}='${val}']`;
125
- }
126
- function setDataForNode(node, nodeHash, setToParentNode, currentWindow) {
127
- const taskId = taskIdKey;
128
- if (!(node instanceof currentWindow.HTMLElement)) {
129
- return "";
130
- }
131
- if (!taskId) {
132
- console.error("No task id found");
133
- return "";
134
- }
135
- const selector = selectorForValue(nodeHash);
136
- if (getDebugMode()) {
137
- if (setToParentNode) {
138
- if (node.parentNode instanceof currentWindow.HTMLElement) {
139
- node.parentNode.setAttribute(taskIdKey, nodeHash.toString());
140
- }
141
- } else {
142
- node.setAttribute(taskIdKey, nodeHash.toString());
143
- }
144
- }
145
- return selector;
146
- }
147
119
  function isElementPartiallyInViewport(rect, currentWindow, currentDocument, visibleAreaRatio = 2 / 3) {
148
120
  const elementHeight = rect.height;
149
121
  const elementWidth = rect.width;
@@ -430,7 +402,6 @@ function collectElementInfo(node, currentWindow, currentDocument, baseZoom = 1,
430
402
  const attributes = getNodeAttributes(node, currentWindow);
431
403
  let valueContent = attributes.value || attributes.placeholder || node.textContent || "";
432
404
  const nodeHashId = midsceneGenerateHash(node, valueContent, rect);
433
- const selector = setDataForNode(node, nodeHashId, false, currentWindow);
434
405
  const tagName = node.tagName.toLowerCase();
435
406
  if (node.tagName.toLowerCase() === "select") {
436
407
  const selectedOption = node.options[node.selectedIndex];
@@ -442,7 +413,6 @@ function collectElementInfo(node, currentWindow, currentDocument, baseZoom = 1,
442
413
  const elementInfo = {
443
414
  id: nodeHashId,
444
415
  nodeHashId,
445
- locator: selector,
446
416
  nodeType: "FORM_ITEM Node" /* FORM_ITEM */,
447
417
  indexId: indexId++,
448
418
  attributes: {
@@ -475,13 +445,11 @@ function collectElementInfo(node, currentWindow, currentDocument, baseZoom = 1,
475
445
  const pseudo = getPseudoElementContent(node, currentWindow);
476
446
  const content = node.innerText || pseudo.before || pseudo.after || "";
477
447
  const nodeHashId = midsceneGenerateHash(node, content, rect2);
478
- const selector = setDataForNode(node, nodeHashId, false, currentWindow);
479
448
  const elementInfo = {
480
449
  id: nodeHashId,
481
450
  indexId: indexId++,
482
451
  nodeHashId,
483
452
  nodeType: "BUTTON Node" /* BUTTON */,
484
- locator: selector,
485
453
  attributes: {
486
454
  ...attributes,
487
455
  htmlTagName: tagNameOfNode(node),
@@ -501,12 +469,10 @@ function collectElementInfo(node, currentWindow, currentDocument, baseZoom = 1,
501
469
  if (isImgElement(node)) {
502
470
  const attributes = getNodeAttributes(node, currentWindow);
503
471
  const nodeHashId = midsceneGenerateHash(node, "", rect);
504
- const selector = setDataForNode(node, nodeHashId, false, currentWindow);
505
472
  const elementInfo = {
506
473
  id: nodeHashId,
507
474
  indexId: indexId++,
508
475
  nodeHashId,
509
- locator: selector,
510
476
  attributes: {
511
477
  ...attributes,
512
478
  ...node.nodeName.toLowerCase() === "svg" ? {
@@ -538,13 +504,11 @@ function collectElementInfo(node, currentWindow, currentDocument, baseZoom = 1,
538
504
  return null;
539
505
  }
540
506
  const nodeHashId = midsceneGenerateHash(node, text, rect);
541
- const selector = setDataForNode(node, nodeHashId, true, currentWindow);
542
507
  const elementInfo = {
543
508
  id: nodeHashId,
544
509
  indexId: indexId++,
545
510
  nodeHashId,
546
511
  nodeType: "TEXT Node" /* TEXT */,
547
- locator: selector,
548
512
  attributes: {
549
513
  ...attributes,
550
514
  nodeType: "TEXT Node" /* TEXT */,
@@ -566,13 +530,11 @@ function collectElementInfo(node, currentWindow, currentDocument, baseZoom = 1,
566
530
  const pseudo = getPseudoElementContent(node, currentWindow);
567
531
  const content = node.innerText || pseudo.before || pseudo.after || "";
568
532
  const nodeHashId = midsceneGenerateHash(node, content, rect);
569
- const selector = setDataForNode(node, nodeHashId, false, currentWindow);
570
533
  const elementInfo = {
571
534
  id: nodeHashId,
572
535
  indexId: indexId++,
573
536
  nodeHashId,
574
537
  nodeType: "Anchor Node" /* A */,
575
- locator: selector,
576
538
  attributes: {
577
539
  ...attributes,
578
540
  htmlTagName: tagNameOfNode(node),
@@ -592,13 +554,11 @@ function collectElementInfo(node, currentWindow, currentDocument, baseZoom = 1,
592
554
  if (isContainerElement(node)) {
593
555
  const attributes = getNodeAttributes(node, currentWindow);
594
556
  const nodeHashId = midsceneGenerateHash(node, "", rect);
595
- const selector = setDataForNode(node, nodeHashId, false, currentWindow);
596
557
  const elementInfo = {
597
558
  id: nodeHashId,
598
559
  nodeHashId,
599
560
  indexId: indexId++,
600
561
  nodeType: "CONTAINER Node" /* CONTAINER */,
601
- locator: selector,
602
562
  attributes: {
603
563
  ...attributes,
604
564
  nodeType: "CONTAINER Node" /* CONTAINER */,
@@ -1,2 +1,2 @@
1
1
  import './constants.js';
2
- export { E as ElementInfo, a as ElementNode, d as descriptionOfTree, m as generateElementByPosition, l as getElementInfoByXpath, i as getNodeFromCacheList, k as getNodeInfoByXpath, j as getXpathsById, s as setNodeHashCacheListOnWindow, t as traverseTree, b as treeToList, e as trimAttributes, c as truncateText, g as webExtractNodeTree, h as webExtractNodeTreeAsString, f as webExtractTextWithPosition } from './index-a171e36c.js';
2
+ export { E as ElementInfo, a as ElementNode, d as descriptionOfTree, m as generateElementByPosition, l as getElementInfoByXpath, i as getNodeFromCacheList, k as getNodeInfoByXpath, j as getXpathsById, s as setNodeHashCacheListOnWindow, t as traverseTree, b as treeToList, e as trimAttributes, c as truncateText, g as webExtractNodeTree, h as webExtractNodeTreeAsString, f as webExtractTextWithPosition } from './index-59587d83.js';
@@ -252,40 +252,12 @@ var debugMode = false;
252
252
  function setDebugMode(mode) {
253
253
  debugMode = mode;
254
254
  }
255
- function getDebugMode() {
256
- return debugMode;
257
- }
258
255
  function logger(..._msg) {
259
256
  if (!debugMode) {
260
257
  return;
261
258
  }
262
259
  console.log(..._msg);
263
260
  }
264
- var taskIdKey = "_midscene_retrieve_task_id";
265
- function selectorForValue(val) {
266
- return `[${taskIdKey}='${val}']`;
267
- }
268
- function setDataForNode(node, nodeHash, setToParentNode, currentWindow) {
269
- const taskId = taskIdKey;
270
- if (!(node instanceof currentWindow.HTMLElement)) {
271
- return "";
272
- }
273
- if (!taskId) {
274
- console.error("No task id found");
275
- return "";
276
- }
277
- const selector = selectorForValue(nodeHash);
278
- if (getDebugMode()) {
279
- if (setToParentNode) {
280
- if (node.parentNode instanceof currentWindow.HTMLElement) {
281
- node.parentNode.setAttribute(taskIdKey, nodeHash.toString());
282
- }
283
- } else {
284
- node.setAttribute(taskIdKey, nodeHash.toString());
285
- }
286
- }
287
- return selector;
288
- }
289
261
  function isElementPartiallyInViewport(rect, currentWindow, currentDocument, visibleAreaRatio = 2 / 3) {
290
262
  const elementHeight = rect.height;
291
263
  const elementWidth = rect.width;
@@ -562,7 +534,6 @@ function collectElementInfo(node, currentWindow, currentDocument, baseZoom = 1,
562
534
  const attributes = getNodeAttributes(node, currentWindow);
563
535
  let valueContent = attributes.value || attributes.placeholder || node.textContent || "";
564
536
  const nodeHashId = midsceneGenerateHash(node, valueContent, rect);
565
- const selector = setDataForNode(node, nodeHashId, false, currentWindow);
566
537
  const tagName = node.tagName.toLowerCase();
567
538
  if (node.tagName.toLowerCase() === "select") {
568
539
  const selectedOption = node.options[node.selectedIndex];
@@ -574,7 +545,6 @@ function collectElementInfo(node, currentWindow, currentDocument, baseZoom = 1,
574
545
  const elementInfo = {
575
546
  id: nodeHashId,
576
547
  nodeHashId,
577
- locator: selector,
578
548
  nodeType: "FORM_ITEM Node" /* FORM_ITEM */,
579
549
  indexId: indexId++,
580
550
  attributes: {
@@ -607,13 +577,11 @@ function collectElementInfo(node, currentWindow, currentDocument, baseZoom = 1,
607
577
  const pseudo = getPseudoElementContent(node, currentWindow);
608
578
  const content = node.innerText || pseudo.before || pseudo.after || "";
609
579
  const nodeHashId = midsceneGenerateHash(node, content, rect2);
610
- const selector = setDataForNode(node, nodeHashId, false, currentWindow);
611
580
  const elementInfo = {
612
581
  id: nodeHashId,
613
582
  indexId: indexId++,
614
583
  nodeHashId,
615
584
  nodeType: "BUTTON Node" /* BUTTON */,
616
- locator: selector,
617
585
  attributes: {
618
586
  ...attributes,
619
587
  htmlTagName: tagNameOfNode(node),
@@ -633,12 +601,10 @@ function collectElementInfo(node, currentWindow, currentDocument, baseZoom = 1,
633
601
  if (isImgElement(node)) {
634
602
  const attributes = getNodeAttributes(node, currentWindow);
635
603
  const nodeHashId = midsceneGenerateHash(node, "", rect);
636
- const selector = setDataForNode(node, nodeHashId, false, currentWindow);
637
604
  const elementInfo = {
638
605
  id: nodeHashId,
639
606
  indexId: indexId++,
640
607
  nodeHashId,
641
- locator: selector,
642
608
  attributes: {
643
609
  ...attributes,
644
610
  ...node.nodeName.toLowerCase() === "svg" ? {
@@ -670,13 +636,11 @@ function collectElementInfo(node, currentWindow, currentDocument, baseZoom = 1,
670
636
  return null;
671
637
  }
672
638
  const nodeHashId = midsceneGenerateHash(node, text, rect);
673
- const selector = setDataForNode(node, nodeHashId, true, currentWindow);
674
639
  const elementInfo = {
675
640
  id: nodeHashId,
676
641
  indexId: indexId++,
677
642
  nodeHashId,
678
643
  nodeType: "TEXT Node" /* TEXT */,
679
- locator: selector,
680
644
  attributes: {
681
645
  ...attributes,
682
646
  nodeType: "TEXT Node" /* TEXT */,
@@ -698,13 +662,11 @@ function collectElementInfo(node, currentWindow, currentDocument, baseZoom = 1,
698
662
  const pseudo = getPseudoElementContent(node, currentWindow);
699
663
  const content = node.innerText || pseudo.before || pseudo.after || "";
700
664
  const nodeHashId = midsceneGenerateHash(node, content, rect);
701
- const selector = setDataForNode(node, nodeHashId, false, currentWindow);
702
665
  const elementInfo = {
703
666
  id: nodeHashId,
704
667
  indexId: indexId++,
705
668
  nodeHashId,
706
669
  nodeType: "Anchor Node" /* A */,
707
- locator: selector,
708
670
  attributes: {
709
671
  ...attributes,
710
672
  htmlTagName: tagNameOfNode(node),
@@ -724,13 +686,11 @@ function collectElementInfo(node, currentWindow, currentDocument, baseZoom = 1,
724
686
  if (isContainerElement(node)) {
725
687
  const attributes = getNodeAttributes(node, currentWindow);
726
688
  const nodeHashId = midsceneGenerateHash(node, "", rect);
727
- const selector = setDataForNode(node, nodeHashId, false, currentWindow);
728
689
  const elementInfo = {
729
690
  id: nodeHashId,
730
691
  nodeHashId,
731
692
  indexId: indexId++,
732
693
  nodeType: "CONTAINER Node" /* CONTAINER */,
733
- locator: selector,
734
694
  attributes: {
735
695
  ...attributes,
736
696
  nodeType: "CONTAINER Node" /* CONTAINER */,
package/dist/es/img.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Buffer } from 'node:buffer';
2
2
  import Jimp from 'jimp';
3
- import { R as Rect, B as BaseElement } from './index-a171e36c.js';
3
+ import { R as Rect, B as BaseElement } from './index-59587d83.js';
4
4
  import './constants.js';
5
5
 
6
6
  interface Size {
@@ -46,7 +46,6 @@ interface ElementInfo {
46
46
  id: string;
47
47
  indexId: number;
48
48
  nodeHashId: string;
49
- locator: string;
50
49
  xpaths?: string[];
51
50
  attributes: {
52
51
  nodeType: NodeType;
@@ -90,7 +89,6 @@ declare abstract class BaseElement {
90
89
  abstract content: string;
91
90
  abstract rect: Rect;
92
91
  abstract center: [number, number];
93
- abstract locator?: string;
94
92
  abstract xpaths?: string[];
95
93
  abstract isVisible: boolean;
96
94
  }
@@ -1,2 +1,2 @@
1
1
  import './constants.js';
2
- export { B as BaseElement, n as ElementTreeNode, P as Point, R as Rect, S as Size, W as WebElementInfo } from './index-a171e36c.js';
2
+ export { B as BaseElement, n as ElementTreeNode, P as Point, R as Rect, S as Size, W as WebElementInfo } from './index-59587d83.js';
@@ -1,3 +1,6 @@
1
+ declare const PLAYWRIGHT_EXAMPLE_CODE = "\n// Reference the following code to generate Midscene test cases\n// The following is test code for Midscene AI, for reference\n// The following is Playwright syntax, you can use Playwright to assist in test generation\nIMPORTANT: Follow these exact type signatures for AI functions:\n\n// Type signatures for AI functions:\naiInput(value: string, locator: string): Promise<void>\naiTap(locator: string): Promise<void> \naiAssert(assertion: string): Promise<void>\naiQuery<T>(queryObject: Record<string, string>): Promise<T> // Extracts data from page based on descriptions\n\n// examples:\n// Reference the following code to generate Midscene test cases\n// The following is test code for Midscene AI, for reference\n// The following is Playwright syntax, you can use Playwright to assist in test generation\nimport { test as base } from '@playwright/test';\nimport type { PlayWrightAiFixtureType } from '@midscene/web/playwright';\nimport { PlaywrightAiFixture } from '@midscene/web/playwright';\n\nexport const test = base.extend<PlayWrightAiFixtureType>(PlaywrightAiFixture({\n waitForNetworkIdleTimeout: 2000, // optional, the timeout for waiting for network idle between each action, default is 2000ms\n }));\n\n\ntest.beforeEach(async ({ page }) => {\n await page.goto('https://www.xxx.com/');\n await page.setViewportSize({ width: 1920, height: 1080 });\n});\n\ntest('ai shop', async ({\n aiInput,\n aiAssert,\n aiQuery,\n aiKeyboardPress,\n aiHover,\n aiTap,\n agentForPage,\n page,\n}) => {\n // login\n await aiAssert('The page shows the login interface');\n await aiInput('user_name', 'in user name input');\n await aiInput('password', 'in password input');\n await aiKeyboardPress('Enter', 'Login Button');\n\n // check the login success\n await aiWaitFor('The page shows that the loading is complete');\n await aiAssert('The current page shows the product detail page');\n\n // check the product info\n const dataA = await aiQuery({\n userInfo: 'User information in the format {name: string}',\n theFirstProductInfo: 'The first product info in the format {name: string, price: number}',\n });\n expect(dataA.theFirstProductInfo.name).toBe('xxx');\n expect(dataA.theFirstProductInfo.price).toBe(100);\n\n\n // add to cart\n await aiTap('click add to cart button');\n \n await aiTap('click right top cart icon');\n await aiAssert('The cart icon shows the number 1');\n});\n";
2
+ declare const YAML_EXAMPLE_CODE = "\n1. Format:\n\ntarget:\n url: \"starting_url\"\n viewportWidth: 1280\n viewportHeight: 960\n\ntasks:\n - name: \"descriptive task name\"\n flow:\n - aiTap: \"element description\"\n - aiInput: 'text value'\n locate: 'input field description'\n - aiScroll:\n direction: down/up\n scrollType: untilBottom/untilTop/page\n - aiAssert: \"expected state\"\n - sleep: milliseconds\n\n2. Action Types:\n- aiTap: for clicks (natural language targeting)\n- aiInput: for text input with 'locate' field\n- aiScroll: with direction and scrollType\n- aiAssert: for validations\n- sleep: for delays (milliseconds)\n\n3. Best Practices:\n- Group related actions into logical tasks\n- Use natural language descriptions\n- Add deepThink: true for complex interactions\n- Keep task names concise but descriptive\n";
3
+
1
4
  declare const TEXT_SIZE_THRESHOLD = 9;
2
5
  declare const TEXT_MAX_SIZE = 40;
3
6
  declare const CONTAINER_MINI_HEIGHT = 3;
@@ -18,4 +21,4 @@ declare const DEFAULT_WAIT_FOR_NETWORK_IDLE_TIMEOUT = 2000;
18
21
  declare const DEFAULT_WAIT_FOR_NETWORK_IDLE_TIME = 300;
19
22
  declare const DEFAULT_WAIT_FOR_NETWORK_IDLE_CONCURRENCY = 2;
20
23
 
21
- export { CONTAINER_MINI_HEIGHT, CONTAINER_MINI_WIDTH, DEFAULT_WAIT_FOR_NAVIGATION_TIMEOUT, DEFAULT_WAIT_FOR_NETWORK_IDLE_CONCURRENCY, DEFAULT_WAIT_FOR_NETWORK_IDLE_TIME, DEFAULT_WAIT_FOR_NETWORK_IDLE_TIMEOUT, NodeType, PLAYGROUND_SERVER_PORT, SCRCPY_SERVER_PORT, TEXT_MAX_SIZE, TEXT_SIZE_THRESHOLD };
24
+ export { CONTAINER_MINI_HEIGHT, CONTAINER_MINI_WIDTH, DEFAULT_WAIT_FOR_NAVIGATION_TIMEOUT, DEFAULT_WAIT_FOR_NETWORK_IDLE_CONCURRENCY, DEFAULT_WAIT_FOR_NETWORK_IDLE_TIME, DEFAULT_WAIT_FOR_NETWORK_IDLE_TIMEOUT, NodeType, PLAYGROUND_SERVER_PORT, PLAYWRIGHT_EXAMPLE_CODE, SCRCPY_SERVER_PORT, TEXT_MAX_SIZE, TEXT_SIZE_THRESHOLD, YAML_EXAMPLE_CODE };
@@ -28,11 +28,116 @@ __export(constants_exports, {
28
28
  DEFAULT_WAIT_FOR_NETWORK_IDLE_TIMEOUT: () => DEFAULT_WAIT_FOR_NETWORK_IDLE_TIMEOUT,
29
29
  NodeType: () => NodeType,
30
30
  PLAYGROUND_SERVER_PORT: () => PLAYGROUND_SERVER_PORT,
31
+ PLAYWRIGHT_EXAMPLE_CODE: () => PLAYWRIGHT_EXAMPLE_CODE,
31
32
  SCRCPY_SERVER_PORT: () => SCRCPY_SERVER_PORT,
32
33
  TEXT_MAX_SIZE: () => TEXT_MAX_SIZE,
33
- TEXT_SIZE_THRESHOLD: () => TEXT_SIZE_THRESHOLD
34
+ TEXT_SIZE_THRESHOLD: () => TEXT_SIZE_THRESHOLD,
35
+ YAML_EXAMPLE_CODE: () => YAML_EXAMPLE_CODE
34
36
  });
35
37
  module.exports = __toCommonJS(constants_exports);
38
+
39
+ // src/constants/example-code.ts
40
+ var PLAYWRIGHT_EXAMPLE_CODE = `
41
+ // Reference the following code to generate Midscene test cases
42
+ // The following is test code for Midscene AI, for reference
43
+ // The following is Playwright syntax, you can use Playwright to assist in test generation
44
+ IMPORTANT: Follow these exact type signatures for AI functions:
45
+
46
+ // Type signatures for AI functions:
47
+ aiInput(value: string, locator: string): Promise<void>
48
+ aiTap(locator: string): Promise<void>
49
+ aiAssert(assertion: string): Promise<void>
50
+ aiQuery<T>(queryObject: Record<string, string>): Promise<T> // Extracts data from page based on descriptions
51
+
52
+ // examples:
53
+ // Reference the following code to generate Midscene test cases
54
+ // The following is test code for Midscene AI, for reference
55
+ // The following is Playwright syntax, you can use Playwright to assist in test generation
56
+ import { test as base } from '@playwright/test';
57
+ import type { PlayWrightAiFixtureType } from '@midscene/web/playwright';
58
+ import { PlaywrightAiFixture } from '@midscene/web/playwright';
59
+
60
+ export const test = base.extend<PlayWrightAiFixtureType>(PlaywrightAiFixture({
61
+ waitForNetworkIdleTimeout: 2000, // optional, the timeout for waiting for network idle between each action, default is 2000ms
62
+ }));
63
+
64
+
65
+ test.beforeEach(async ({ page }) => {
66
+ await page.goto('https://www.xxx.com/');
67
+ await page.setViewportSize({ width: 1920, height: 1080 });
68
+ });
69
+
70
+ test('ai shop', async ({
71
+ aiInput,
72
+ aiAssert,
73
+ aiQuery,
74
+ aiKeyboardPress,
75
+ aiHover,
76
+ aiTap,
77
+ agentForPage,
78
+ page,
79
+ }) => {
80
+ // login
81
+ await aiAssert('The page shows the login interface');
82
+ await aiInput('user_name', 'in user name input');
83
+ await aiInput('password', 'in password input');
84
+ await aiKeyboardPress('Enter', 'Login Button');
85
+
86
+ // check the login success
87
+ await aiWaitFor('The page shows that the loading is complete');
88
+ await aiAssert('The current page shows the product detail page');
89
+
90
+ // check the product info
91
+ const dataA = await aiQuery({
92
+ userInfo: 'User information in the format {name: string}',
93
+ theFirstProductInfo: 'The first product info in the format {name: string, price: number}',
94
+ });
95
+ expect(dataA.theFirstProductInfo.name).toBe('xxx');
96
+ expect(dataA.theFirstProductInfo.price).toBe(100);
97
+
98
+
99
+ // add to cart
100
+ await aiTap('click add to cart button');
101
+
102
+ await aiTap('click right top cart icon');
103
+ await aiAssert('The cart icon shows the number 1');
104
+ });
105
+ `;
106
+ var YAML_EXAMPLE_CODE = `
107
+ 1. Format:
108
+
109
+ target:
110
+ url: "starting_url"
111
+ viewportWidth: 1280
112
+ viewportHeight: 960
113
+
114
+ tasks:
115
+ - name: "descriptive task name"
116
+ flow:
117
+ - aiTap: "element description"
118
+ - aiInput: 'text value'
119
+ locate: 'input field description'
120
+ - aiScroll:
121
+ direction: down/up
122
+ scrollType: untilBottom/untilTop/page
123
+ - aiAssert: "expected state"
124
+ - sleep: milliseconds
125
+
126
+ 2. Action Types:
127
+ - aiTap: for clicks (natural language targeting)
128
+ - aiInput: for text input with 'locate' field
129
+ - aiScroll: with direction and scrollType
130
+ - aiAssert: for validations
131
+ - sleep: for delays (milliseconds)
132
+
133
+ 3. Best Practices:
134
+ - Group related actions into logical tasks
135
+ - Use natural language descriptions
136
+ - Add deepThink: true for complex interactions
137
+ - Keep task names concise but descriptive
138
+ `;
139
+
140
+ // src/constants/index.ts
36
141
  var TEXT_SIZE_THRESHOLD = 9;
37
142
  var TEXT_MAX_SIZE = 40;
38
143
  var CONTAINER_MINI_HEIGHT = 3;
@@ -63,7 +168,9 @@ var DEFAULT_WAIT_FOR_NETWORK_IDLE_CONCURRENCY = 2;
63
168
  DEFAULT_WAIT_FOR_NETWORK_IDLE_TIMEOUT,
64
169
  NodeType,
65
170
  PLAYGROUND_SERVER_PORT,
171
+ PLAYWRIGHT_EXAMPLE_CODE,
66
172
  SCRCPY_SERVER_PORT,
67
173
  TEXT_MAX_SIZE,
68
- TEXT_SIZE_THRESHOLD
174
+ TEXT_SIZE_THRESHOLD,
175
+ YAML_EXAMPLE_CODE
69
176
  });