diff --git a/Userland/Services/WebContent/WebDriverClient.ipc b/Userland/Services/WebContent/WebDriverClient.ipc index 68fcd0043b..8838beed36 100644 --- a/Userland/Services/WebContent/WebDriverClient.ipc +++ b/Userland/Services/WebContent/WebDriverClient.ipc @@ -10,4 +10,5 @@ endpoint WebDriverClient { maximize_window() => (Web::WebDriver::Response response) minimize_window() => (Web::WebDriver::Response response) find_element(JsonValue payload) => (Web::WebDriver::Response response) + find_elements(JsonValue payload) => (Web::WebDriver::Response response) } diff --git a/Userland/Services/WebContent/WebDriverConnection.cpp b/Userland/Services/WebContent/WebDriverConnection.cpp index 57ab7f2f86..ffe3e5266a 100644 --- a/Userland/Services/WebContent/WebDriverConnection.cpp +++ b/Userland/Services/WebContent/WebDriverConnection.cpp @@ -343,6 +343,38 @@ Messages::WebDriverClient::FindElementResponse WebDriverConnection::find_element return make_success_response(result.at(0)); } +// 12.3.3 Find Elements, https://w3c.github.io/webdriver/#dfn-find-elements +Messages::WebDriverClient::FindElementsResponse WebDriverConnection::find_elements(JsonValue const& payload) +{ + // 1. Let location strategy be the result of getting a property called "using". + auto location_strategy_string = TRY(get_property(payload, "using"sv)); + auto location_strategy = Web::WebDriver::location_strategy_from_string(location_strategy_string); + + // 2. If location strategy is not present as a keyword in the table of location strategies, return error with error code invalid argument. + if (!location_strategy.has_value()) + return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, String::formatted("Location strategy '{}' is invalid", location_strategy_string)); + + // 3. Let selector be the result of getting a property called "value". + // 4. If selector is undefined, return error with error code invalid argument. + auto selector = TRY(get_property(payload, "value"sv)); + + // 5. If the current browsing context is no longer open, return error with error code no such window. + TRY(ensure_open_top_level_browsing_context()); + + // FIXME: 6. Handle any user prompts and return its value if it is an error. + + // 7. Let start node be the current browsing context’s document element. + auto* start_node = m_page_host.page().top_level_browsing_context().active_document(); + + // 8. If start node is null, return error with error code no such element. + if (!start_node) + return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::NoSuchElement, "document element does not exist"sv); + + // 9. Return the result of trying to Find with start node, location strategy, and selector. + auto result = TRY(find(*start_node, *location_strategy, selector)); + return make_success_response(move(result)); +} + // https://w3c.github.io/webdriver/#dfn-no-longer-open ErrorOr WebDriverConnection::ensure_open_top_level_browsing_context() { diff --git a/Userland/Services/WebContent/WebDriverConnection.h b/Userland/Services/WebContent/WebDriverConnection.h index 3475c73d42..889b0beacd 100644 --- a/Userland/Services/WebContent/WebDriverConnection.h +++ b/Userland/Services/WebContent/WebDriverConnection.h @@ -40,6 +40,7 @@ private: virtual Messages::WebDriverClient::MaximizeWindowResponse maximize_window() override; virtual Messages::WebDriverClient::MinimizeWindowResponse minimize_window() override; virtual Messages::WebDriverClient::FindElementResponse find_element(JsonValue const& payload) override; + virtual Messages::WebDriverClient::FindElementsResponse find_elements(JsonValue const& payload) override; ErrorOr ensure_open_top_level_browsing_context(); void restore_the_window(); diff --git a/Userland/Services/WebDriver/Client.cpp b/Userland/Services/WebDriver/Client.cpp index 5843173b36..ede08154c6 100644 --- a/Userland/Services/WebDriver/Client.cpp +++ b/Userland/Services/WebDriver/Client.cpp @@ -627,8 +627,7 @@ Web::WebDriver::Response Client::handle_find_elements(Vector const& { dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session//elements"); auto* session = TRY(find_session_with_id(parameters[0])); - auto result = TRY(session->find_elements(payload)); - return make_json_value(result); + return session->web_content_connection().find_elements(payload); } // 12.3.4 Find Element From Element, https://w3c.github.io/webdriver/#dfn-find-element-from-element diff --git a/Userland/Services/WebDriver/Session.cpp b/Userland/Services/WebDriver/Session.cpp index 64b5696bcc..aa79b3edd5 100644 --- a/Userland/Services/WebDriver/Session.cpp +++ b/Userland/Services/WebDriver/Session.cpp @@ -447,56 +447,6 @@ ErrorOr, Web::WebDriver::Error> Session::locator_s return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::UnsupportedOperation, "Not implemented: locator strategy XPath"); } -// 12.3.3 Find Elements, https://w3c.github.io/webdriver/#dfn-find-elements -Web::WebDriver::Response Session::find_elements(JsonValue const& payload) -{ - if (!payload.is_object()) - return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, "Payload is not a JSON object"); - - auto const& properties = payload.as_object(); - // 1. Let location strategy be the result of getting a property called "using". - if (!properties.has("using"sv)) - return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, "No property called 'using' present"); - auto const& maybe_location_strategy = properties.get("using"sv); - if (!maybe_location_strategy.is_string()) - return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, "Property 'using' is not a String"); - - auto location_strategy = maybe_location_strategy.to_string(); - - // 2. If location strategy is not present as a keyword in the table of location strategies, return error with error code invalid argument. - if (!s_locator_strategies.first_matching([&](LocatorStrategy const& match) { return match.name == location_strategy; }).has_value()) - return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, "No valid location strategy"); - - // 3. Let selector be the result of getting a property called "value". - // 4. If selector is undefined, return error with error code invalid argument. - if (!properties.has("value"sv)) - return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, "No property called 'value' present"); - auto const& maybe_selector = properties.get("value"sv); - if (!maybe_selector.is_string()) - return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, "Property 'value' is not a String"); - - auto selector = maybe_selector.to_string(); - - // 5. If the current browsing context is no longer open, return error with error code no such window. - TRY(check_for_open_top_level_browsing_context_or_return_error()); - - // FIXME: 6. Handle any user prompts and return its value if it is an error. - - // 7. Let start node be the current browsing context’s document element. - auto maybe_start_node_id = m_browser_connection->get_document_element(); - - // 8. If start node is null, return error with error code no such element. - if (!maybe_start_node_id.has_value()) - return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::NoSuchElement, "document element does not exist"); - - auto start_node_id = maybe_start_node_id.release_value(); - LocalElement start_node = { start_node_id }; - - // 9. Return the result of trying to Find with start node, location strategy, and selector. - auto result = TRY(find(start_node, location_strategy, selector)); - return JsonValue(result); -} - // 12.3.4 Find Element From Element, https://w3c.github.io/webdriver/#dfn-find-element-from-element Web::WebDriver::Response Session::find_element_from_element(JsonValue const& payload, StringView parameter_element_id) { diff --git a/Userland/Services/WebDriver/Session.h b/Userland/Services/WebDriver/Session.h index 05377f5b7f..735404b0cf 100644 --- a/Userland/Services/WebDriver/Session.h +++ b/Userland/Services/WebDriver/Session.h @@ -58,7 +58,6 @@ public: Web::WebDriver::Response get_window_handle(); ErrorOr> close_window(); Web::WebDriver::Response get_window_handles() const; - Web::WebDriver::Response find_elements(JsonValue const& payload); Web::WebDriver::Response find_element_from_element(JsonValue const& payload, StringView parameter_element_id); Web::WebDriver::Response find_elements_from_element(JsonValue const& payload, StringView parameter_element_id); Web::WebDriver::Response is_element_selected(StringView element_id);