From e26532e19b11d55d27bead32256f09ce0bcec7c7 Mon Sep 17 00:00:00 2001 From: Euclid Ye Date: Wed, 18 Jun 2025 14:39:55 +0800 Subject: [PATCH] `webdriver_server`: Implement find element(s) from element according to spec (#37521) Report `InvalidArgument` and `NoSuchElement` properly for [Find Element from Element](https://w3c.github.io/webdriver/#find-element-from-element) + [Find Elements from Element](https://w3c.github.io/webdriver/#find-elements-from-element) Testing: `./mach test-wpt -r .\tests\wpt\tests\webdriver\tests\classic\element_click .\tests\wpt\tests\webdriver\tests\classic\find_* --product servodriver` --------- Signed-off-by: Euclid Ye --- components/webdriver_server/lib.rs | 26 +++++++++++++------ .../classic/element_click/navigate.py.ini | 10 ------- .../find_element_from_element/find.py.ini | 9 ------- .../find_elements_from_element/find.py.ini | 12 --------- 4 files changed, 18 insertions(+), 39 deletions(-) diff --git a/components/webdriver_server/lib.rs b/components/webdriver_server/lib.rs index 242c89ccb2e..46e3904f2ce 100644 --- a/components/webdriver_server/lib.rs +++ b/components/webdriver_server/lib.rs @@ -1167,12 +1167,16 @@ impl Handler { } } - // https://w3c.github.io/webdriver/#find-element-from-element + /// fn handle_find_element_element( &self, element: &WebElement, parameters: &LocatorParameters, ) -> WebDriverResult { + // Step 4. If selector is undefined, return error with error code invalid argument. + if parameters.value.is_empty() { + return Err(WebDriverError::new(ErrorStatus::InvalidArgument, "")); + } let (sender, receiver) = ipc::channel().unwrap(); match parameters.using { @@ -1208,24 +1212,30 @@ impl Handler { )); }, } - + // Step 9. If result is empty, return error with error code no such element. + // Otherwise, return the first element of result. match wait_for_script_response(receiver)? { - Ok(value) => { - let value_resp = serde_json::to_value( - value.map(|x| serde_json::to_value(WebElement(x)).unwrap()), - )?; - Ok(WebDriverResponse::Generic(ValueResponse(value_resp))) + Ok(value) => match value { + Some(value) => { + let value_resp = serde_json::to_value(WebElement(value))?; + Ok(WebDriverResponse::Generic(ValueResponse(value_resp))) + }, + None => Err(WebDriverError::new(ErrorStatus::NoSuchElement, "")), }, Err(error) => Err(WebDriverError::new(error, "")), } } - // https://w3c.github.io/webdriver/#find-elements-from-element + /// fn handle_find_elements_from_element( &self, element: &WebElement, parameters: &LocatorParameters, ) -> WebDriverResult { + // Step 4. If selector is undefined, return error with error code invalid argument. + if parameters.value.is_empty() { + return Err(WebDriverError::new(ErrorStatus::InvalidArgument, "")); + } let (sender, receiver) = ipc::channel().unwrap(); match parameters.using { diff --git a/tests/wpt/meta/webdriver/tests/classic/element_click/navigate.py.ini b/tests/wpt/meta/webdriver/tests/classic/element_click/navigate.py.ini index 4811bba2d43..6000751c1f1 100644 --- a/tests/wpt/meta/webdriver/tests/classic/element_click/navigate.py.ini +++ b/tests/wpt/meta/webdriver/tests/classic/element_click/navigate.py.ini @@ -1,5 +1,4 @@ [navigate.py] - expected: TIMEOUT [test_numbers_link] expected: FAIL @@ -12,21 +11,12 @@ [test_link_hash] expected: FAIL - [test_link_from_toplevel_context_with_target[\]] - expected: FAIL - [test_link_from_toplevel_context_with_target[_blank\]] expected: FAIL [test_link_from_toplevel_context_with_target[_parent\]] expected: FAIL - [test_link_from_toplevel_context_with_target[_self\]] - expected: FAIL - - [test_link_from_toplevel_context_with_target[_top\]] - expected: FAIL - [test_link_from_nested_context_with_target[\]] expected: FAIL diff --git a/tests/wpt/meta/webdriver/tests/classic/find_element_from_element/find.py.ini b/tests/wpt/meta/webdriver/tests/classic/find_element_from_element/find.py.ini index 85a7daf2244..7a6fdf5a5ff 100644 --- a/tests/wpt/meta/webdriver/tests/classic/find_element_from_element/find.py.ini +++ b/tests/wpt/meta/webdriver/tests/classic/find_element_from_element/find.py.ini @@ -5,15 +5,6 @@ [test_no_such_element_with_shadow_root] expected: FAIL - [test_no_such_element_with_unknown_selector[not-existent\]] - expected: FAIL - - [test_no_such_element_with_unknown_selector[existent-other-frame\]] - expected: FAIL - - [test_no_such_element_with_unknown_selector[existent-inside-shadow-root\]] - expected: FAIL - [test_no_such_element_with_startnode_from_other_frame] expected: FAIL diff --git a/tests/wpt/meta/webdriver/tests/classic/find_elements_from_element/find.py.ini b/tests/wpt/meta/webdriver/tests/classic/find_elements_from_element/find.py.ini index 47ac0c0b589..3255f206fb9 100644 --- a/tests/wpt/meta/webdriver/tests/classic/find_elements_from_element/find.py.ini +++ b/tests/wpt/meta/webdriver/tests/classic/find_elements_from_element/find.py.ini @@ -11,18 +11,6 @@ [test_find_elements[xpath-//a\]] expected: FAIL - [test_find_elements_link_text[link
text
-link\\ntext\]] - expected: FAIL - - [test_find_elements_link_text[link text-LINK TEXT\]] - expected: FAIL - - [test_find_elements_partial_link_text[partial link
text
-k\\nt\]] - expected: FAIL - - [test_find_elements_partial_link_text[partial link text-LINK\]] - expected: FAIL - [test_xhtml_namespace[xpath-//*[name()='a'\]\]] expected: FAIL