Skip to main content

stratum_test/
lib.rs

1//! # stratum-test
2//!
3//! Test utilities for NexusStratum components.
4//!
5//! Provides assertion helpers and test harness utilities for verifying
6//! component render output, accessibility attributes, and state transitions.
7//!
8//! ## Usage
9//!
10//! ```ignore
11//! use stratum_test::*;
12//! use stratum_core::aria::AriaRole;
13//!
14//! let output = MyComponent::render(&props);
15//! assert!(assert_aria_role(&output, AriaRole::Button));
16//! assert!(assert_has_class(&output, "btn-primary"));
17//! ```
18
19use stratum_core::aria::AriaRole;
20use stratum_core::render::RenderOutput;
21
22/// Assert that a `RenderOutput` has the expected ARIA role.
23///
24/// Returns `true` if the role matches, `false` otherwise.
25pub fn assert_aria_role(output: &RenderOutput, expected: AriaRole) -> bool {
26    output.aria.role == Some(expected)
27}
28
29/// Assert that a `RenderOutput` contains the specified CSS class.
30///
31/// Returns `true` if the class is present.
32pub fn assert_has_class(output: &RenderOutput, class: &str) -> bool {
33    output.classes.iter().any(|c| c == class)
34}
35
36/// Assert that a `RenderOutput` has an HTML attribute with the given name.
37///
38/// Returns `true` if an attribute with that name exists (regardless of value).
39pub fn assert_has_attr(output: &RenderOutput, name: &str) -> bool {
40    output.attrs.iter().any(|(k, _)| k == name)
41}
42
43/// Assert that a `RenderOutput` has an HTML attribute with the expected string value.
44///
45/// Returns `true` if the attribute exists and its value matches.
46pub fn assert_attr_value(output: &RenderOutput, name: &str, expected: &str) -> bool {
47    output
48        .attrs
49        .iter()
50        .any(|(k, v)| k == name && v.to_html_value().as_deref() == Some(expected))
51}
52
53/// Assert that a `RenderOutput` has a data attribute with the given name.
54///
55/// Returns `true` if a `data-{name}` attribute is present.
56pub fn assert_has_data_attr(output: &RenderOutput, name: &str) -> bool {
57    output.data_attrs.iter().any(|(k, _)| k == name)
58}
59
60/// Assert that a `RenderOutput` does **not** have the `aria-hidden` attribute
61/// set to `"true"`, ensuring the element is visible to assistive technology.
62pub fn assert_not_aria_hidden(output: &RenderOutput) -> bool {
63    output.aria.hidden != Some(true)
64}
65
66/// Assert that the render output uses the expected HTML tag.
67///
68/// Returns `true` if the effective tag matches.
69pub fn assert_tag(output: &RenderOutput, expected: &str) -> bool {
70    output.effective_tag() == expected
71}
72
73#[cfg(test)]
74mod tests {
75    use super::*;
76    use stratum_core::aria::AriaAttributes;
77
78    #[test]
79    fn test_assert_aria_role_match() {
80        let output =
81            RenderOutput::new().with_aria(AriaAttributes::new().with_role(AriaRole::Button));
82        assert!(assert_aria_role(&output, AriaRole::Button));
83    }
84
85    #[test]
86    fn test_assert_aria_role_mismatch() {
87        let output = RenderOutput::new().with_aria(AriaAttributes::new().with_role(AriaRole::Link));
88        assert!(!assert_aria_role(&output, AriaRole::Button));
89    }
90
91    #[test]
92    fn test_assert_has_class() {
93        let output = RenderOutput::new()
94            .with_class("btn")
95            .with_class("btn-primary");
96        assert!(assert_has_class(&output, "btn"));
97        assert!(assert_has_class(&output, "btn-primary"));
98        assert!(!assert_has_class(&output, "btn-secondary"));
99    }
100
101    #[test]
102    fn test_assert_has_data_attr() {
103        let output = RenderOutput::new().with_data("testid", "save-btn");
104        assert!(assert_has_data_attr(&output, "testid"));
105        assert!(!assert_has_data_attr(&output, "other"));
106    }
107
108    #[test]
109    fn test_assert_tag() {
110        let output = RenderOutput::new().with_tag("button");
111        assert!(assert_tag(&output, "button"));
112        assert!(!assert_tag(&output, "div"));
113    }
114
115    #[test]
116    fn test_assert_tag_default() {
117        let output = RenderOutput::new();
118        assert!(assert_tag(&output, "div"));
119    }
120}