Skip to content

Commit

Permalink
feat: support document as startNodes in `browsingContext.locateNode…
Browse files Browse the repository at this point in the history
…s` (#2218)

* w3c/webdriver-bidi#705
* w3c/webdriver-bidi#713
* web-platform-tests/wpt#46345

---------

Signed-off-by: Browser Automation Bot <[email protected]>
Co-authored-by: Browser Automation Bot <[email protected]>
  • Loading branch information
sadym-chromium and browser-automation-bot authored May 21, 2024
1 parent b5f7a08 commit ad7318f
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 21 deletions.
37 changes: 28 additions & 9 deletions src/bidiMapper/modules/context/BrowsingContextImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1105,12 +1105,12 @@ export class BrowsingContextImpl {
(
xPathSelector: string,
maxNodeCount: number,
...startNodes: HTMLElement[]
...startNodes: Node[]
) => {
// https://w3c.github.io/webdriver-bidi/#locate-nodes-using-xpath
const evaluator = new XPathEvaluator();
const expression = evaluator.createExpression(xPathSelector);
const locateNodesUsingXpath = (element: HTMLElement) => {
const locateNodesUsingXpath = (element: Node) => {
const xPathResult = expression.evaluate(
element,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE
Expand Down Expand Up @@ -1157,16 +1157,36 @@ export class BrowsingContextImpl {
ignoreCase: boolean,
maxNodeCount: number,
maxDepth: number,
...startNodes: HTMLElement[]
...startNodes: Node[]
) => {
const searchText = ignoreCase
? innerTextSelector.toUpperCase()
: innerTextSelector;
const locateNodesUsingInnerText = (
element: HTMLElement,
const locateNodesUsingInnerText: (
node: Node,
currentMaxDepth: number
) => {
) => HTMLElement[] = (node: Node, currentMaxDepth: number) => {
const returnedNodes: HTMLElement[] = [];
if (
node instanceof DocumentFragment ||
node instanceof Document
) {
const children = [...node.children];
children.forEach((child) =>
// `currentMaxDepth` is not decremented intentionally according to
// https://github.com/w3c/webdriver-bidi/pull/713.
returnedNodes.push(
...locateNodesUsingInnerText(child, currentMaxDepth)
)
);
return returnedNodes;
}

if (!(node instanceof HTMLElement)) {
return [];
}

const element = node;
const nodeInnerText = ignoreCase
? element.innerText?.toUpperCase()
: element.innerText;
Expand All @@ -1191,7 +1211,7 @@ export class BrowsingContextImpl {
} else {
const childNodeMatches =
// Don't search deeper if `maxDepth` is reached.
currentMaxDepth === 0
currentMaxDepth <= 0
? []
: childNodes
.map((child) =>
Expand All @@ -1213,9 +1233,8 @@ export class BrowsingContextImpl {
// TODO: stop search early if `maxNodeCount` is reached.
return returnedNodes;
};
// TODO: add maxDepth.
// TODO: stop search early if `maxNodeCount` is reached.
startNodes = startNodes.length > 0 ? startNodes : [document.body];
startNodes = startNodes.length > 0 ? startNodes : [document];
const returnedNodes = startNodes
.map((startNode) =>
// TODO: stop search early if `maxNodeCount` is reached.
Expand Down
27 changes: 24 additions & 3 deletions tests/browsing_context/test_locate_nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,20 +39,41 @@
}
},
])
@pytest.mark.parametrize('start_node_expression',
[None, 'document', 'document.body'])
@pytest.mark.asyncio
async def test_locate_nodes_locator_found(websocket, context_id, html,
locator):
async def test_locate_nodes_locator_found(websocket, context_id, html, locator,
start_node_expression):
await goto_url(
websocket, context_id,
html(
'<div data-class="one" aria-label="test" role="button">foobarBARbaz</div><div data-class="two" aria-label="test" role="button">foobarBAR<span>baz</span></div>'
))

start_nodes = None
if start_node_expression:
resp = await execute_command(
websocket, {
'method': 'script.evaluate',
'params': {
'expression': start_node_expression,
'target': {
'context': context_id
},
'awaitPromise': False
}
})
start_nodes = [{'sharedId': resp['result']['sharedId']}]

resp = await execute_command(
websocket, {
'method': 'browsingContext.locateNodes',
'params': {
'context': context_id,
'locator': locator
'locator': locator,
**({
'startNodes': start_nodes
} if start_nodes else {})
}
})

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[locator.py]
[test_find_by_inner_text[ignore_case_true_full_match_max_depth_zero\]]
expected: FAIL

[test_find_by_inner_text[ignore_case_false_full_match_max_depth_zero\]]
expected: FAIL

[test_find_by_inner_text[ignore_case_true_partial_match_max_depth_zero\]]
expected: FAIL

[test_find_by_inner_text[ignore_case_false_partial_match_max_depth_zero\]]
expected: FAIL

[test_find_by_inner_text[ignore_case_true_full_match_max_depth_one\]]
expected: FAIL

[test_find_by_inner_text[ignore_case_false_full_match_max_depth_one\]]
expected: FAIL

[test_find_by_inner_text[ignore_case_true_partial_match_max_depth_one\]]
expected: FAIL

[test_find_by_inner_text[ignore_case_false_partial_match_max_depth_one\]]
expected: FAIL

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[locator.py]
[test_find_by_inner_text[ignore_case_true_full_match_max_depth_zero\]]
expected: FAIL

[test_find_by_inner_text[ignore_case_false_full_match_max_depth_zero\]]
expected: FAIL

[test_find_by_inner_text[ignore_case_true_partial_match_max_depth_zero\]]
expected: FAIL

[test_find_by_inner_text[ignore_case_false_partial_match_max_depth_zero\]]
expected: FAIL

[test_find_by_inner_text[ignore_case_true_full_match_max_depth_one\]]
expected: FAIL

[test_find_by_inner_text[ignore_case_false_full_match_max_depth_one\]]
expected: FAIL

[test_find_by_inner_text[ignore_case_true_partial_match_max_depth_one\]]
expected: FAIL

[test_find_by_inner_text[ignore_case_false_partial_match_max_depth_one\]]
expected: FAIL

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[locator.py]
[test_find_by_inner_text[ignore_case_true_full_match_max_depth_zero\]]
expected: FAIL

[test_find_by_inner_text[ignore_case_false_full_match_max_depth_zero\]]
expected: FAIL

[test_find_by_inner_text[ignore_case_true_partial_match_max_depth_zero\]]
expected: FAIL

[test_find_by_inner_text[ignore_case_false_partial_match_max_depth_zero\]]
expected: FAIL

[test_find_by_inner_text[ignore_case_true_full_match_max_depth_one\]]
expected: FAIL

[test_find_by_inner_text[ignore_case_false_full_match_max_depth_one\]]
expected: FAIL

[test_find_by_inner_text[ignore_case_true_partial_match_max_depth_one\]]
expected: FAIL

[test_find_by_inner_text[ignore_case_false_partial_match_max_depth_one\]]
expected: FAIL

This file was deleted.

0 comments on commit ad7318f

Please sign in to comment.