mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
script: Improve webdriver_handler::get_element_in_view_center_point
(#38058)
1. Some rounding was wrongly used which can be a source of inaccuracy. 2. Use `window.InnerWidth` instead of `body.ClientWidth` according to spec. Testing: Many new passing cases. Fixes: Part of #38042. --------- Signed-off-by: Euclid Ye <euclid.ye@huawei.com>
This commit is contained in:
parent
f13311a00e
commit
8877adccf2
8 changed files with 63 additions and 69 deletions
|
@ -2,7 +2,6 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use std::cmp;
|
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::ptr::NonNull;
|
use std::ptr::NonNull;
|
||||||
|
@ -630,38 +629,45 @@ pub(crate) fn handle_get_browsing_context_id(
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://w3c.github.io/webdriver/#dfn-center-point
|
/// <https://w3c.github.io/webdriver/#dfn-center-point>
|
||||||
fn get_element_in_view_center_point(element: &Element, can_gc: CanGc) -> Option<Point2D<i64>> {
|
fn get_element_in_view_center_point(element: &Element, can_gc: CanGc) -> Option<Point2D<i64>> {
|
||||||
element
|
let doc = element.owner_document();
|
||||||
.owner_document()
|
// Step 1: Let rectangle be the first element of the DOMRect sequence
|
||||||
.GetBody()
|
// returned by calling getClientRects() on element.
|
||||||
.map(DomRoot::upcast::<Element>)
|
element.GetClientRects(can_gc).first().map(|rectangle| {
|
||||||
.and_then(|body| {
|
let x = rectangle.X();
|
||||||
// Step 1: Let rectangle be the first element of the DOMRect sequence
|
let y = rectangle.Y();
|
||||||
// returned by calling getClientRects() on element.
|
let width = rectangle.Width();
|
||||||
element.GetClientRects(can_gc).first().map(|rectangle| {
|
let height = rectangle.Height();
|
||||||
let x = rectangle.X().round() as i64;
|
debug!(
|
||||||
let y = rectangle.Y().round() as i64;
|
"get_element_in_view_center_point: Element rectangle at \
|
||||||
let width = rectangle.Width().round() as i64;
|
(x: {x}, y: {y}, width: {width}, height: {height})",
|
||||||
let height = rectangle.Height().round() as i64;
|
);
|
||||||
|
let window = doc.window();
|
||||||
|
// Steps 2. Let left be max(0, min(x coordinate, x coordinate + width dimension)).
|
||||||
|
let left = (x.min(x + width)).max(0.0);
|
||||||
|
// Step 3. Let right be min(innerWidth, max(x coordinate, x coordinate + width dimension)).
|
||||||
|
let right = f64::min(window.InnerWidth() as f64, x.max(x + width));
|
||||||
|
// Step 4. Let top be max(0, min(y coordinate, y coordinate + height dimension)).
|
||||||
|
let top = (y.min(y + height)).max(0.0);
|
||||||
|
// Step 5. Let bottom be
|
||||||
|
// min(innerHeight, max(y coordinate, y coordinate + height dimension)).
|
||||||
|
let bottom = f64::min(window.InnerHeight() as f64, y.max(y + height));
|
||||||
|
debug!(
|
||||||
|
"get_element_in_view_center_point: Computed rectangle is \
|
||||||
|
(left: {left}, right: {right}, top: {top}, bottom: {bottom})",
|
||||||
|
);
|
||||||
|
// Step 6. Let x be floor((left + right) ÷ 2.0).
|
||||||
|
let center_x = ((left + right) / 2.0).floor() as i64;
|
||||||
|
// Step 7. Let y be floor((top + bottom) ÷ 2.0).
|
||||||
|
let center_y = ((top + bottom) / 2.0).floor() as i64;
|
||||||
|
|
||||||
let client_width = body.ClientWidth(can_gc) as i64;
|
debug!(
|
||||||
let client_height = body.ClientHeight(can_gc) as i64;
|
"get_element_in_view_center_point: Element center point at ({center_x}, {center_y})",
|
||||||
|
);
|
||||||
// Steps 2 - 5
|
// Step 8
|
||||||
let left = cmp::max(0, cmp::min(x, x + width));
|
Point2D::new(center_x, center_y)
|
||||||
let right = cmp::min(client_width, cmp::max(x, x + width));
|
})
|
||||||
let top = cmp::max(0, cmp::min(y, y + height));
|
|
||||||
let bottom = cmp::min(client_height, cmp::max(y, y + height));
|
|
||||||
|
|
||||||
// Steps 6 - 7
|
|
||||||
let x = (left + right) / 2;
|
|
||||||
let y = (top + bottom) / 2;
|
|
||||||
|
|
||||||
// Step 8
|
|
||||||
Point2D::new(x, y)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn handle_get_element_in_view_center_point(
|
pub(crate) fn handle_get_element_in_view_center_point(
|
||||||
|
|
|
@ -1875,7 +1875,7 @@ impl Handler {
|
||||||
fn handle_element_click(&mut self, element: &WebElement) -> WebDriverResult<WebDriverResponse> {
|
fn handle_element_click(&mut self, element: &WebElement) -> WebDriverResult<WebDriverResponse> {
|
||||||
let (sender, receiver) = ipc::channel().unwrap();
|
let (sender, receiver) = ipc::channel().unwrap();
|
||||||
|
|
||||||
// Steps 1 - 7
|
// Steps 1 - 7 + Step 8 for <option>
|
||||||
let cmd = WebDriverScriptCommand::ElementClick(element.to_string(), sender);
|
let cmd = WebDriverScriptCommand::ElementClick(element.to_string(), sender);
|
||||||
self.browsing_context_script_command(cmd, VerifyBrowsingContextIsOpen::Yes)?;
|
self.browsing_context_script_command(cmd, VerifyBrowsingContextIsOpen::Yes)?;
|
||||||
|
|
||||||
|
@ -1883,7 +1883,7 @@ impl Handler {
|
||||||
Ok(element_id) => match element_id {
|
Ok(element_id) => match element_id {
|
||||||
Some(element_id) => {
|
Some(element_id) => {
|
||||||
let id = Uuid::new_v4().to_string();
|
let id = Uuid::new_v4().to_string();
|
||||||
|
// Step 8 for elements other than <option>
|
||||||
// Step 8.1
|
// Step 8.1
|
||||||
self.session_mut()?.input_state_table.borrow_mut().insert(
|
self.session_mut()?.input_state_table.borrow_mut().insert(
|
||||||
id.clone(),
|
id.clone(),
|
||||||
|
|
|
@ -40,3 +40,6 @@
|
||||||
|
|
||||||
[test_add_cookie_with_invalid_samesite_flag]
|
[test_add_cookie_with_invalid_samesite_flag]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
[test_add_cookie_with_expiry_in_the_future]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -1,30 +1,3 @@
|
||||||
[scroll_into_view.py]
|
[scroll_into_view.py]
|
||||||
[test_scroll_into_view]
|
[test_scroll_into_view]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[test_partially_visible_does_not_scroll[9\]]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_partially_visible_does_not_scroll[8\]]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_partially_visible_does_not_scroll[7\]]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_partially_visible_does_not_scroll[6\]]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_partially_visible_does_not_scroll[5\]]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_partially_visible_does_not_scroll[4\]]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_partially_visible_does_not_scroll[3\]]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_partially_visible_does_not_scroll[2\]]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_partially_visible_does_not_scroll[1\]]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -10,3 +10,6 @@
|
||||||
|
|
||||||
[test_seen_nodes[https coop\]]
|
[test_seen_nodes[https coop\]]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
[test_removed_iframe]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -4,6 +4,3 @@
|
||||||
|
|
||||||
[test_control_click[\\ue051-ctrlKey\]]
|
[test_control_click[\\ue051-ctrlKey\]]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[test_release_control_click]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,9 +1,3 @@
|
||||||
[pointer_origin.py]
|
[pointer_origin.py]
|
||||||
[test_element_center_point]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[test_element_center_point_with_offset]
|
[test_element_center_point_with_offset]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[test_element_larger_than_viewport]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -43,3 +43,21 @@
|
||||||
|
|
||||||
[test_no_change[rect19\]]
|
[test_no_change[rect19\]]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
[test_partial_input[rect2\]]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[test_partial_input[rect3\]]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[test_partial_input[rect4\]]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[test_partial_input[rect5\]]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[test_partial_input[rect6\]]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[test_partial_input[rect7\]]
|
||||||
|
expected: FAIL
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue