@midscene/web 0.0.1 → 0.1.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.
- package/dist/es/index.js +337 -110
- package/dist/es/playwright-report.js +2380 -0
- package/dist/lib/index.js +338 -110
- package/dist/lib/playwright-report.js +2383 -0
- package/dist/script/htmlElement.js +596 -25
- package/dist/script/types/htmlElement.d.ts +2 -0
- package/dist/types/index.d.ts +116 -21
- package/dist/types/playwright-report.d.ts +10 -0
- package/package.json +25 -4
- package/modern.config.ts +0 -13
- package/modern.inspect.config.ts +0 -20
- package/playwright.config.ts +0 -42
- package/src/html-element/constants.ts +0 -10
- package/src/html-element/debug.ts +0 -3
- package/src/html-element/dom-util.ts +0 -11
- package/src/html-element/extractInfo.ts +0 -168
- package/src/html-element/index.ts +0 -1
- package/src/html-element/util.ts +0 -160
- package/src/img/img.ts +0 -132
- package/src/img/util.ts +0 -28
- package/src/index.ts +0 -2
- package/src/playwright/actions.ts +0 -276
- package/src/playwright/cdp.ts +0 -322
- package/src/playwright/element.ts +0 -74
- package/src/playwright/index.ts +0 -120
- package/src/playwright/utils.ts +0 -88
- package/src/puppeteer/element.ts +0 -49
- package/src/puppeteer/index.ts +0 -6
- package/src/puppeteer/utils.ts +0 -116
- package/tests/e2e/ai-auto-todo.spec.ts +0 -24
- package/tests/e2e/ai-xicha.spec.ts +0 -34
- package/tests/e2e/fixture.ts +0 -6
- package/tests/e2e/generate-test-data.spec.ts +0 -60
- package/tests/e2e/todo-app-midscene.spec.ts +0 -98
- package/tests/e2e/tool.ts +0 -63
- package/tsconfig.json +0 -23
- package/vitest.config.ts +0 -14
package/dist/types/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { TestInfo } from '@playwright/test';
|
|
2
1
|
import { Page } from 'playwright';
|
|
3
|
-
import
|
|
2
|
+
import { TestInfo } from '@playwright/test';
|
|
3
|
+
import Insight, { BaseElement, Rect, UIContext, PlanningAction, AIElementParseResponse, ExecutionDump, InsightExtractParam, GroupedActionDump } from '@midscene/core';
|
|
4
|
+
import { Page as Page$1 } from 'puppeteer';
|
|
4
5
|
|
|
5
6
|
declare enum NodeType {
|
|
6
7
|
'INPUT' = "INPUT Node",
|
|
@@ -9,12 +10,14 @@ declare enum NodeType {
|
|
|
9
10
|
'TEXT' = "TEXT Node"
|
|
10
11
|
}
|
|
11
12
|
|
|
13
|
+
type WebPage = Page | Page$1;
|
|
14
|
+
|
|
12
15
|
declare class WebElementInfo implements BaseElement {
|
|
13
16
|
content: string;
|
|
14
17
|
locator: string;
|
|
15
18
|
rect: Rect;
|
|
16
19
|
center: [number, number];
|
|
17
|
-
page:
|
|
20
|
+
page: WebPage;
|
|
18
21
|
id: string;
|
|
19
22
|
attributes: {
|
|
20
23
|
['nodeType']: NodeType;
|
|
@@ -23,7 +26,7 @@ declare class WebElementInfo implements BaseElement {
|
|
|
23
26
|
constructor({ content, rect, page, locator, id, attributes, }: {
|
|
24
27
|
content: string;
|
|
25
28
|
rect: Rect;
|
|
26
|
-
page:
|
|
29
|
+
page: WebPage;
|
|
27
30
|
locator: string;
|
|
28
31
|
id: string;
|
|
29
32
|
attributes: {
|
|
@@ -31,19 +34,85 @@ declare class WebElementInfo implements BaseElement {
|
|
|
31
34
|
[key: string]: string;
|
|
32
35
|
};
|
|
33
36
|
});
|
|
34
|
-
tap(): Promise<void>;
|
|
35
|
-
hover(): Promise<void>;
|
|
36
|
-
type(text: string): Promise<void>;
|
|
37
|
-
press(key: Parameters<typeof this$1.page.keyboard.press>[0]): Promise<void>;
|
|
38
37
|
}
|
|
39
38
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
39
|
+
type WebUIContext = UIContext<WebElementInfo> & {
|
|
40
|
+
url: string;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
type PlanTask = {
|
|
44
|
+
type: 'plan';
|
|
45
|
+
prompt: string;
|
|
46
|
+
pageContext: {
|
|
47
|
+
url: string;
|
|
48
|
+
size: {
|
|
49
|
+
width: number;
|
|
50
|
+
height: number;
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
response: {
|
|
54
|
+
plans: PlanningAction[];
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
type LocateTask = {
|
|
58
|
+
type: 'locate';
|
|
59
|
+
prompt: string;
|
|
60
|
+
pageContext: {
|
|
61
|
+
url: string;
|
|
62
|
+
size: {
|
|
63
|
+
width: number;
|
|
64
|
+
height: number;
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
response: AIElementParseResponse;
|
|
68
|
+
};
|
|
69
|
+
type AiTasks = Array<PlanTask | LocateTask>;
|
|
70
|
+
type AiTaskCache = {
|
|
71
|
+
aiTasks: AiTasks;
|
|
72
|
+
};
|
|
73
|
+
declare class TaskCache {
|
|
74
|
+
cache: AiTaskCache | undefined;
|
|
75
|
+
newCache: AiTaskCache;
|
|
76
|
+
constructor(opts?: {
|
|
77
|
+
cache: AiTaskCache;
|
|
78
|
+
});
|
|
79
|
+
/**
|
|
80
|
+
* Read and return cached responses asynchronously based on specific criteria
|
|
81
|
+
* This function is mainly used to read cached responses from a certain storage medium.
|
|
82
|
+
* It accepts three parameters: the page context information, the task type, and the user's prompt information.
|
|
83
|
+
* In the function, it first checks whether there is cached data. If there is, it retrieves the first task response from the cache.
|
|
84
|
+
* It then checks whether the task type is 'locate' and whether the corresponding element can be found in the new context.
|
|
85
|
+
* If the element cannot be found, it returns false, indicating that the cache is invalid.
|
|
86
|
+
* If the task type is correct and the user prompt matches, it checks whether the page context is the same.
|
|
87
|
+
* If the page context is the same, it returns the cached response, indicating that the cache hit is successful.
|
|
88
|
+
* If there is no cached data or the conditions are not met, the function returns false, indicating that no cache is available or the cache is not hit.
|
|
89
|
+
*
|
|
90
|
+
* @param pageContext UIContext<WebElementInfo> type, representing the context information of the current page
|
|
91
|
+
* @param type String type, specifying the task type, can be 'plan' or 'locate'
|
|
92
|
+
* @param userPrompt String type, representing user prompt information
|
|
93
|
+
* @return Returns a Promise object that resolves to a boolean or object
|
|
94
|
+
*/
|
|
95
|
+
readCache(pageContext: WebUIContext, type: 'plan', userPrompt: string): PlanTask['response'];
|
|
96
|
+
readCache(pageContext: WebUIContext, type: 'locate', userPrompt: string): LocateTask['response'];
|
|
97
|
+
saveCache(cache: PlanTask | LocateTask): void;
|
|
98
|
+
pageContextEqual(taskPageContext: LocateTask['pageContext'], pageContext: WebUIContext): boolean;
|
|
99
|
+
/**
|
|
100
|
+
* Generate task cache data.
|
|
101
|
+
* This method is mainly used to create or obtain some cached data for tasks, and it returns a new cache object.
|
|
102
|
+
* In the cache object, it may contain task-related information, states, or other necessary data.
|
|
103
|
+
* It is assumed that the `newCache` property already exists in the current class or object and is a data structure used to store task cache.
|
|
104
|
+
* @returns {Object} Returns a new cache object, which may include task cache data.
|
|
105
|
+
*/
|
|
106
|
+
generateTaskCache(): AiTaskCache;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
declare class PageTaskExecutor {
|
|
110
|
+
page: WebPage;
|
|
111
|
+
insight: Insight<WebElementInfo, WebUIContext>;
|
|
112
|
+
executionDump?: ExecutionDump;
|
|
113
|
+
taskCache: TaskCache;
|
|
114
|
+
constructor(page: WebPage, opts: {
|
|
115
|
+
cache: AiTaskCache;
|
|
47
116
|
});
|
|
48
117
|
private recordScreenshot;
|
|
49
118
|
private wrapExecutorWithScreenshot;
|
|
@@ -53,14 +122,40 @@ declare class PlayWrightActionAgent {
|
|
|
53
122
|
}
|
|
54
123
|
|
|
55
124
|
declare const PlaywrightAiFixture: () => {
|
|
56
|
-
ai: ({ page }:
|
|
57
|
-
|
|
58
|
-
|
|
125
|
+
ai: ({ page }: {
|
|
126
|
+
page: Page;
|
|
127
|
+
}, use: any, testInfo: TestInfo) => Promise<void>;
|
|
128
|
+
aiAction: ({ page }: {
|
|
129
|
+
page: Page;
|
|
130
|
+
}, use: any, testInfo: TestInfo) => Promise<void>;
|
|
131
|
+
aiQuery: ({ page }: {
|
|
132
|
+
page: Page;
|
|
133
|
+
}, use: any, testInfo: TestInfo) => Promise<void>;
|
|
59
134
|
};
|
|
60
135
|
type PlayWrightAiFixtureType = {
|
|
61
|
-
ai: <T = any>(prompt: string,
|
|
62
|
-
|
|
136
|
+
ai: <T = any>(prompt: string, opts?: {
|
|
137
|
+
type?: 'action' | 'query';
|
|
138
|
+
}) => Promise<T>;
|
|
139
|
+
aiAction: (taskPrompt: string) => ReturnType<PageTaskExecutor['action']>;
|
|
63
140
|
aiQuery: <T = any>(demand: any) => Promise<T>;
|
|
64
141
|
};
|
|
65
142
|
|
|
66
|
-
|
|
143
|
+
declare class PageAgent {
|
|
144
|
+
page: WebPage;
|
|
145
|
+
dumps: GroupedActionDump[];
|
|
146
|
+
testId: string;
|
|
147
|
+
dumpFile?: string;
|
|
148
|
+
actionAgent: PageTaskExecutor;
|
|
149
|
+
constructor(page: WebPage, opts: {
|
|
150
|
+
testId?: string;
|
|
151
|
+
taskFile?: string;
|
|
152
|
+
cache?: AiTaskCache;
|
|
153
|
+
});
|
|
154
|
+
appendDump(execution: ExecutionDump): void;
|
|
155
|
+
writeOutActionDumps(): void;
|
|
156
|
+
aiAction(taskPrompt: string): Promise<void>;
|
|
157
|
+
aiQuery(demand: any): Promise<any>;
|
|
158
|
+
ai(taskPrompt: string, type?: string): Promise<any>;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export { type PlayWrightAiFixtureType, PlaywrightAiFixture, PageAgent as PuppeteerAgent };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Reporter, FullConfig, Suite, TestCase, TestResult, FullResult } from '@playwright/test/reporter';
|
|
2
|
+
|
|
3
|
+
declare class MidSceneReporter implements Reporter {
|
|
4
|
+
onBegin(config: FullConfig, suite: Suite): Promise<void>;
|
|
5
|
+
onTestBegin(test: TestCase, _result: TestResult): void;
|
|
6
|
+
onTestEnd(test: TestCase, result: TestResult): void;
|
|
7
|
+
onEnd(result: FullResult): void;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export { MidSceneReporter as default };
|
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.0
|
|
4
|
+
"version": "0.1.0",
|
|
5
5
|
"jsnext:source": "./src/index.ts",
|
|
6
6
|
"main": "./dist/lib/index.js",
|
|
7
7
|
"module": "./dist/es/index.js",
|
|
@@ -12,6 +12,11 @@
|
|
|
12
12
|
"import": "./dist/es/index.js",
|
|
13
13
|
"require": "./dist/lib/index.js"
|
|
14
14
|
},
|
|
15
|
+
"./playwright-report": {
|
|
16
|
+
"types": "./dist/types/playwright-report.d.ts",
|
|
17
|
+
"import": "./dist/es/playwright-report.js",
|
|
18
|
+
"require": "./dist/lib/inplaywright-report.js"
|
|
19
|
+
},
|
|
15
20
|
"./constants": {
|
|
16
21
|
"types": "./dist/types/constants.d.ts",
|
|
17
22
|
"import": "./dist/es/constants.js",
|
|
@@ -28,6 +33,9 @@
|
|
|
28
33
|
".": [
|
|
29
34
|
"./dist/types/index.d.ts"
|
|
30
35
|
],
|
|
36
|
+
"playwright-report": [
|
|
37
|
+
"./dist/types/playwright-report.d.ts"
|
|
38
|
+
],
|
|
31
39
|
"constants": [
|
|
32
40
|
"./dist/types/constants.d.ts"
|
|
33
41
|
],
|
|
@@ -36,19 +44,28 @@
|
|
|
36
44
|
]
|
|
37
45
|
}
|
|
38
46
|
},
|
|
47
|
+
"files": [
|
|
48
|
+
"dist",
|
|
49
|
+
"README.md"
|
|
50
|
+
],
|
|
39
51
|
"dependencies": {
|
|
40
52
|
"openai": "4.47.1",
|
|
41
53
|
"sharp": "0.33.3",
|
|
42
|
-
"
|
|
54
|
+
"inquirer": "10.1.5",
|
|
55
|
+
"@midscene/core": "0.1.0",
|
|
56
|
+
"@midscene/visualizer-report": "0.1.0"
|
|
43
57
|
},
|
|
44
58
|
"devDependencies": {
|
|
45
59
|
"@modern-js/module-tools": "^2.54.2",
|
|
60
|
+
"js-sha256": "0.11.0",
|
|
46
61
|
"@types/node": "^18.0.0",
|
|
47
62
|
"typescript": "~5.0.4",
|
|
48
63
|
"vitest": "^1.6.0",
|
|
49
64
|
"playwright": "1.44.1",
|
|
50
65
|
"puppeteer": "^22.8.0",
|
|
51
|
-
"@playwright/test": "1.44.1"
|
|
66
|
+
"@playwright/test": "1.44.1",
|
|
67
|
+
"fs-extra": "11.2.0",
|
|
68
|
+
"@types/fs-extra": "11.0.4"
|
|
52
69
|
},
|
|
53
70
|
"peerDependencies": {
|
|
54
71
|
"@playwright/test": "^1.44.1",
|
|
@@ -77,9 +94,13 @@
|
|
|
77
94
|
"build:pkg": "modern build -c ./modern.config.ts",
|
|
78
95
|
"build:script": "modern build -c ./modern.inspect.config.ts",
|
|
79
96
|
"build:watch": "modern build -w -c ./modern.config.ts & modern build -w -c ./modern.inspect.config.ts",
|
|
97
|
+
"test": "vitest --run",
|
|
98
|
+
"test:all": "AITEST=true vitest --run",
|
|
80
99
|
"new": "modern new",
|
|
81
100
|
"upgrade": "modern upgrade",
|
|
82
101
|
"e2e": "playwright test --config=playwright.config.ts",
|
|
83
|
-
"e2e:
|
|
102
|
+
"e2e:cache": "MIDSCENE_CACHE=true playwright test --config=playwright.config.ts",
|
|
103
|
+
"e2e:ui": "playwright test --config=playwright.config.ts --ui",
|
|
104
|
+
"e2e:ui-cache": "MIDSCENE_CACHE=true playwright test --config=playwright.config.ts --ui"
|
|
84
105
|
}
|
|
85
106
|
}
|
package/modern.config.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { moduleTools, defineConfig } from '@modern-js/module-tools';
|
|
2
|
-
|
|
3
|
-
export default defineConfig({
|
|
4
|
-
plugins: [moduleTools()],
|
|
5
|
-
buildPreset: 'npm-library',
|
|
6
|
-
buildConfig: {
|
|
7
|
-
platform: 'node',
|
|
8
|
-
input: {
|
|
9
|
-
index: 'src/index.ts',
|
|
10
|
-
},
|
|
11
|
-
target: 'es2017',
|
|
12
|
-
},
|
|
13
|
-
});
|
package/modern.inspect.config.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { moduleTools, defineConfig } from '@modern-js/module-tools';
|
|
2
|
-
|
|
3
|
-
// It was split into two configuration files because of a bug in the build config array
|
|
4
|
-
export default defineConfig({
|
|
5
|
-
plugins: [moduleTools()],
|
|
6
|
-
buildPreset: 'npm-library',
|
|
7
|
-
buildConfig: {
|
|
8
|
-
buildType: 'bundle',
|
|
9
|
-
format: 'iife',
|
|
10
|
-
input: {
|
|
11
|
-
htmlElement:'src/html-element/index.ts',
|
|
12
|
-
},
|
|
13
|
-
outDir: 'dist/script',
|
|
14
|
-
esbuildOptions: options => {
|
|
15
|
-
options.globalName = 'midscene_element_inspector'
|
|
16
|
-
return options;
|
|
17
|
-
},
|
|
18
|
-
target: 'es2017',
|
|
19
|
-
}
|
|
20
|
-
});
|
package/playwright.config.ts
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { defineConfig, devices } from '@playwright/test';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Read environment variables from file.
|
|
5
|
-
* https://github.com/motdotla/dotenv
|
|
6
|
-
*/
|
|
7
|
-
// require('dotenv').config();
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* See https://playwright.dev/docs/test-configuration.
|
|
11
|
-
*/
|
|
12
|
-
export default defineConfig({
|
|
13
|
-
testDir: './tests/e2e',
|
|
14
|
-
timeout: 90000 * 1000,
|
|
15
|
-
/* Run tests in files in parallel */
|
|
16
|
-
fullyParallel: true,
|
|
17
|
-
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
|
18
|
-
forbidOnly: !!process.env.CI,
|
|
19
|
-
/* Retry on CI only */
|
|
20
|
-
retries: process.env.CI ? 2 : 0,
|
|
21
|
-
/* Opt out of parallel tests on CI. */
|
|
22
|
-
workers: process.env.CI ? 1 : undefined,
|
|
23
|
-
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
|
24
|
-
reporter: 'html',
|
|
25
|
-
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
|
26
|
-
use: {
|
|
27
|
-
/* Base URL to use in actions like `await page.goto('/')`. */
|
|
28
|
-
// baseURL: 'http://127.0.0.1:3000',
|
|
29
|
-
|
|
30
|
-
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
|
31
|
-
trace: 'on-first-retry',
|
|
32
|
-
},
|
|
33
|
-
|
|
34
|
-
/* Configure projects for major browsers */
|
|
35
|
-
projects: [
|
|
36
|
-
{
|
|
37
|
-
name: 'chromium',
|
|
38
|
-
use: { ...devices['Desktop Chrome'] },
|
|
39
|
-
},
|
|
40
|
-
],
|
|
41
|
-
|
|
42
|
-
});
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export function isInputElement(node: Node): node is HTMLInputElement {
|
|
2
|
-
return node instanceof HTMLElement && node.tagName.toLowerCase() === 'input';
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
export function isButtonElement(node: Node): node is HTMLButtonElement {
|
|
6
|
-
return node instanceof HTMLElement && node.tagName.toLowerCase() === 'button';
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export function isImgElement(node: Node): node is HTMLImageElement {
|
|
10
|
-
return node instanceof HTMLElement && node.tagName.toLowerCase() === 'img';
|
|
11
|
-
}
|
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
getNodeAttributes,
|
|
3
|
-
getPseudoElementContent,
|
|
4
|
-
logger,
|
|
5
|
-
setDataForNode,
|
|
6
|
-
validTextNodeContent,
|
|
7
|
-
visibleRect,
|
|
8
|
-
} from './util';
|
|
9
|
-
import { NodeType, TEXT_SIZE_THRESHOLD } from './constants';
|
|
10
|
-
import { isButtonElement, isImgElement, isInputElement } from './dom-util';
|
|
11
|
-
|
|
12
|
-
interface NodeDescriptor {
|
|
13
|
-
node: Node;
|
|
14
|
-
childrens: NodeDescriptor[];
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export interface ElementInfo {
|
|
18
|
-
id: string;
|
|
19
|
-
locator: string | void;
|
|
20
|
-
attributes: {
|
|
21
|
-
nodeType: NodeType;
|
|
22
|
-
[key: string]: string;
|
|
23
|
-
};
|
|
24
|
-
content: string;
|
|
25
|
-
rect: { left: number; top: number; width: number; height: number };
|
|
26
|
-
center: [number, number];
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const container: HTMLElement = document.body;
|
|
30
|
-
|
|
31
|
-
function generateId(numberId: number) {
|
|
32
|
-
// const letters = 'ABCDEFGHIJKLMNPRSTUVXYZ';
|
|
33
|
-
// const numbers = '0123456789';
|
|
34
|
-
// const randomLetter = letters.charAt(Math.floor(Math.random() * letters.length)).toUpperCase();
|
|
35
|
-
// const randomNumber = numbers.charAt(Math.floor(Math.random() * numbers.length));
|
|
36
|
-
// return randomLetter + numberId;
|
|
37
|
-
return `${numberId}`;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export function extractTextWithPositionDFS(initNode: Node = container): ElementInfo[] {
|
|
41
|
-
const elementInfoArray: ElementInfo[] = [];
|
|
42
|
-
const nodeMapTree: NodeDescriptor = { node: initNode, childrens: [] };
|
|
43
|
-
let nodeIndex = 1;
|
|
44
|
-
|
|
45
|
-
function dfs(node: Node, parentNode: NodeDescriptor | null = null): void {
|
|
46
|
-
if (!node) {
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const currentNodeDes: NodeDescriptor = { node, childrens: [] };
|
|
51
|
-
if (parentNode?.childrens) {
|
|
52
|
-
parentNode.childrens.push(currentNodeDes);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
collectElementInfo(node);
|
|
56
|
-
|
|
57
|
-
// eslint-disable-next-line @typescript-eslint/prefer-for-of
|
|
58
|
-
for (let i = 0; i < node.childNodes.length; i++) {
|
|
59
|
-
logger('will dfs', node.childNodes[i]);
|
|
60
|
-
dfs(node.childNodes[i], currentNodeDes);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function collectElementInfo(node: Node) {
|
|
65
|
-
const rect = visibleRect(node);
|
|
66
|
-
if (!rect) {
|
|
67
|
-
logger('Element is not visible', node);
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
if (isInputElement(node)) {
|
|
72
|
-
const attributes = getNodeAttributes(node);
|
|
73
|
-
const selector = setDataForNode(node, nodeIndex);
|
|
74
|
-
elementInfoArray.push({
|
|
75
|
-
id: generateId(nodeIndex++),
|
|
76
|
-
locator: selector,
|
|
77
|
-
attributes: {
|
|
78
|
-
...attributes,
|
|
79
|
-
nodeType: NodeType.INPUT,
|
|
80
|
-
},
|
|
81
|
-
content: attributes.placeholder || '',
|
|
82
|
-
rect,
|
|
83
|
-
center: [Math.round(rect.left + rect.width / 2), Math.round(rect.top + rect.height / 2)],
|
|
84
|
-
});
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
if (isButtonElement(node)) {
|
|
89
|
-
const attributes = getNodeAttributes(node);
|
|
90
|
-
const pseudo = getPseudoElementContent(node);
|
|
91
|
-
const selector = setDataForNode(node, nodeIndex);
|
|
92
|
-
elementInfoArray.push({
|
|
93
|
-
id: generateId(nodeIndex++),
|
|
94
|
-
locator: selector,
|
|
95
|
-
attributes: {
|
|
96
|
-
...attributes,
|
|
97
|
-
nodeType: NodeType.BUTTON,
|
|
98
|
-
},
|
|
99
|
-
content: node.innerText || pseudo.before || pseudo.after || '',
|
|
100
|
-
rect,
|
|
101
|
-
center: [Math.round(rect.left + rect.width / 2), Math.round(rect.top + rect.height / 2)],
|
|
102
|
-
});
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
if (isImgElement(node)) {
|
|
107
|
-
const attributes = getNodeAttributes(node);
|
|
108
|
-
const selector = setDataForNode(node, nodeIndex);
|
|
109
|
-
elementInfoArray.push({
|
|
110
|
-
id: generateId(nodeIndex++),
|
|
111
|
-
locator: selector,
|
|
112
|
-
attributes: {
|
|
113
|
-
...attributes,
|
|
114
|
-
nodeType: NodeType.IMG,
|
|
115
|
-
},
|
|
116
|
-
content: '',
|
|
117
|
-
rect,
|
|
118
|
-
center: [Math.round(rect.left + rect.width / 2), Math.round(rect.top + rect.height / 2)],
|
|
119
|
-
});
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// if (node instanceof HTMLElement && hasOverflowY(node)) {
|
|
124
|
-
// const rect = visibleRect(node);
|
|
125
|
-
// if (!rect || rect.height < 100) {
|
|
126
|
-
// logger('Element is not visible', node);
|
|
127
|
-
// } else {
|
|
128
|
-
// const attributes = getNodeAttributes(node);
|
|
129
|
-
// const selector = setDataForNode(node, nodeIndex);
|
|
130
|
-
// elementInfoArray.push({
|
|
131
|
-
// id: nodeIndex++,
|
|
132
|
-
// nodeType: 'ScrollContainer Node',
|
|
133
|
-
// locator: selector!,
|
|
134
|
-
// parentIndex,
|
|
135
|
-
// attributes,
|
|
136
|
-
// content: "",
|
|
137
|
-
// rect,
|
|
138
|
-
// center: [Math.round(rect.left + rect.width / 2), Math.round(rect.top + rect.height / 2)],
|
|
139
|
-
// });
|
|
140
|
-
// }
|
|
141
|
-
// }
|
|
142
|
-
|
|
143
|
-
const text = validTextNodeContent(node);
|
|
144
|
-
if (text) {
|
|
145
|
-
if (rect.width < TEXT_SIZE_THRESHOLD || rect.height < TEXT_SIZE_THRESHOLD) {
|
|
146
|
-
logger('Element is too small', text);
|
|
147
|
-
return;
|
|
148
|
-
}
|
|
149
|
-
const attributes = getNodeAttributes(node);
|
|
150
|
-
const selector = setDataForNode(node, nodeIndex);
|
|
151
|
-
elementInfoArray.push({
|
|
152
|
-
id: generateId(nodeIndex++),
|
|
153
|
-
attributes: {
|
|
154
|
-
...attributes,
|
|
155
|
-
nodeType: NodeType.TEXT,
|
|
156
|
-
},
|
|
157
|
-
locator: selector,
|
|
158
|
-
center: [Math.round(rect.left + rect.width / 2), Math.round(rect.top + rect.height / 2)],
|
|
159
|
-
// attributes,
|
|
160
|
-
content: text,
|
|
161
|
-
rect,
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
dfs(initNode, nodeMapTree);
|
|
167
|
-
return elementInfoArray;
|
|
168
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { extractTextWithPositionDFS } from './extractInfo';
|