From 64a8fcc4effa0ec41136940966f2f1c585a43898 Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Sun, 3 Nov 2024 17:58:32 -0500 Subject: [PATCH] LibWeb: Begin implementing a Selenium-like method to get element text Unfortunately, there isn't an exact spec method to get the rendered text of an element, including its shadow DOM. The WebDriver spec requires just doing exactly what Selenium does. This patch does not implement this, but is a step in the right direction as we will now handle text transforms. --- .../Libraries/LibWeb/WebDriver/ElementReference.cpp | 12 ++++++++++++ .../Libraries/LibWeb/WebDriver/ElementReference.h | 2 ++ Userland/Services/WebContent/WebDriverConnection.cpp | 7 ++++--- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/Userland/Libraries/LibWeb/WebDriver/ElementReference.cpp b/Userland/Libraries/LibWeb/WebDriver/ElementReference.cpp index c8dec6ef5a2..bd3ae366cca 100644 --- a/Userland/Libraries/LibWeb/WebDriver/ElementReference.cpp +++ b/Userland/Libraries/LibWeb/WebDriver/ElementReference.cpp @@ -516,6 +516,18 @@ bool is_shadow_root_detached(Web::DOM::ShadowRoot const& shadow_root) return !shadow_root.document().is_active() || !shadow_root.host() || is_element_stale(*shadow_root.host()); } +// https://w3c.github.io/webdriver/#dfn-bot-dom-getvisibletext +String element_rendered_text(DOM::Node& node) +{ + // FIXME: The spec does not define how to get the element's rendered text, other than to do exactly as Selenium does. + // This implementation is not sufficient, as we must also at least consider the shadow DOM. + if (!is(node)) + return node.text_content().value_or(String {}); + + auto& element = static_cast(node); + return element.inner_text(); +} + // https://w3c.github.io/webdriver/#dfn-center-point CSSPixelPoint in_view_center_point(DOM::Element const& element, CSSPixelRect viewport) { diff --git a/Userland/Libraries/LibWeb/WebDriver/ElementReference.h b/Userland/Libraries/LibWeb/WebDriver/ElementReference.h index b9d3e0b86a6..aeca6515b7a 100644 --- a/Userland/Libraries/LibWeb/WebDriver/ElementReference.h +++ b/Userland/Libraries/LibWeb/WebDriver/ElementReference.h @@ -55,6 +55,8 @@ ErrorOr, WebDriver::Error> deserialize_sh ErrorOr, Web::WebDriver::Error> get_known_shadow_root(HTML::BrowsingContext const&, StringView reference); bool is_shadow_root_detached(Web::DOM::ShadowRoot const&); +String element_rendered_text(DOM::Node&); + CSSPixelPoint in_view_center_point(DOM::Element const& element, CSSPixelRect viewport); } diff --git a/Userland/Services/WebContent/WebDriverConnection.cpp b/Userland/Services/WebContent/WebDriverConnection.cpp index 95bffb8b96b..c8142aa79b4 100644 --- a/Userland/Services/WebContent/WebDriverConnection.cpp +++ b/Userland/Services/WebContent/WebDriverConnection.cpp @@ -1322,11 +1322,12 @@ Messages::WebDriverClient::GetElementTextResponse WebDriverConnection::get_eleme // 3. Let element be the result of trying to get a known connected element with url variable element id. auto element = WEBDRIVER_TRY(Web::WebDriver::get_known_element(current_browsing_context(), element_id)); - // 4. Let rendered text be the result of performing implementation-specific steps whose result is exactly the same as the result of a Function.[[Call]](null, element) with bot.dom.getVisibleText as the this value. - auto rendered_text = element->text_content(); + // 4. Let rendered text be the result of performing implementation-specific steps whose result is exactly the + // same as the result of a Function.[[Call]](null, element) with bot.dom.getVisibleText as the this value. + auto rendered_text = Web::WebDriver::element_rendered_text(element); // 5. Return success with data rendered text. - async_driver_execution_complete({ rendered_text.value_or(String {}).to_byte_string() }); + async_driver_execution_complete({ rendered_text.to_byte_string() }); }); return JsonValue {};