mod common;
use common::{Response, execute, skip_if_no_chrome, spawn};
use earl_protocol_browser::PreparedBrowserCommand;
use earl_protocol_browser::schema::BrowserStep;
use std::collections::HashMap;
#[tokio::test]
async fn local_storage_set_and_get_round_trip() {
if skip_if_no_chrome() {
return;
}
let _guard = common::chrome_lock().await;
let mut routes = HashMap::new();
routes.insert(
"GET /".to_string(),
Response::html("<html><body>hello</body></html>"),
);
let server = spawn(routes).await;
let data = PreparedBrowserCommand {
session_id: None,
headless: true,
timeout_ms: 30_000,
on_failure_screenshot: false,
steps: vec![
BrowserStep::Navigate {
url: server.url("/"),
expected_status: None,
timeout_ms: None,
optional: false,
},
BrowserStep::LocalStorageSet {
key: "theme".to_string(),
value: "dark".to_string(),
optional: false,
},
BrowserStep::LocalStorageGet {
key: "theme".to_string(),
optional: false,
},
],
};
let result = execute(data).await.expect("execute should succeed");
assert_eq!(
result["value"].as_str(),
Some("dark"),
"expected localStorage['theme'] == 'dark'; got: {result}"
);
}
#[tokio::test]
async fn local_storage_delete_removes_key() {
if skip_if_no_chrome() {
return;
}
let _guard = common::chrome_lock().await;
let mut routes = HashMap::new();
routes.insert(
"GET /".to_string(),
Response::html("<html><body>hello</body></html>"),
);
let server = spawn(routes).await;
let data = PreparedBrowserCommand {
session_id: None,
headless: true,
timeout_ms: 30_000,
on_failure_screenshot: false,
steps: vec![
BrowserStep::Navigate {
url: server.url("/"),
expected_status: None,
timeout_ms: None,
optional: false,
},
BrowserStep::LocalStorageSet {
key: "x".to_string(),
value: "1".to_string(),
optional: false,
},
BrowserStep::LocalStorageDelete {
key: "x".to_string(),
optional: false,
},
BrowserStep::Evaluate {
function: "() => localStorage.length".to_string(),
r#ref: None,
timeout_ms: None,
optional: false,
},
],
};
let result = execute(data).await.expect("execute should succeed");
assert_eq!(
result["value"],
serde_json::json!(0),
"expected localStorage.length == 0 after delete; got: {result}"
);
}
#[tokio::test]
async fn local_storage_clear_wipes_all_keys() {
if skip_if_no_chrome() {
return;
}
let _guard = common::chrome_lock().await;
let mut routes = HashMap::new();
routes.insert(
"GET /".to_string(),
Response::html("<html><body>hello</body></html>"),
);
let server = spawn(routes).await;
let data = PreparedBrowserCommand {
session_id: None,
headless: true,
timeout_ms: 30_000,
on_failure_screenshot: false,
steps: vec![
BrowserStep::Navigate {
url: server.url("/"),
expected_status: None,
timeout_ms: None,
optional: false,
},
BrowserStep::LocalStorageSet {
key: "a".to_string(),
value: "1".to_string(),
optional: false,
},
BrowserStep::LocalStorageSet {
key: "b".to_string(),
value: "2".to_string(),
optional: false,
},
BrowserStep::LocalStorageClear { optional: false },
BrowserStep::Evaluate {
function: "() => localStorage.length".to_string(),
r#ref: None,
timeout_ms: None,
optional: false,
},
],
};
let result = execute(data).await.expect("execute should succeed");
assert_eq!(
result["value"],
serde_json::json!(0),
"expected localStorage.length == 0 after clear; got: {result}"
);
}
#[tokio::test]
async fn storage_state_includes_local_storage_entries() {
if skip_if_no_chrome() {
return;
}
let _guard = common::chrome_lock().await;
let mut routes = HashMap::new();
routes.insert(
"GET /".to_string(),
Response::html("<html><body>hello</body></html>"),
);
let server = spawn(routes).await;
let data = PreparedBrowserCommand {
session_id: None,
headless: true,
timeout_ms: 30_000,
on_failure_screenshot: false,
steps: vec![
BrowserStep::Navigate {
url: server.url("/"),
expected_status: None,
timeout_ms: None,
optional: false,
},
BrowserStep::LocalStorageSet {
key: "pref".to_string(),
value: "compact".to_string(),
optional: false,
},
BrowserStep::StorageState {
path: None,
optional: false,
},
],
};
let result = execute(data).await.expect("execute should succeed");
let ls = result
.get("local_storage")
.expect("storage_state result should have a 'local_storage' field");
assert_eq!(
ls["pref"].as_str(),
Some("compact"),
"expected local_storage['pref'] == 'compact'; got: {result}"
);
}
#[tokio::test]
async fn session_storage_set_and_get_round_trip() {
if skip_if_no_chrome() {
return;
}
let _guard = common::chrome_lock().await;
let mut routes = HashMap::new();
routes.insert(
"GET /".to_string(),
Response::html("<html><body>hello</body></html>"),
);
let server = spawn(routes).await;
let data = PreparedBrowserCommand {
session_id: None,
headless: true,
timeout_ms: 30_000,
on_failure_screenshot: false,
steps: vec![
BrowserStep::Navigate {
url: server.url("/"),
expected_status: None,
timeout_ms: None,
optional: false,
},
BrowserStep::SessionStorageSet {
key: "token".to_string(),
value: "xyz".to_string(),
optional: false,
},
BrowserStep::SessionStorageGet {
key: "token".to_string(),
optional: false,
},
],
};
let result = execute(data).await.expect("execute should succeed");
assert_eq!(
result["value"].as_str(),
Some("xyz"),
"expected sessionStorage['token'] == 'xyz'; got: {result}"
);
}
#[tokio::test]
async fn session_storage_delete_removes_key() {
if skip_if_no_chrome() {
return;
}
let _guard = common::chrome_lock().await;
let mut routes = HashMap::new();
routes.insert(
"GET /".to_string(),
Response::html("<html><body>hello</body></html>"),
);
let server = spawn(routes).await;
let data = PreparedBrowserCommand {
session_id: None,
headless: true,
timeout_ms: 30_000,
on_failure_screenshot: false,
steps: vec![
BrowserStep::Navigate {
url: server.url("/"),
expected_status: None,
timeout_ms: None,
optional: false,
},
BrowserStep::SessionStorageSet {
key: "x".to_string(),
value: "1".to_string(),
optional: false,
},
BrowserStep::SessionStorageDelete {
key: "x".to_string(),
optional: false,
},
BrowserStep::Evaluate {
function: "() => sessionStorage.length".to_string(),
r#ref: None,
timeout_ms: None,
optional: false,
},
],
};
let result = execute(data).await.expect("execute should succeed");
assert_eq!(
result["value"],
serde_json::json!(0),
"expected sessionStorage.length == 0 after delete; got: {result}"
);
}
#[tokio::test]
async fn session_storage_clear_wipes_all_keys() {
if skip_if_no_chrome() {
return;
}
let _guard = common::chrome_lock().await;
let mut routes = HashMap::new();
routes.insert(
"GET /".to_string(),
Response::html("<html><body>hello</body></html>"),
);
let server = spawn(routes).await;
let data = PreparedBrowserCommand {
session_id: None,
headless: true,
timeout_ms: 30_000,
on_failure_screenshot: false,
steps: vec![
BrowserStep::Navigate {
url: server.url("/"),
expected_status: None,
timeout_ms: None,
optional: false,
},
BrowserStep::SessionStorageSet {
key: "a".to_string(),
value: "1".to_string(),
optional: false,
},
BrowserStep::SessionStorageSet {
key: "b".to_string(),
value: "2".to_string(),
optional: false,
},
BrowserStep::SessionStorageClear { optional: false },
BrowserStep::Evaluate {
function: "() => sessionStorage.length".to_string(),
r#ref: None,
timeout_ms: None,
optional: false,
},
],
};
let result = execute(data).await.expect("execute should succeed");
assert_eq!(
result["value"],
serde_json::json!(0),
"expected sessionStorage.length == 0 after clear; got: {result}"
);
}