use browser_oxide::Page;
fn html(body: &str) -> String {
format!("<!DOCTYPE html><html><head></head><body>{body}</body></html>")
}
async fn evaluate(js: &str) -> String {
let mut page = Page::from_html(&html(""), None::<browser_oxide::stealth::StealthProfile>)
.await
.unwrap();
page.evaluate(js).unwrap_or_else(|e| format!("ERROR: {e}"))
}
const IFRAME_SETUP: &str = "
const f = document.createElement('iframe');
document.body.appendChild(f);
const cw = f.contentWindow;
";
#[tokio::test]
#[ignore = "not yet implemented: per-realm constructor identity for iframe contexts"]
async fn iframe_navigator_distinct_identity() {
let r = evaluate(&format!("{IFRAME_SETUP} cw.Navigator !== Navigator")).await;
assert_eq!(
r, "true",
"iframe.contentWindow.Navigator must be distinct from window.Navigator"
);
}
#[tokio::test]
#[ignore = "not yet implemented: per-realm constructor identity for iframe contexts"]
async fn iframe_navigator_prototype_distinct_identity() {
let r = evaluate(&format!(
"{IFRAME_SETUP} cw.Navigator.prototype !== Navigator.prototype"
))
.await;
assert_eq!(
r, "true",
"iframe.contentWindow.Navigator.prototype must be distinct"
);
}
#[tokio::test]
async fn iframe_navigator_prototype_same_shape() {
let js = format!(
"{IFRAME_SETUP}
const a = Object.getOwnPropertyNames(cw.Navigator.prototype).sort().join(',');
const b = Object.getOwnPropertyNames(Navigator.prototype).sort().join(',');
a === b
"
);
let r = evaluate(&js).await;
assert_eq!(
r, "true",
"iframe Navigator.prototype must have same own-property-names as parent's"
);
}
#[tokio::test]
#[allow(non_snake_case, reason = "mirrors JS API name under test")]
async fn iframe_function_toString_native_shape() {
let js = format!(
"{IFRAME_SETUP}
const s = cw.Function.prototype.toString.call(window.fetch);
s.includes('[native code]')
"
);
let r = evaluate(&js).await;
assert_eq!(
r, "true",
"cross-realm Function.prototype.toString must produce [native code]"
);
}
#[tokio::test]
async fn iframe_array_distinct_identity() {
let r = evaluate(&format!("{IFRAME_SETUP} cw.Array !== Array")).await;
assert_eq!(
r, "true",
"iframe.contentWindow.Array must be distinct from window.Array"
);
}
#[tokio::test]
async fn iframe_object_distinct_identity() {
let r = evaluate(&format!("{IFRAME_SETUP} cw.Object !== Object")).await;
assert_eq!(
r, "true",
"iframe.contentWindow.Object must be distinct from window.Object"
);
}
#[tokio::test]
async fn iframe_array_cross_realm_instanceof_false() {
let js = format!("{IFRAME_SETUP} ([] instanceof cw.Array)");
let r = evaluate(&js).await;
assert_eq!(r, "false", "parent [] must NOT be instanceof iframe.Array");
}
#[tokio::test]
#[ignore = "not yet implemented: per-realm constructor identity for iframe contexts"]
async fn iframe_html_element_distinct_identity() {
let r = evaluate(&format!("{IFRAME_SETUP} cw.HTMLElement !== HTMLElement")).await;
assert_eq!(r, "true");
}
#[tokio::test]
#[ignore = "not yet implemented: per-realm constructor identity for iframe contexts"]
async fn iframe_element_distinct_identity() {
let r = evaluate(&format!("{IFRAME_SETUP} cw.Element !== Element")).await;
assert_eq!(r, "true");
}
#[tokio::test]
#[ignore = "not yet implemented: per-realm constructor identity for iframe contexts"]
async fn iframe_node_distinct_identity() {
let r = evaluate(&format!("{IFRAME_SETUP} cw.Node !== Node")).await;
assert_eq!(r, "true");
}
#[tokio::test]
#[ignore = "not yet implemented: per-realm constructor identity for iframe contexts"]
async fn iframe_event_target_distinct_identity() {
let r = evaluate(&format!("{IFRAME_SETUP} cw.EventTarget !== EventTarget")).await;
assert_eq!(r, "true");
}
#[tokio::test]
#[ignore = "not yet implemented: per-realm constructor identity for iframe contexts"]
async fn iframe_event_distinct_identity() {
let r = evaluate(&format!("{IFRAME_SETUP} cw.Event !== Event")).await;
assert_eq!(r, "true");
}
#[tokio::test]
async fn iframe_navigator_constructor_name() {
let r = evaluate(&format!("{IFRAME_SETUP} cw.Navigator.name")).await;
assert_eq!(r, "Navigator");
}
#[tokio::test]
#[ignore = "not yet implemented: per-realm Navigator identity for iframe contexts"]
#[allow(non_snake_case, reason = "mirrors JS API name under test")]
async fn iframe_navigator_toString_native_shape() {
let r = evaluate(&format!(
"{IFRAME_SETUP} cw.Function.prototype.toString.call(cw.Navigator)"
))
.await;
assert_eq!(r, "function Navigator() { [native code] }");
}