Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(web-extract): fix the extractor may fail if there is no <body/> #76

Merged
merged 7 commits into from
Aug 28, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions packages/web-integration/src/common/tasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,8 @@ export class PageTaskExecutor {
type: 'Insight',
subType: 'Locate',
param: plan.param,
executor: async (param) => {
executor: async (param, taskContext) => {
const { task } = taskContext;
let insightDump: InsightDump | undefined;
const dumpCollector: DumpSubscriber = (dump) => {
insightDump = dump;
Expand All @@ -124,7 +125,6 @@ export class PageTaskExecutor {
},
});

assert(element, `Element not found: ${param.prompt}`);
if (locateResult) {
this.taskCache.saveCache({
type: 'locate',
Expand All @@ -136,6 +136,13 @@ export class PageTaskExecutor {
response: locateResult,
});
}
if (!element) {
task.log = {
dump: insightDump,
};
throw new Error(`Element not found: ${param.prompt}`);
}

return {
output: {
element,
Expand Down
1 change: 1 addition & 0 deletions packages/web-integration/src/extractor/debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ import { extractTextWithPosition } from '.';

console.log(extractTextWithPosition(document.body, true));
console.log(JSON.stringify(extractTextWithPosition(document.body, false)));
(window as any).extractTextWithPosition = extractTextWithPosition;
9 changes: 9 additions & 0 deletions packages/web-integration/src/extractor/dom-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,12 @@ export function isImgElement(node: Node): node is HTMLImageElement {
export function isTextElement(node: Node): node is HTMLTextAreaElement {
return node.nodeName.toLowerCase() === '#text';
}

export function isWidgetElement(node: Node): node is HTMLElement {
return (
node instanceof HTMLElement &&
(node.hasAttribute('aria-label') ||
node.hasAttribute('aria-controls') ||
node.hasAttribute('aria-labelledby'))
);
}
30 changes: 28 additions & 2 deletions packages/web-integration/src/extractor/extractor.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { NodeType, TEXT_SIZE_THRESHOLD } from '@midscene/shared/constants';
import { NodeType } from '@midscene/shared/constants';
import {
isButtonElement,
isFormElement,
isImgElement,
isTextElement,
isWidgetElement,
} from './dom-util';
import {
generateHash,
Expand Down Expand Up @@ -36,7 +37,7 @@ export interface ElementInfo {
center: [number, number];
}

const container: HTMLElement = document.body;
const container: HTMLElement = document.body || document;

function generateId(numberId: number) {
// const letters = 'ABCDEFGHIJKLMNPRSTUVXYZ';
Expand Down Expand Up @@ -212,6 +213,31 @@ export function extractTextWithPosition(
return;
}

if (isWidgetElement(node)) {
const attributes = getNodeAttributes(node);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

为什么这里是判断有没有 aria 属性就是 form 元素了

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个是不是直接判断可见性,如果这个节点不是 input、img、text,并且是可见的有宽高的,我们就把他加到里面去,类型是 container,是不是可以减少类似的问题

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

不过这里需要避免子节点再次被添加直接 return 返回空就行了,这样子节点不会再次被遍历,到这里就终止了

const nodeHashId = generateHash('', rect);
const selector = setDataForNode(node, nodeHashId);
elementInfoArray.push({
id: nodeHashId,
indexId: generateId(nodeIndex++),
nodeHashId,
nodeType: NodeType.FORM_ITEM,
locator: selector,
attributes: {
...attributes,
nodeType: NodeType.FORM_ITEM,
},
content: '',
rect,
center: [
Math.round(rect.left + rect.width / 2),
Math.round(rect.top + rect.height / 2),
],
htmlNode: debugMode ? node : null,
});
return true;
}

return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -372,5 +372,36 @@ exports[`extractor > basic 1`] = `
},
"content": "",
},
{
"attributes": {
"aria-label": "Click me",
"class": ".widget",
"nodeType": "FORM_ITEM Node",
"role": "button",
},
"content": "",
},
{
"attributes": {
"nodeType": "TEXT Node",
},
"content": "Click me",
},
{
"attributes": {
"aria-controls": "semi-select-5yxiyng",
"class": ".widget",
"nodeType": "FORM_ITEM Node",
},
"content": "",
},
{
"attributes": {
"aria-labelledby": "eval_object.object_type-label",
"class": ".widget",
"nodeType": "FORM_ITEM Node",
},
"content": "",
},
]
`;
Loading
Loading