mirror of
https://github.com/servo/servo.git
synced 2025-08-06 22:15:33 +01:00
Auto merge of #23443 - georgeroman:start_enabling_wdspec_tests, r=jdm
Start enabling automated webdriver tests <!-- Please describe your changes on the following line: --> --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors <!-- Either: --> - [X] There are tests for these changes <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/23443) <!-- Reviewable:end -->
This commit is contained in:
commit
237ef8da34
5 changed files with 256 additions and 26 deletions
89
components/webdriver_server/capabilities.rs
Normal file
89
components/webdriver_server/capabilities.rs
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* 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/. */
|
||||||
|
|
||||||
|
use serde_json::{Map, Value};
|
||||||
|
use webdriver::capabilities::{BrowserCapabilities, Capabilities};
|
||||||
|
use webdriver::error::WebDriverResult;
|
||||||
|
|
||||||
|
pub struct ServoCapabilities {
|
||||||
|
pub browser_name: String,
|
||||||
|
pub browser_version: String,
|
||||||
|
pub platform_name: Option<String>,
|
||||||
|
pub accept_insecure_certs: bool,
|
||||||
|
pub set_window_rect: bool,
|
||||||
|
pub strict_file_interactability: bool,
|
||||||
|
pub accept_proxy: bool,
|
||||||
|
pub accept_custom: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ServoCapabilities {
|
||||||
|
pub fn new() -> ServoCapabilities {
|
||||||
|
ServoCapabilities {
|
||||||
|
browser_name: "servo".to_string(),
|
||||||
|
browser_version: "0.0.1".to_string(),
|
||||||
|
platform_name: get_platform_name(),
|
||||||
|
accept_insecure_certs: false,
|
||||||
|
set_window_rect: true,
|
||||||
|
strict_file_interactability: false,
|
||||||
|
accept_proxy: false,
|
||||||
|
accept_custom: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BrowserCapabilities for ServoCapabilities {
|
||||||
|
fn init(&mut self, _: &Capabilities) {}
|
||||||
|
|
||||||
|
fn browser_name(&mut self, _: &Capabilities) -> WebDriverResult<Option<String>> {
|
||||||
|
Ok(Some(self.browser_name.clone()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn browser_version(&mut self, _: &Capabilities) -> WebDriverResult<Option<String>> {
|
||||||
|
Ok(Some(self.browser_version.clone()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compare_browser_version(&mut self, _: &str, _: &str) -> WebDriverResult<bool> {
|
||||||
|
Ok(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn platform_name(&mut self, _: &Capabilities) -> WebDriverResult<Option<String>> {
|
||||||
|
Ok(self.platform_name.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn accept_insecure_certs(&mut self, _: &Capabilities) -> WebDriverResult<bool> {
|
||||||
|
Ok(self.accept_insecure_certs)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_window_rect(&mut self, _: &Capabilities) -> WebDriverResult<bool> {
|
||||||
|
Ok(self.set_window_rect)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn strict_file_interactability(&mut self, _: &Capabilities) -> WebDriverResult<bool> {
|
||||||
|
Ok(self.strict_file_interactability)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn accept_proxy(&mut self, _: &Map<String, Value>, _: &Capabilities) -> WebDriverResult<bool> {
|
||||||
|
Ok(self.accept_proxy)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn accept_custom(&mut self, _: &str, _: &Value, _: &Capabilities) -> WebDriverResult<bool> {
|
||||||
|
Ok(self.accept_custom)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate_custom(&self, _: &str, _: &Value) -> WebDriverResult<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_platform_name() -> Option<String> {
|
||||||
|
if cfg!(target_os = "windows") {
|
||||||
|
Some("windows".to_string())
|
||||||
|
} else if cfg!(target_os = "linux") {
|
||||||
|
Some("linux".to_string())
|
||||||
|
} else if cfg!(target_os = "macos") {
|
||||||
|
Some("mac".to_string())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,8 +10,13 @@
|
||||||
extern crate log;
|
extern crate log;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate serde_json;
|
||||||
|
|
||||||
|
mod capabilities;
|
||||||
|
|
||||||
use base64;
|
use base64;
|
||||||
|
use capabilities::ServoCapabilities;
|
||||||
use crossbeam_channel::Sender;
|
use crossbeam_channel::Sender;
|
||||||
use euclid::TypedSize2D;
|
use euclid::TypedSize2D;
|
||||||
use hyper::Method;
|
use hyper::Method;
|
||||||
|
@ -28,7 +33,7 @@ use script_traits::webdriver_msg::{
|
||||||
use script_traits::{ConstellationMsg, LoadData, WebDriverCommandMsg};
|
use script_traits::{ConstellationMsg, LoadData, WebDriverCommandMsg};
|
||||||
use serde::de::{Deserialize, Deserializer, MapAccess, Visitor};
|
use serde::de::{Deserialize, Deserializer, MapAccess, Visitor};
|
||||||
use serde::ser::{Serialize, Serializer};
|
use serde::ser::{Serialize, Serializer};
|
||||||
use serde_json::{self, Value};
|
use serde_json::{json, Value};
|
||||||
use servo_config::{prefs, prefs::PrefValue};
|
use servo_config::{prefs, prefs::PrefValue};
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
|
@ -38,10 +43,13 @@ use std::net::{SocketAddr, SocketAddrV4};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
use webdriver::capabilities::{Capabilities, CapabilitiesMatching};
|
||||||
use webdriver::command::{
|
use webdriver::command::{
|
||||||
AddCookieParameters, GetParameters, JavascriptCommandParameters, LocatorParameters,
|
AddCookieParameters, GetParameters, JavascriptCommandParameters, LocatorParameters,
|
||||||
};
|
};
|
||||||
use webdriver::command::{SendKeysParameters, SwitchToFrameParameters, TimeoutsParameters};
|
use webdriver::command::{
|
||||||
|
NewSessionParameters, SendKeysParameters, SwitchToFrameParameters, TimeoutsParameters,
|
||||||
|
};
|
||||||
use webdriver::command::{
|
use webdriver::command::{
|
||||||
WebDriverCommand, WebDriverExtensionCommand, WebDriverMessage, WindowRectParameters,
|
WebDriverCommand, WebDriverExtensionCommand, WebDriverMessage, WindowRectParameters,
|
||||||
};
|
};
|
||||||
|
@ -117,6 +125,11 @@ struct WebDriverSession {
|
||||||
/// Time to wait for the element location strategy when retrieving elements, and when
|
/// Time to wait for the element location strategy when retrieving elements, and when
|
||||||
/// waiting for an element to become interactable.
|
/// waiting for an element to become interactable.
|
||||||
implicit_wait_timeout: u64,
|
implicit_wait_timeout: u64,
|
||||||
|
|
||||||
|
page_loading_strategy: String,
|
||||||
|
secure_tls: bool,
|
||||||
|
strict_file_interactability: bool,
|
||||||
|
unhandled_prompt_behavior: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WebDriverSession {
|
impl WebDriverSession {
|
||||||
|
@ -132,6 +145,11 @@ impl WebDriverSession {
|
||||||
script_timeout: Some(30_000),
|
script_timeout: Some(30_000),
|
||||||
load_timeout: 300_000,
|
load_timeout: 300_000,
|
||||||
implicit_wait_timeout: 0,
|
implicit_wait_timeout: 0,
|
||||||
|
|
||||||
|
page_loading_strategy: "normal".to_string(),
|
||||||
|
secure_tls: true,
|
||||||
|
strict_file_interactability: false,
|
||||||
|
unhandled_prompt_behavior: "dismiss and notify".to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -381,26 +399,137 @@ impl Handler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_new_session(&mut self) -> WebDriverResult<WebDriverResponse> {
|
fn handle_new_session(
|
||||||
debug!("new session");
|
&mut self,
|
||||||
|
parameters: &NewSessionParameters,
|
||||||
|
) -> WebDriverResult<WebDriverResponse> {
|
||||||
|
let mut servo_capabilities = ServoCapabilities::new();
|
||||||
|
let processed_capabilities = match parameters {
|
||||||
|
NewSessionParameters::Legacy(_) => Some(Capabilities::new()),
|
||||||
|
NewSessionParameters::Spec(capabilities) => {
|
||||||
|
capabilities.match_browser(&mut servo_capabilities)?
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
if self.session.is_none() {
|
if self.session.is_none() {
|
||||||
let top_level_browsing_context_id = self.focus_top_level_browsing_context_id()?;
|
match processed_capabilities {
|
||||||
let browsing_context_id = BrowsingContextId::from(top_level_browsing_context_id);
|
Some(mut processed) => {
|
||||||
let session = WebDriverSession::new(browsing_context_id, top_level_browsing_context_id);
|
let top_level_browsing_context_id =
|
||||||
let mut capabilities = serde_json::Map::new();
|
self.focus_top_level_browsing_context_id()?;
|
||||||
capabilities.insert("browserName".to_owned(), serde_json::to_value("servo")?);
|
let browsing_context_id =
|
||||||
capabilities.insert("browserVersion".to_owned(), serde_json::to_value("0.0.1")?);
|
BrowsingContextId::from(top_level_browsing_context_id);
|
||||||
capabilities.insert(
|
let mut session =
|
||||||
"acceptInsecureCerts".to_owned(),
|
WebDriverSession::new(browsing_context_id, top_level_browsing_context_id);
|
||||||
serde_json::to_value(false)?,
|
|
||||||
|
match processed.get("pageLoadStrategy") {
|
||||||
|
Some(strategy) => session.page_loading_strategy = strategy.to_string(),
|
||||||
|
None => {
|
||||||
|
processed.insert(
|
||||||
|
"pageLoadStrategy".to_string(),
|
||||||
|
json!(session.page_loading_strategy),
|
||||||
);
|
);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
match processed.get("strictFileInteractability") {
|
||||||
|
Some(strict_file_interactability) => {
|
||||||
|
session.strict_file_interactability =
|
||||||
|
strict_file_interactability.as_bool().unwrap()
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
processed.insert(
|
||||||
|
"strictFileInteractability".to_string(),
|
||||||
|
json!(session.strict_file_interactability),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
match processed.get("proxy") {
|
||||||
|
Some(_) => (),
|
||||||
|
None => {
|
||||||
|
processed.insert("proxy".to_string(), json!({}));
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(timeouts) = processed.get("timeouts") {
|
||||||
|
if let Some(script_timeout_value) = timeouts.get("script") {
|
||||||
|
session.script_timeout = script_timeout_value.as_u64();
|
||||||
|
}
|
||||||
|
if let Some(load_timeout_value) = timeouts.get("pageLoad") {
|
||||||
|
if let Some(load_timeout) = load_timeout_value.as_u64() {
|
||||||
|
session.load_timeout = load_timeout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(implicit_wait_timeout_value) = timeouts.get("implicit") {
|
||||||
|
if let Some(implicit_wait_timeout) =
|
||||||
|
implicit_wait_timeout_value.as_u64()
|
||||||
|
{
|
||||||
|
session.implicit_wait_timeout = implicit_wait_timeout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
processed.insert(
|
||||||
|
"timeouts".to_string(),
|
||||||
|
json!({
|
||||||
|
"script": session.script_timeout,
|
||||||
|
"pageLoad": session.load_timeout,
|
||||||
|
"implicit": session.implicit_wait_timeout,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
match processed.get("acceptInsecureCerts") {
|
||||||
|
Some(accept_insecure_certs) => {
|
||||||
|
session.secure_tls = !accept_insecure_certs.as_bool().unwrap()
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
processed.insert(
|
||||||
|
"acceptInsecureCerts".to_string(),
|
||||||
|
json!(servo_capabilities.accept_insecure_certs),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
match processed.get("unhandledPromptBehavior") {
|
||||||
|
Some(unhandled_prompt_behavior) => {
|
||||||
|
session.unhandled_prompt_behavior =
|
||||||
|
unhandled_prompt_behavior.to_string()
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
processed.insert(
|
||||||
|
"unhandledPromptBehavior".to_string(),
|
||||||
|
json!(session.unhandled_prompt_behavior),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
processed.insert(
|
||||||
|
"browserName".to_string(),
|
||||||
|
json!(servo_capabilities.browser_name),
|
||||||
|
);
|
||||||
|
processed.insert(
|
||||||
|
"browserVersion".to_string(),
|
||||||
|
json!(servo_capabilities.browser_version),
|
||||||
|
);
|
||||||
|
processed.insert(
|
||||||
|
"platformName".to_string(),
|
||||||
|
json!(servo_capabilities
|
||||||
|
.platform_name
|
||||||
|
.unwrap_or("unknown".to_string())),
|
||||||
|
);
|
||||||
|
processed.insert(
|
||||||
|
"setWindowRect".to_string(),
|
||||||
|
json!(servo_capabilities.set_window_rect),
|
||||||
|
);
|
||||||
|
|
||||||
let response =
|
let response =
|
||||||
NewSessionResponse::new(session.id.to_string(), Value::Object(capabilities));
|
NewSessionResponse::new(session.id.to_string(), Value::Object(processed));
|
||||||
debug!("new session created {}.", session.id);
|
|
||||||
self.session = Some(session);
|
self.session = Some(session);
|
||||||
|
|
||||||
Ok(WebDriverResponse::NewSession(response))
|
Ok(WebDriverResponse::NewSession(response))
|
||||||
|
},
|
||||||
|
None => Ok(WebDriverResponse::Void),
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
debug!("new session failed.");
|
|
||||||
Err(WebDriverError::new(
|
Err(WebDriverError::new(
|
||||||
ErrorStatus::UnknownError,
|
ErrorStatus::UnknownError,
|
||||||
"Session already created",
|
"Session already created",
|
||||||
|
@ -1287,7 +1416,7 @@ impl WebDriverHandler<ServoExtensionRoute> for Handler {
|
||||||
}
|
}
|
||||||
|
|
||||||
match msg.command {
|
match msg.command {
|
||||||
WebDriverCommand::NewSession(_) => self.handle_new_session(),
|
WebDriverCommand::NewSession(ref parameters) => self.handle_new_session(parameters),
|
||||||
WebDriverCommand::DeleteSession => self.handle_delete_session(),
|
WebDriverCommand::DeleteSession => self.handle_delete_session(),
|
||||||
WebDriverCommand::AddCookie(ref parameters) => self.handle_add_cookie(parameters),
|
WebDriverCommand::AddCookie(ref parameters) => self.handle_add_cookie(parameters),
|
||||||
WebDriverCommand::Get(ref parameters) => self.handle_get(parameters),
|
WebDriverCommand::Get(ref parameters) => self.handle_get(parameters),
|
||||||
|
@ -1350,11 +1479,6 @@ impl WebDriverHandler<ServoExtensionRoute> for Handler {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn delete_session(&mut self, _session: &Option<Session>) {
|
fn delete_session(&mut self, _session: &Option<Session>) {
|
||||||
// Servo doesn't support multiple sessions, so we exit on session deletion
|
|
||||||
let _ = self
|
|
||||||
.constellation_chan
|
|
||||||
.send(ConstellationMsg::Exit)
|
|
||||||
.unwrap();
|
|
||||||
self.session = None;
|
self.session = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,6 +125,12 @@ skip: true
|
||||||
skip: false
|
skip: false
|
||||||
[WebCryptoAPI]
|
[WebCryptoAPI]
|
||||||
skip: false
|
skip: false
|
||||||
|
[webdriver]
|
||||||
|
skip: true
|
||||||
|
[tests]
|
||||||
|
skip: true
|
||||||
|
[new_session]
|
||||||
|
skip: false
|
||||||
[webgl]
|
[webgl]
|
||||||
skip: false
|
skip: false
|
||||||
[webvr]
|
[webvr]
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
[default_values.py]
|
||||||
|
[test_no_capabilites]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[test_desired]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
[invalid_capabilities.py]
|
||||||
|
[test_invalid_always_match[None\]]
|
||||||
|
expected: FAIL
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue