use blitz_dom::DocumentConfig;
use blitz_html::{HtmlDocument, HtmlProvider};
use blitz_traits::shell::{ColorScheme, Viewport};
use std::sync::Arc;
fn doc(html: &str) -> HtmlDocument {
let mut doc = HtmlDocument::from_html(
html,
DocumentConfig {
viewport: Some(Viewport::new(200, 200, 1.0, ColorScheme::Light)),
html_parser_provider: Some(Arc::new(HtmlProvider) as _),
..Default::default()
},
);
doc.resolve(0.0);
doc
}
fn hit_id(doc: &HtmlDocument, x: f32, y: f32) -> usize {
doc.hit(x, y).expect("hit should land somewhere").node_id
}
fn node_id(doc: &HtmlDocument, selector: &str) -> usize {
doc.query_selector(selector).unwrap().expect(selector)
}
#[test]
fn overlay_with_pointer_events_none_passes_through_to_button() {
let doc = doc(r#"<html><body style="margin:0">
<div style="position:relative; width:200px; height:36px;">
<button id="btn" style="position:static; width:44px; height:36px; margin-left:156px; display:block;">x</button>
<div id="overlay" style="position:absolute; left:0; top:0; right:0; bottom:0; pointer-events:none;">
<span>Kopuz</span>
</div>
</div>
</body></html>"#);
let btn = node_id(&doc, "#btn");
let hit = hit_id(&doc, 178.0, 18.0);
let hit_or_ancestor =
std::iter::successors(Some(hit), |&id| doc.get_node(id).and_then(|n| n.parent))
.any(|id| id == btn);
assert!(
hit_or_ancestor,
"expected hit on #btn (node {btn}) but hit node {hit}"
);
}
#[test]
fn element_with_pointer_events_none_is_not_a_target() {
let doc = doc(r#"<html><body style="margin:0">
<div id="under" style="width:100px; height:100px;">
<div id="blocker" style="width:100px; height:100px; pointer-events:none;"></div>
</div>
</body></html>"#);
let blocker = node_id(&doc, "#blocker");
let under = node_id(&doc, "#under");
let hit = hit_id(&doc, 50.0, 50.0);
assert_ne!(hit, blocker, "pointer-events:none element must not be hit");
assert_eq!(hit, under, "the event should fall through to the parent");
}
#[test]
fn descendant_restoring_pointer_events_auto_is_targetable() {
let doc = doc(r#"<html><body style="margin:0">
<div style="pointer-events:none; width:200px; height:100px;">
<div id="inner" style="pointer-events:auto; width:50px; height:50px;"></div>
</div>
</body></html>"#);
let inner = node_id(&doc, "#inner");
assert_eq!(hit_id(&doc, 25.0, 25.0), inner);
}
#[test]
fn text_inside_pointer_events_none_overlay_is_not_a_target() {
let doc = doc(r#"<html><body style="margin:0">
<div id="under" style="position:relative; width:200px; height:36px;">
<div id="overlay" style="position:absolute; left:0; top:0; right:0; bottom:0; pointer-events:none;">
<span id="label" style="font-size:20px;">KOPUZKOPUZKOPUZ</span>
</div>
</div>
</body></html>"#);
let overlay = node_id(&doc, "#overlay");
let label = node_id(&doc, "#label");
let hit = hit_id(&doc, 30.0, 14.0);
assert_ne!(hit, overlay);
assert_ne!(
hit, label,
"text in a pointer-events:none subtree must not be hit"
);
}