#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Role {
Button,
Text,
Image,
Slider,
Alert,
Dialog,
Checkbox,
Radio,
Switch,
TextInput,
MenuItem,
ProgressBar,
Link,
Heading,
List,
ListItem,
Tab,
TabPanel,
Unknown,
}
#[derive(Clone, Debug)]
pub struct SemanticNode {
pub label: Option<String>,
pub role: Role,
pub value: Option<String>,
pub heading_level: Option<u8>,
pub href: Option<String>,
pub children: Vec<SemanticNode>,
}
impl SemanticNode {
pub fn new() -> Self {
SemanticNode {
label: None,
role: Role::Unknown,
value: None,
heading_level: None,
href: None,
children: Vec::new(),
}
}
pub fn label(mut self, label: impl Into<String>) -> Self {
self.label = Some(label.into());
self
}
pub fn role(mut self, role: Role) -> Self {
self.role = role;
self
}
pub fn value(mut self, value: impl Into<String>) -> Self {
self.value = Some(value.into());
self
}
pub fn heading_level(mut self, level: u8) -> Self {
self.heading_level = Some(level);
self
}
pub fn href(mut self, href: impl Into<String>) -> Self {
self.href = Some(href.into());
self
}
pub fn child(mut self, node: SemanticNode) -> Self {
self.children.push(node);
self
}
}
impl Default for SemanticNode {
fn default() -> Self {
SemanticNode::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_semantic_node_has_unknown_role_and_no_optional_fields() {
let node = SemanticNode::new();
assert_eq!(node.role, Role::Unknown);
assert!(node.label.is_none());
assert!(node.value.is_none());
assert!(node.heading_level.is_none());
assert!(node.href.is_none());
assert!(node.children.is_empty());
}
#[test]
fn builder_methods_set_the_expected_fields() {
let node = SemanticNode::new()
.role(Role::Heading)
.label("Section title")
.heading_level(2)
.value("current value")
.child(SemanticNode::new().role(Role::Text).label("child"));
assert_eq!(node.role, Role::Heading);
assert_eq!(node.label.as_deref(), Some("Section title"));
assert_eq!(node.heading_level, Some(2));
assert_eq!(node.value.as_deref(), Some("current value"));
assert_eq!(node.children.len(), 1);
}
#[test]
fn href_only_meaningful_for_link_but_settable_regardless() {
let node = SemanticNode::new().role(Role::Link).href("https://example.com");
assert_eq!(node.href.as_deref(), Some("https://example.com"));
}
#[test]
fn default_matches_new() {
assert_eq!(SemanticNode::default().role, SemanticNode::new().role);
}
}