1#![forbid(unsafe_code)]
46
47mod arena;
48mod tiers;
49mod tree;
50
51pub use arena::{Arena, ArenaBuilder, ArenaNode};
52pub use tiers::{
53 Caps, Color, ComputedStyle, Interaction, NameSource, Rect, Rendering, Semantics, Tier,
54};
55pub use tree::{
56 ancestors, closest, descendants, elements, has_text, self_and_descendants, subtree_text,
57 Document, Node, NodeId, NodeKind,
58};
59
60#[cfg(test)]
61mod tests {
62 use super::*;
63
64 fn doc() -> Arena {
65 Arena::builder()
66 .open("html")
67 .attr("lang", "de")
68 .open("head")
69 .open("title")
70 .text("Seite")
71 .close()
72 .close()
73 .open("body")
74 .open("main")
75 .open("h1")
76 .text("Titel")
77 .close()
78 .open("p")
79 .text("Ein ")
80 .open("a")
81 .attr("href", "/x")
82 .text("Link")
83 .close()
84 .text(".")
85 .close()
86 .close()
87 .close()
88 .close()
89 .build()
90 }
91
92 #[test]
93 fn wurzel_und_attribute() {
94 let d = doc();
95 assert_eq!(d.root().local_name(), "html");
96 assert_eq!(d.root().attr("lang"), Some("de"));
97 assert!(d.root().has_attr("lang"));
98 assert!(!d.root().has_attr("dir"));
99 }
100
101 #[test]
102 fn nachfahren_kommen_in_dokumentreihenfolge() {
103 let d = doc();
104 let namen: Vec<&str> = elements(&d).map(|n| n.local_name()).collect();
105 assert_eq!(
106 namen,
107 vec!["html", "head", "title", "body", "main", "h1", "p", "a"]
108 );
109 }
110
111 #[test]
112 fn subtree_text_sammelt_ueber_verschachtelung() {
113 let d = doc();
114 let p = elements(&d).find(|n| n.local_name() == "p").unwrap();
115 assert_eq!(subtree_text(p), "Ein Link.");
116 assert!(has_text(p));
117 }
118
119 #[test]
120 fn eigener_text_ist_nicht_teilbaumtext() {
121 let d = doc();
122 let p = elements(&d).find(|n| n.local_name() == "p").unwrap();
123 assert_eq!(p.text(), "");
125 assert_eq!(subtree_text(p), "Ein Link.");
126 }
127
128 #[test]
129 fn vorfahren_und_closest() {
130 let d = doc();
131 let a = elements(&d).find(|n| n.local_name() == "a").unwrap();
132 let kette: Vec<&str> = ancestors(a).map(|n| n.local_name()).collect();
133 assert_eq!(kette, vec!["p", "main", "body", "html"]);
134 assert_eq!(closest(a, "main").map(|n| n.local_name()), Some("main"));
135 assert_eq!(closest(a, "a").map(|n| n.local_name()), Some("a"));
137 assert!(closest(a, "form").is_none());
138 }
139
140 #[test]
141 fn knoten_lassen_sich_ueber_die_kennung_zurueckholen() {
142 let d = doc();
143 let h1 = elements(&d).find(|n| n.local_name() == "h1").unwrap();
144 let wieder = d.get(h1.id()).unwrap();
145 assert_eq!(wieder, h1);
146 assert!(d.get(NodeId(9999)).is_none());
147 }
148
149 #[test]
150 fn caps_kennt_struktur_immer() {
151 let nur_struktur = Caps::STRUCTURE_ONLY;
152 assert!(nur_struktur.has(Tier::Structure));
153 assert!(!nur_struktur.has(Tier::Semantics));
154
155 let voll = Caps::default()
156 .with_semantics()
157 .with_rendering()
158 .with_interaction();
159 assert!(voll.has(Tier::Rendering));
160 assert!(voll.has(Tier::Interaction));
161 }
162
163 #[test]
164 fn node_count_ist_optional_aber_hier_bekannt() {
165 let d = doc();
166 assert_eq!(d.node_count(), Some(d.len()));
167 }
168}