@midscene/web 0.3.4 → 0.4.0

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.
@@ -580,9 +580,18 @@ var midscene_element_inspector = (() => {
580
580
  extractTextWithPosition: () => extractTextWithPosition
581
581
  });
582
582
 
583
+ // ../shared/dist/es/constants.js
584
+ var NodeType = /* @__PURE__ */ ((NodeType2) => {
585
+ NodeType2["FORM_ITEM"] = "FORM_ITEM Node";
586
+ NodeType2["BUTTON"] = "BUTTON Node";
587
+ NodeType2["IMG"] = "IMG Node";
588
+ NodeType2["TEXT"] = "TEXT Node";
589
+ return NodeType2;
590
+ })(NodeType || {});
591
+
583
592
  // src/extractor/dom-util.ts
584
- function isInputElement(node) {
585
- return node instanceof HTMLElement && (node.tagName.toLowerCase() === "input" || node.tagName.toLowerCase() === "textarea");
593
+ function isFormElement(node) {
594
+ return node instanceof HTMLElement && (node.tagName.toLowerCase() === "input" || node.tagName.toLowerCase() === "textarea" || node.tagName.toLowerCase() === "label" || node.tagName.toLowerCase() === "select" || node.tagName.toLowerCase() === "option");
586
595
  }
587
596
  function isButtonElement(node) {
588
597
  return node instanceof HTMLElement && node.tagName.toLowerCase() === "button";
@@ -744,6 +753,7 @@ var midscene_element_inspector = (() => {
744
753
  }
745
754
  const shouldContinue = collectElementInfo(node);
746
755
  if (!shouldContinue) {
756
+ logger("should NOT continue for node", node);
747
757
  return;
748
758
  }
749
759
  for (let i = 0; i < node.childNodes.length; i++) {
@@ -759,20 +769,27 @@ var midscene_element_inspector = (() => {
759
769
  logger("Element is not visible", node);
760
770
  return true;
761
771
  }
762
- if (isInputElement(node)) {
772
+ if (isFormElement(node)) {
763
773
  const attributes = getNodeAttributes(node);
764
774
  const nodeHashId = generateHash(attributes.placeholder, rect);
765
775
  const selector = setDataForNode(node, nodeHashId);
776
+ let valueContent = attributes.value || attributes.placeholder || node.textContent || "";
777
+ const tagName = node.tagName.toLowerCase();
778
+ if (node.tagName.toLowerCase() === "select") {
779
+ const selectedOption = node.options[node.selectedIndex];
780
+ valueContent = selectedOption.textContent || "";
781
+ }
766
782
  elementInfoArray.push({
767
783
  id: nodeHashId,
768
784
  indexId: generateId(nodeIndex++),
769
785
  nodeHashId,
770
786
  locator: selector,
771
- nodeType: "INPUT Node" /* INPUT */,
787
+ nodeType: NodeType.FORM_ITEM,
772
788
  attributes: __spreadProps(__spreadValues({}, attributes), {
773
- nodeType: "INPUT Node" /* INPUT */
789
+ htmlTagName: `<${tagName}>`,
790
+ nodeType: NodeType.FORM_ITEM
774
791
  }),
775
- content: attributes.placeholder || "",
792
+ content: valueContent.trim(),
776
793
  rect,
777
794
  center: [
778
795
  Math.round(rect.left + rect.width / 2),
@@ -780,6 +797,8 @@ var midscene_element_inspector = (() => {
780
797
  ],
781
798
  htmlNode: debugMode2 ? node : null
782
799
  });
800
+ if (tagName === "label")
801
+ return true;
783
802
  return;
784
803
  }
785
804
  if (isButtonElement(node)) {
@@ -792,10 +811,10 @@ var midscene_element_inspector = (() => {
792
811
  id: nodeHashId,
793
812
  indexId: generateId(nodeIndex++),
794
813
  nodeHashId,
795
- nodeType: "BUTTON Node" /* BUTTON */,
814
+ nodeType: NodeType.BUTTON,
796
815
  locator: selector,
797
816
  attributes: __spreadProps(__spreadValues({}, attributes), {
798
- nodeType: "BUTTON Node" /* BUTTON */
817
+ nodeType: NodeType.BUTTON
799
818
  }),
800
819
  content,
801
820
  rect,
@@ -817,9 +836,9 @@ var midscene_element_inspector = (() => {
817
836
  nodeHashId,
818
837
  locator: selector,
819
838
  attributes: __spreadProps(__spreadValues({}, attributes), {
820
- nodeType: "IMG Node" /* IMG */
839
+ nodeType: NodeType.IMG
821
840
  }),
822
- nodeType: "IMG Node" /* IMG */,
841
+ nodeType: NodeType.IMG,
823
842
  content: "",
824
843
  rect,
825
844
  center: [
@@ -836,16 +855,20 @@ var midscene_element_inspector = (() => {
836
855
  return;
837
856
  }
838
857
  const attributes = getNodeAttributes(node);
858
+ const attributeKeys = Object.keys(attributes);
859
+ if (!text.trim() && attributeKeys.length === 0) {
860
+ return;
861
+ }
839
862
  const nodeHashId = generateHash(text, rect);
840
863
  const selector = setDataForNode(node, nodeHashId);
841
864
  elementInfoArray.push({
842
865
  id: nodeHashId,
843
866
  indexId: generateId(nodeIndex++),
844
867
  nodeHashId,
845
- nodeType: "TEXT Node" /* TEXT */,
868
+ nodeType: NodeType.TEXT,
846
869
  locator: selector,
847
870
  attributes: __spreadProps(__spreadValues({}, attributes), {
848
- nodeType: "TEXT Node" /* TEXT */
871
+ nodeType: NodeType.TEXT
849
872
  }),
850
873
  center: [
851
874
  Math.round(rect.left + rect.width / 2),
@@ -569,9 +569,18 @@ var midscene_element_inspector = (() => {
569
569
  }
570
570
  });
571
571
 
572
+ // ../shared/dist/es/constants.js
573
+ var NodeType = /* @__PURE__ */ ((NodeType2) => {
574
+ NodeType2["FORM_ITEM"] = "FORM_ITEM Node";
575
+ NodeType2["BUTTON"] = "BUTTON Node";
576
+ NodeType2["IMG"] = "IMG Node";
577
+ NodeType2["TEXT"] = "TEXT Node";
578
+ return NodeType2;
579
+ })(NodeType || {});
580
+
572
581
  // src/extractor/dom-util.ts
573
- function isInputElement(node) {
574
- return node instanceof HTMLElement && (node.tagName.toLowerCase() === "input" || node.tagName.toLowerCase() === "textarea");
582
+ function isFormElement(node) {
583
+ return node instanceof HTMLElement && (node.tagName.toLowerCase() === "input" || node.tagName.toLowerCase() === "textarea" || node.tagName.toLowerCase() === "label" || node.tagName.toLowerCase() === "select" || node.tagName.toLowerCase() === "option");
575
584
  }
576
585
  function isButtonElement(node) {
577
586
  return node instanceof HTMLElement && node.tagName.toLowerCase() === "button";
@@ -733,6 +742,7 @@ var midscene_element_inspector = (() => {
733
742
  }
734
743
  const shouldContinue = collectElementInfo(node);
735
744
  if (!shouldContinue) {
745
+ logger("should NOT continue for node", node);
736
746
  return;
737
747
  }
738
748
  for (let i = 0; i < node.childNodes.length; i++) {
@@ -748,20 +758,27 @@ var midscene_element_inspector = (() => {
748
758
  logger("Element is not visible", node);
749
759
  return true;
750
760
  }
751
- if (isInputElement(node)) {
761
+ if (isFormElement(node)) {
752
762
  const attributes = getNodeAttributes(node);
753
763
  const nodeHashId = generateHash(attributes.placeholder, rect);
754
764
  const selector = setDataForNode(node, nodeHashId);
765
+ let valueContent = attributes.value || attributes.placeholder || node.textContent || "";
766
+ const tagName = node.tagName.toLowerCase();
767
+ if (node.tagName.toLowerCase() === "select") {
768
+ const selectedOption = node.options[node.selectedIndex];
769
+ valueContent = selectedOption.textContent || "";
770
+ }
755
771
  elementInfoArray.push({
756
772
  id: nodeHashId,
757
773
  indexId: generateId(nodeIndex++),
758
774
  nodeHashId,
759
775
  locator: selector,
760
- nodeType: "INPUT Node" /* INPUT */,
776
+ nodeType: NodeType.FORM_ITEM,
761
777
  attributes: __spreadProps(__spreadValues({}, attributes), {
762
- nodeType: "INPUT Node" /* INPUT */
778
+ htmlTagName: `<${tagName}>`,
779
+ nodeType: NodeType.FORM_ITEM
763
780
  }),
764
- content: attributes.placeholder || "",
781
+ content: valueContent.trim(),
765
782
  rect,
766
783
  center: [
767
784
  Math.round(rect.left + rect.width / 2),
@@ -769,6 +786,8 @@ var midscene_element_inspector = (() => {
769
786
  ],
770
787
  htmlNode: debugMode2 ? node : null
771
788
  });
789
+ if (tagName === "label")
790
+ return true;
772
791
  return;
773
792
  }
774
793
  if (isButtonElement(node)) {
@@ -781,10 +800,10 @@ var midscene_element_inspector = (() => {
781
800
  id: nodeHashId,
782
801
  indexId: generateId(nodeIndex++),
783
802
  nodeHashId,
784
- nodeType: "BUTTON Node" /* BUTTON */,
803
+ nodeType: NodeType.BUTTON,
785
804
  locator: selector,
786
805
  attributes: __spreadProps(__spreadValues({}, attributes), {
787
- nodeType: "BUTTON Node" /* BUTTON */
806
+ nodeType: NodeType.BUTTON
788
807
  }),
789
808
  content,
790
809
  rect,
@@ -806,9 +825,9 @@ var midscene_element_inspector = (() => {
806
825
  nodeHashId,
807
826
  locator: selector,
808
827
  attributes: __spreadProps(__spreadValues({}, attributes), {
809
- nodeType: "IMG Node" /* IMG */
828
+ nodeType: NodeType.IMG
810
829
  }),
811
- nodeType: "IMG Node" /* IMG */,
830
+ nodeType: NodeType.IMG,
812
831
  content: "",
813
832
  rect,
814
833
  center: [
@@ -825,16 +844,20 @@ var midscene_element_inspector = (() => {
825
844
  return;
826
845
  }
827
846
  const attributes = getNodeAttributes(node);
847
+ const attributeKeys = Object.keys(attributes);
848
+ if (!text.trim() && attributeKeys.length === 0) {
849
+ return;
850
+ }
828
851
  const nodeHashId = generateHash(text, rect);
829
852
  const selector = setDataForNode(node, nodeHashId);
830
853
  elementInfoArray.push({
831
854
  id: nodeHashId,
832
855
  indexId: generateId(nodeIndex++),
833
856
  nodeHashId,
834
- nodeType: "TEXT Node" /* TEXT */,
857
+ nodeType: NodeType.TEXT,
835
858
  locator: selector,
836
859
  attributes: __spreadProps(__spreadValues({}, attributes), {
837
- nodeType: "TEXT Node" /* TEXT */
860
+ nodeType: NodeType.TEXT
838
861
  }),
839
862
  center: [
840
863
  Math.round(rect.left + rect.width / 2),
@@ -1,8 +1,30 @@
1
1
  import { writeFileSync } from 'node:fs';
2
2
  import { W as WebPage } from './page.d-70ed000f.js';
3
+ import { NodeType } from '@midscene/shared/constants';
3
4
  import 'playwright';
4
5
  import 'puppeteer';
5
6
 
7
+ interface ElementInfo {
8
+ id: string;
9
+ indexId: string;
10
+ nodeHashId: string;
11
+ locator: string;
12
+ attributes: {
13
+ nodeType: NodeType;
14
+ [key: string]: string;
15
+ };
16
+ nodeType: NodeType;
17
+ htmlNode: Node | null;
18
+ content: string;
19
+ rect: {
20
+ left: number;
21
+ top: number;
22
+ width: number;
23
+ height: number;
24
+ };
25
+ center: [number, number];
26
+ }
27
+
6
28
  declare function generateExtractData(page: WebPage, targetDir: string, saveImgType?: {
7
29
  disableInputImage: boolean;
8
30
  disableOutputImage: boolean;
@@ -13,5 +35,30 @@ declare function generateExtractData(page: WebPage, targetDir: string, saveImgTy
13
35
  declare function generateTestDataPath(testDataName: string): string;
14
36
  type WriteFileSyncParams = Parameters<typeof writeFileSync>;
15
37
  declare function writeFileSyncWithDir(filePath: string, content: WriteFileSyncParams[1], options?: WriteFileSyncParams[2]): void;
38
+ declare function getElementInfos(page: any): Promise<{
39
+ elementsPositionInfo: {
40
+ label: string;
41
+ x: number;
42
+ y: number;
43
+ width: number;
44
+ height: number;
45
+ attributes: {
46
+ [key: string]: string;
47
+ nodeType: NodeType;
48
+ };
49
+ }[];
50
+ captureElementSnapshot: ElementInfo[];
51
+ elementsPositionInfoWithoutText: {
52
+ label: string;
53
+ x: number;
54
+ y: number;
55
+ width: number;
56
+ height: number;
57
+ attributes: {
58
+ [key: string]: string;
59
+ nodeType: NodeType;
60
+ };
61
+ }[];
62
+ }>;
16
63
 
17
- export { generateExtractData, generateTestDataPath, writeFileSyncWithDir };
64
+ export { generateExtractData, generateTestDataPath, getElementInfos, writeFileSyncWithDir };
@@ -4,8 +4,9 @@ export { generateExtractData } from './debug.js';
4
4
  import '@midscene/core/.';
5
5
  import '@playwright/test';
6
6
  import 'playwright';
7
- import './tasks-75eae15e.js';
7
+ import './tasks-ce3a7499.js';
8
8
  import './page.d-70ed000f.js';
9
9
  import 'puppeteer';
10
10
  import '@midscene/core';
11
+ import '@midscene/shared/constants';
11
12
  import 'node:fs';
@@ -1,10 +1,11 @@
1
1
  import { AgentWaitForOpt } from '@midscene/core/.';
2
2
  import { TestInfo } from '@playwright/test';
3
3
  import { Page } from 'playwright';
4
- import { P as PageTaskExecutor } from './tasks-75eae15e.js';
4
+ import { P as PageTaskExecutor } from './tasks-ce3a7499.js';
5
5
  import './page.d-70ed000f.js';
6
6
  import 'puppeteer';
7
7
  import '@midscene/core';
8
+ import '@midscene/shared/constants';
8
9
 
9
10
  declare const PlaywrightAiFixture: () => {
10
11
  ai: ({ page }: {
@@ -1,8 +1,9 @@
1
1
  import { W as WebPage } from './page.d-70ed000f.js';
2
2
  import { GroupedActionDump, ExecutionDump, AgentWaitForOpt } from '@midscene/core';
3
- import { P as PageTaskExecutor, A as AiTaskCache } from './tasks-75eae15e.js';
3
+ import { P as PageTaskExecutor, A as AiTaskCache } from './tasks-ce3a7499.js';
4
4
  import 'playwright';
5
5
  import 'puppeteer';
6
+ import '@midscene/shared/constants';
6
7
 
7
8
  interface PageAgentOpt {
8
9
  testId?: string;
@@ -1,12 +1,6 @@
1
1
  import { W as WebPage } from './page.d-70ed000f.js';
2
2
  import Insight, { BaseElement, Rect, UIContext, PlanningAction, AIElementParseResponse, InsightExtractParam, InsightAssertionResponse, PlanningActionParamWaitFor, Executor } from '@midscene/core';
3
-
4
- declare enum NodeType {
5
- INPUT = "INPUT Node",
6
- BUTTON = "BUTTON Node",
7
- IMG = "IMG Node",
8
- TEXT = "TEXT Node"
9
- }
3
+ import { NodeType } from '@midscene/shared/constants';
10
4
 
11
5
  declare class WebElementInfo implements BaseElement {
12
6
  content: string;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@midscene/web",
3
3
  "description": "Web integration for Midscene.js",
4
- "version": "0.3.4",
4
+ "version": "0.4.0",
5
5
  "jsnext:source": "./src/index.ts",
6
6
  "main": "./dist/lib/index.js",
7
7
  "module": "./dist/es/index.js",
@@ -74,12 +74,12 @@
74
74
  ],
75
75
  "dependencies": {
76
76
  "openai": "4.47.1",
77
- "sharp": "0.33.3",
78
77
  "inquirer": "10.1.5",
79
- "@midscene/core": "0.3.4"
78
+ "@midscene/core": "0.4.0",
79
+ "@midscene/shared": "0.4.0"
80
80
  },
81
81
  "devDependencies": {
82
- "@modern-js/module-tools": "^2.56.1",
82
+ "@modern-js/module-tools": "2.58.2",
83
83
  "js-sha256": "0.11.0",
84
84
  "@types/node": "^18.0.0",
85
85
  "typescript": "~5.0.4",
@@ -1,30 +0,0 @@
1
- declare enum NodeType {
2
- INPUT = "INPUT Node",
3
- BUTTON = "BUTTON Node",
4
- IMG = "IMG Node",
5
- TEXT = "TEXT Node"
6
- }
7
-
8
- interface ElementInfo {
9
- id: string;
10
- indexId: string;
11
- nodeHashId: string;
12
- locator: string;
13
- attributes: {
14
- nodeType: NodeType;
15
- [key: string]: string;
16
- };
17
- nodeType: NodeType;
18
- htmlNode: Node | null;
19
- content: string;
20
- rect: {
21
- left: number;
22
- top: number;
23
- width: number;
24
- height: number;
25
- };
26
- center: [number, number];
27
- }
28
- declare function extractTextWithPosition(initNode?: Node, debugMode?: boolean): ElementInfo[];
29
-
30
- export { extractTextWithPosition };
@@ -1,2 +0,0 @@
1
-
2
- export { }