use blitz_dom::Document as _;
use blitz_script::ScriptDocument;
fn eval_string(doc: &mut ScriptDocument, code: &str) -> String {
doc.eval(&format!("globalThis.__out = String({code});"));
doc.eval_json("globalThis.__out")
.ok()
.and_then(|v| v.as_str().map(str::to_owned))
.unwrap_or_default()
}
fn page() -> ScriptDocument {
ScriptDocument::from_html(
r#"<html><head><style>
#shown { display: flex; width: 320px; height: 40px; color: rgb(1, 2, 3); }
#gone { display: none; }
</style></head>
<body style="margin:0">
<div id="shown">visible</div>
<div id="gone">hidden</div>
</body></html>"#,
blitz_dom::DocumentConfig::default(),
)
}
#[test]
fn a_hidden_element_reports_display_none() {
let mut doc = page();
doc.execute_scripts();
doc.inner_mut().resolve(0.0);
let shown = eval_string(
&mut doc,
"getComputedStyle(document.getElementById('shown')).display",
);
let gone = eval_string(
&mut doc,
"getComputedStyle(document.getElementById('gone')).display",
);
assert_eq!(shown, "flex", "a shown element should report its display");
assert_eq!(gone, "none", "a hidden element should report `none`");
assert_ne!(
shown, gone,
"a stub returning one value for both is the bug"
);
}
#[test]
fn get_property_value_agrees_with_property_access() {
let mut doc = page();
doc.execute_scripts();
doc.inner_mut().resolve(0.0);
let direct = eval_string(
&mut doc,
"getComputedStyle(document.getElementById('shown')).display",
);
let via_getter = eval_string(
&mut doc,
"getComputedStyle(document.getElementById('shown')).getPropertyValue('display')",
);
assert_eq!(direct, "flex");
assert_eq!(via_getter, direct);
}
#[test]
fn a_hyphenated_property_is_reachable_both_ways() {
let mut doc = page();
doc.execute_scripts();
doc.inner_mut().resolve(0.0);
let hyphen = eval_string(
&mut doc,
"getComputedStyle(document.getElementById('shown')).getPropertyValue('font-size')",
);
let camel = eval_string(
&mut doc,
"getComputedStyle(document.getElementById('shown')).fontSize",
);
assert!(
hyphen.ends_with("px"),
"font-size should be a length, got {hyphen:?}"
);
assert_eq!(camel, hyphen);
}
#[test]
fn width_reports_the_used_value() {
let mut doc = page();
doc.execute_scripts();
doc.inner_mut().resolve(0.0);
let width = eval_string(
&mut doc,
"getComputedStyle(document.getElementById('shown')).width",
);
assert_eq!(width, "320px", "width should be the laid-out width");
}
#[test]
fn an_unsupported_property_reads_as_empty() {
let mut doc = page();
doc.execute_scripts();
doc.inner_mut().resolve(0.0);
let value = eval_string(
&mut doc,
"getComputedStyle(document.getElementById('shown')).getPropertyValue('clip-path')",
);
assert_eq!(value, "", "an unsupported property should read as unset");
}
fn boxed_page() -> ScriptDocument {
ScriptDocument::from_html(
r#"<html><head><style>
.box { width: 200px; height: 50px; padding: 10px 12px; border: 3px solid black; margin: 4px 6px; }
#content { box-sizing: content-box; }
#border { box-sizing: border-box; }
</style></head>
<body style="margin:0">
<div id="content" class="box"></div>
<div id="border" class="box"></div>
</body></html>"#,
blitz_dom::DocumentConfig::default(),
)
}
#[test]
fn the_box_model_edges_are_reported() {
let mut doc = boxed_page();
doc.execute_scripts();
doc.inner_mut().resolve(0.0);
let edges = eval_string(
&mut doc,
"(() => { const s = getComputedStyle(document.getElementById('content'));
return [s.paddingTop, s.paddingLeft, s.borderTopWidth,
s.getPropertyValue('border-left-width'), s.marginTop, s.marginLeft].join(' '); })()",
);
assert_eq!(edges, "10px 12px 3px 3px 4px 6px");
}
#[test]
fn width_follows_box_sizing() {
let mut doc = boxed_page();
doc.execute_scripts();
doc.inner_mut().resolve(0.0);
let content = eval_string(
&mut doc,
"getComputedStyle(document.getElementById('content')).width",
);
let border = eval_string(
&mut doc,
"getComputedStyle(document.getElementById('border')).width",
);
assert_eq!(content, "200px", "content-box: the specified content width");
assert_eq!(
border, "200px",
"border-box: the specified border-box width"
);
}