diff --git a/Cargo.lock b/Cargo.lock index 2cce98f..2c1f381 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -113,7 +113,7 @@ dependencies = [ [[package]] name = "blitz-dom" version = "0.3.0-beta.4" -source = "git+https://github.com/hovinen/blitz?branch=support-html-label-for-accessible-name#8fbaa61624e4a27200f0aedf49c4b0bfd83e10c1" +source = "git+https://github.com/hovinen/blitz?branch=flesh-out-accessible-description#1d75549a02abf94c68b9eacb766ac6e133355d94" dependencies = [ "accesskit", "anyrender", @@ -162,7 +162,7 @@ dependencies = [ [[package]] name = "blitz-traits" version = "0.3.0-beta.4" -source = "git+https://github.com/hovinen/blitz?branch=support-html-label-for-accessible-name#8fbaa61624e4a27200f0aedf49c4b0bfd83e10c1" +source = "git+https://github.com/hovinen/blitz?branch=flesh-out-accessible-description#1d75549a02abf94c68b9eacb766ac6e133355d94" dependencies = [ "atomic_refcell", "bitflags", @@ -288,7 +288,7 @@ dependencies = [ [[package]] name = "const-serialize" version = "0.8.0-alpha.3" -source = "git+https://github.com/DioxusLabs/dioxus#7a817390a69294f614b3055aae2dacdf25c050a2" +source = "git+https://github.com/DioxusLabs/dioxus#d481a0b7cf55fce72577744a8272b27fd2bbf472" dependencies = [ "const-serialize-macro", "dioxus-const-vec", @@ -298,7 +298,7 @@ dependencies = [ [[package]] name = "const-serialize-macro" version = "0.8.0-alpha.3" -source = "git+https://github.com/DioxusLabs/dioxus#7a817390a69294f614b3055aae2dacdf25c050a2" +source = "git+https://github.com/DioxusLabs/dioxus#d481a0b7cf55fce72577744a8272b27fd2bbf472" dependencies = [ "proc-macro2", "quote", @@ -307,9 +307,9 @@ dependencies = [ [[package]] name = "const_format" -version = "0.2.36" +version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4481a617ad9a412be3b97c5d403fef8ed023103368908b9c50af598ff467cc1e" +checksum = "a3decb4d6965448659923544a634a0571ba44cede4e11ef15a5a317126840454" dependencies = [ "const_format_proc_macros", "konst", @@ -317,9 +317,9 @@ dependencies = [ [[package]] name = "const_format_proc_macros" -version = "0.2.34" +version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" +checksum = "941b570269a642506f08cb5b688c04bfa6cfd41a26f8bcdc49db8fd00c0ab659" dependencies = [ "proc-macro2", "quote", @@ -516,7 +516,7 @@ checksum = "be1e0bca6c3637f992fc1cc7cbc52a78c1ef6db076dbf1059c4323d6a2048376" [[package]] name = "debug_timer" version = "0.1.3" -source = "git+https://github.com/hovinen/blitz?branch=support-html-label-for-accessible-name#8fbaa61624e4a27200f0aedf49c4b0bfd83e10c1" +source = "git+https://github.com/hovinen/blitz?branch=flesh-out-accessible-description#1d75549a02abf94c68b9eacb766ac6e133355d94" [[package]] name = "derive_more" @@ -552,7 +552,7 @@ dependencies = [ [[package]] name = "dioxus" version = "0.8.0-alpha.3" -source = "git+https://github.com/DioxusLabs/dioxus#7a817390a69294f614b3055aae2dacdf25c050a2" +source = "git+https://github.com/DioxusLabs/dioxus#d481a0b7cf55fce72577744a8272b27fd2bbf472" dependencies = [ "dioxus-asset-resolver", "dioxus-cli-config", @@ -577,7 +577,7 @@ dependencies = [ [[package]] name = "dioxus-asset-resolver" version = "0.8.0-alpha.3" -source = "git+https://github.com/DioxusLabs/dioxus#7a817390a69294f614b3055aae2dacdf25c050a2" +source = "git+https://github.com/DioxusLabs/dioxus#d481a0b7cf55fce72577744a8272b27fd2bbf472" dependencies = [ "jni", "ndk", @@ -589,7 +589,7 @@ dependencies = [ [[package]] name = "dioxus-cli-config" version = "0.8.0-alpha.3" -source = "git+https://github.com/DioxusLabs/dioxus#7a817390a69294f614b3055aae2dacdf25c050a2" +source = "git+https://github.com/DioxusLabs/dioxus#d481a0b7cf55fce72577744a8272b27fd2bbf472" dependencies = [ "wasm-bindgen", ] @@ -597,22 +597,22 @@ dependencies = [ [[package]] name = "dioxus-config-macro" version = "0.8.0-alpha.3" -source = "git+https://github.com/DioxusLabs/dioxus#7a817390a69294f614b3055aae2dacdf25c050a2" +source = "git+https://github.com/DioxusLabs/dioxus#d481a0b7cf55fce72577744a8272b27fd2bbf472" [[package]] name = "dioxus-config-macros" version = "0.8.0-alpha.3" -source = "git+https://github.com/DioxusLabs/dioxus#7a817390a69294f614b3055aae2dacdf25c050a2" +source = "git+https://github.com/DioxusLabs/dioxus#d481a0b7cf55fce72577744a8272b27fd2bbf472" [[package]] name = "dioxus-const-vec" version = "0.8.0-alpha.3" -source = "git+https://github.com/DioxusLabs/dioxus#7a817390a69294f614b3055aae2dacdf25c050a2" +source = "git+https://github.com/DioxusLabs/dioxus#d481a0b7cf55fce72577744a8272b27fd2bbf472" [[package]] name = "dioxus-core" version = "0.8.0-alpha.3" -source = "git+https://github.com/DioxusLabs/dioxus#7a817390a69294f614b3055aae2dacdf25c050a2" +source = "git+https://github.com/DioxusLabs/dioxus#d481a0b7cf55fce72577744a8272b27fd2bbf472" dependencies = [ "anyhow", "const_format", @@ -637,7 +637,7 @@ dependencies = [ [[package]] name = "dioxus-core-macro" version = "0.8.0-alpha.3" -source = "git+https://github.com/DioxusLabs/dioxus#7a817390a69294f614b3055aae2dacdf25c050a2" +source = "git+https://github.com/DioxusLabs/dioxus#d481a0b7cf55fce72577744a8272b27fd2bbf472" dependencies = [ "convert_case", "dioxus-rsx", @@ -649,7 +649,7 @@ dependencies = [ [[package]] name = "dioxus-core-template" version = "0.8.0-alpha.3" -source = "git+https://github.com/DioxusLabs/dioxus#7a817390a69294f614b3055aae2dacdf25c050a2" +source = "git+https://github.com/DioxusLabs/dioxus#d481a0b7cf55fce72577744a8272b27fd2bbf472" dependencies = [ "dioxus-const-vec", "serde", @@ -659,12 +659,12 @@ dependencies = [ [[package]] name = "dioxus-core-types" version = "0.8.0-alpha.3" -source = "git+https://github.com/DioxusLabs/dioxus#7a817390a69294f614b3055aae2dacdf25c050a2" +source = "git+https://github.com/DioxusLabs/dioxus#d481a0b7cf55fce72577744a8272b27fd2bbf472" [[package]] name = "dioxus-devtools" version = "0.8.0-alpha.3" -source = "git+https://github.com/DioxusLabs/dioxus#7a817390a69294f614b3055aae2dacdf25c050a2" +source = "git+https://github.com/DioxusLabs/dioxus#d481a0b7cf55fce72577744a8272b27fd2bbf472" dependencies = [ "dioxus-cli-config", "dioxus-core", @@ -681,7 +681,7 @@ dependencies = [ [[package]] name = "dioxus-devtools-types" version = "0.8.0-alpha.3" -source = "git+https://github.com/DioxusLabs/dioxus#7a817390a69294f614b3055aae2dacdf25c050a2" +source = "git+https://github.com/DioxusLabs/dioxus#d481a0b7cf55fce72577744a8272b27fd2bbf472" dependencies = [ "dioxus-core", "serde", @@ -691,7 +691,7 @@ dependencies = [ [[package]] name = "dioxus-document" version = "0.8.0-alpha.3" -source = "git+https://github.com/DioxusLabs/dioxus#7a817390a69294f614b3055aae2dacdf25c050a2" +source = "git+https://github.com/DioxusLabs/dioxus#d481a0b7cf55fce72577744a8272b27fd2bbf472" dependencies = [ "dioxus-core", "dioxus-core-macro", @@ -709,7 +709,7 @@ dependencies = [ [[package]] name = "dioxus-history" version = "0.8.0-alpha.3" -source = "git+https://github.com/DioxusLabs/dioxus#7a817390a69294f614b3055aae2dacdf25c050a2" +source = "git+https://github.com/DioxusLabs/dioxus#d481a0b7cf55fce72577744a8272b27fd2bbf472" dependencies = [ "dioxus-core", "tracing", @@ -718,7 +718,7 @@ dependencies = [ [[package]] name = "dioxus-hooks" version = "0.8.0-alpha.3" -source = "git+https://github.com/DioxusLabs/dioxus#7a817390a69294f614b3055aae2dacdf25c050a2" +source = "git+https://github.com/DioxusLabs/dioxus#d481a0b7cf55fce72577744a8272b27fd2bbf472" dependencies = [ "dioxus-core", "dioxus-signals", @@ -733,7 +733,7 @@ dependencies = [ [[package]] name = "dioxus-html" version = "0.8.0-alpha.3" -source = "git+https://github.com/DioxusLabs/dioxus#7a817390a69294f614b3055aae2dacdf25c050a2" +source = "git+https://github.com/DioxusLabs/dioxus#d481a0b7cf55fce72577744a8272b27fd2bbf472" dependencies = [ "async-trait", "bytes", @@ -759,7 +759,7 @@ dependencies = [ [[package]] name = "dioxus-html-internal-macro" version = "0.8.0-alpha.3" -source = "git+https://github.com/DioxusLabs/dioxus#7a817390a69294f614b3055aae2dacdf25c050a2" +source = "git+https://github.com/DioxusLabs/dioxus#d481a0b7cf55fce72577744a8272b27fd2bbf472" dependencies = [ "convert_case", "proc-macro2", @@ -770,7 +770,7 @@ dependencies = [ [[package]] name = "dioxus-interpreter-js" version = "0.8.0-alpha.3" -source = "git+https://github.com/DioxusLabs/dioxus#7a817390a69294f614b3055aae2dacdf25c050a2" +source = "git+https://github.com/DioxusLabs/dioxus#d481a0b7cf55fce72577744a8272b27fd2bbf472" dependencies = [ "js-sys", "lazy-js-bundle", @@ -785,7 +785,7 @@ dependencies = [ [[package]] name = "dioxus-logger" version = "0.8.0-alpha.3" -source = "git+https://github.com/DioxusLabs/dioxus#7a817390a69294f614b3055aae2dacdf25c050a2" +source = "git+https://github.com/DioxusLabs/dioxus#d481a0b7cf55fce72577744a8272b27fd2bbf472" dependencies = [ "dioxus-cli-config", "tracing", @@ -796,7 +796,7 @@ dependencies = [ [[package]] name = "dioxus-native-dom" version = "0.8.0-alpha.3" -source = "git+https://github.com/DioxusLabs/dioxus#7a817390a69294f614b3055aae2dacdf25c050a2" +source = "git+https://github.com/DioxusLabs/dioxus#d481a0b7cf55fce72577744a8272b27fd2bbf472" dependencies = [ "blitz-dom", "blitz-traits", @@ -810,7 +810,7 @@ dependencies = [ [[package]] name = "dioxus-rsx" version = "0.8.0-alpha.3" -source = "git+https://github.com/DioxusLabs/dioxus#7a817390a69294f614b3055aae2dacdf25c050a2" +source = "git+https://github.com/DioxusLabs/dioxus#d481a0b7cf55fce72577744a8272b27fd2bbf472" dependencies = [ "dioxus-core-template", "proc-macro2", @@ -823,7 +823,7 @@ dependencies = [ [[package]] name = "dioxus-signals" version = "0.8.0-alpha.3" -source = "git+https://github.com/DioxusLabs/dioxus#7a817390a69294f614b3055aae2dacdf25c050a2" +source = "git+https://github.com/DioxusLabs/dioxus#d481a0b7cf55fce72577744a8272b27fd2bbf472" dependencies = [ "dioxus-core", "futures-channel", @@ -838,7 +838,7 @@ dependencies = [ [[package]] name = "dioxus-stores" version = "0.8.0-alpha.3" -source = "git+https://github.com/DioxusLabs/dioxus#7a817390a69294f614b3055aae2dacdf25c050a2" +source = "git+https://github.com/DioxusLabs/dioxus#d481a0b7cf55fce72577744a8272b27fd2bbf472" dependencies = [ "dioxus-core", "dioxus-signals", @@ -849,7 +849,7 @@ dependencies = [ [[package]] name = "dioxus-stores-macro" version = "0.8.0-alpha.3" -source = "git+https://github.com/DioxusLabs/dioxus#7a817390a69294f614b3055aae2dacdf25c050a2" +source = "git+https://github.com/DioxusLabs/dioxus#d481a0b7cf55fce72577744a8272b27fd2bbf472" dependencies = [ "convert_case", "proc-macro2", @@ -879,7 +879,7 @@ dependencies = [ [[package]] name = "dioxus-web" version = "0.8.0-alpha.3" -source = "git+https://github.com/DioxusLabs/dioxus#7a817390a69294f614b3055aae2dacdf25c050a2" +source = "git+https://github.com/DioxusLabs/dioxus#d481a0b7cf55fce72577744a8272b27fd2bbf472" dependencies = [ "dioxus-cli-config", "dioxus-core", @@ -971,18 +971,18 @@ dependencies = [ [[package]] name = "enumset" -version = "1.1.14" +version = "1.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccc5801fd11762e24d1e420d01d2ac518f2a2ca4329d4fbb6639f2412b6204e0" +checksum = "2e6bd2d7c76d078cd7a460fa169f778c42c026fe16d90e37d7a45d37181bdce5" dependencies = [ "enumset_derive", ] [[package]] name = "enumset_derive" -version = "0.15.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bd536557b58c682b217b8fb199afdff47cd3eff260623f19e77074eb073d63a" +checksum = "f60587c2044cabd91c4d4c73e3912e9f1ea7d76905f31c7eec51869305dae044" dependencies = [ "darling 0.21.3", "proc-macro2", @@ -1181,7 +1181,7 @@ dependencies = [ [[package]] name = "generational-box" version = "0.8.0-alpha.3" -source = "git+https://github.com/DioxusLabs/dioxus#7a817390a69294f614b3055aae2dacdf25c050a2" +source = "git+https://github.com/DioxusLabs/dioxus#d481a0b7cf55fce72577744a8272b27fd2bbf472" dependencies = [ "parking_lot", "tracing", @@ -1605,7 +1605,7 @@ dependencies = [ [[package]] name = "lazy-js-bundle" version = "0.8.0-alpha.3" -source = "git+https://github.com/DioxusLabs/dioxus#7a817390a69294f614b3055aae2dacdf25c050a2" +source = "git+https://github.com/DioxusLabs/dioxus#d481a0b7cf55fce72577744a8272b27fd2bbf472" [[package]] name = "lazy_static" @@ -1699,7 +1699,7 @@ dependencies = [ [[package]] name = "manganis" version = "0.8.0-alpha.3" -source = "git+https://github.com/DioxusLabs/dioxus#7a817390a69294f614b3055aae2dacdf25c050a2" +source = "git+https://github.com/DioxusLabs/dioxus#d481a0b7cf55fce72577744a8272b27fd2bbf472" dependencies = [ "const-serialize", "jni", @@ -1713,7 +1713,7 @@ dependencies = [ [[package]] name = "manganis-core" version = "0.8.0-alpha.3" -source = "git+https://github.com/DioxusLabs/dioxus#7a817390a69294f614b3055aae2dacdf25c050a2" +source = "git+https://github.com/DioxusLabs/dioxus#d481a0b7cf55fce72577744a8272b27fd2bbf472" dependencies = [ "const-serialize", "dioxus-cli-config", @@ -1725,7 +1725,7 @@ dependencies = [ [[package]] name = "manganis-macro" version = "0.8.0-alpha.3" -source = "git+https://github.com/DioxusLabs/dioxus#7a817390a69294f614b3055aae2dacdf25c050a2" +source = "git+https://github.com/DioxusLabs/dioxus#d481a0b7cf55fce72577744a8272b27fd2bbf472" dependencies = [ "dunce", "macro-string", @@ -2664,9 +2664,9 @@ checksum = "9b0e903ee191d8f7a8fbf0d712c3a1699d19e04ceba5ad1eb673053c7d938a09" [[package]] name = "smallvec" -version = "1.16.3" +version = "1.16.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b3dc8af474f516a851ff4bd12db780f948b9250ad37211e4eec0bccea54e01b" +checksum = "d0d5d4b1981b8bbbb7aed204cae5726d683d5d6ac7e74ec54122ea28f315e7c8" [[package]] name = "smol_str" @@ -2860,7 +2860,7 @@ dependencies = [ [[package]] name = "stylo_taffy" version = "0.3.0-beta.4" -source = "git+https://github.com/hovinen/blitz?branch=support-html-label-for-accessible-name#8fbaa61624e4a27200f0aedf49c4b0bfd83e10c1" +source = "git+https://github.com/hovinen/blitz?branch=flesh-out-accessible-description#1d75549a02abf94c68b9eacb766ac6e133355d94" dependencies = [ "bitflags", "stylo", @@ -2892,7 +2892,7 @@ dependencies = [ [[package]] name = "subsecond" version = "0.8.0-alpha.3" -source = "git+https://github.com/DioxusLabs/dioxus#7a817390a69294f614b3055aae2dacdf25c050a2" +source = "git+https://github.com/DioxusLabs/dioxus#d481a0b7cf55fce72577744a8272b27fd2bbf472" dependencies = [ "js-sys", "libc", @@ -2910,7 +2910,7 @@ dependencies = [ [[package]] name = "subsecond-types" version = "0.8.0-alpha.3" -source = "git+https://github.com/DioxusLabs/dioxus#7a817390a69294f614b3055aae2dacdf25c050a2" +source = "git+https://github.com/DioxusLabs/dioxus#d481a0b7cf55fce72577744a8272b27fd2bbf472" dependencies = [ "serde", ] @@ -3344,9 +3344,9 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "uuid" -version = "1.28.0" +version = "1.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cc1186384beb7dd8eedea376413fd654937285ea6c9cfbb928dc3043ea4b606" +checksum = "4a0e2d11620c50695fe12bbbfde96b3477fe606e7284c22d505c12ce51214514" [[package]] name = "version_check" diff --git a/Cargo.toml b/Cargo.toml index 219609a..29c3a02 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,8 +11,8 @@ keywords = ["dom", "ui", "gui", "react", "testing"] [dependencies] accesskit = "0.25" -blitz-dom = { git = "https://github.com/hovinen/blitz", branch = "support-html-label-for-accessible-name", default-features = false } -blitz-traits = { git = "https://github.com/hovinen/blitz", branch = "support-html-label-for-accessible-name", default-features = false } +blitz-dom = { git = "https://github.com/hovinen/blitz", branch = "flesh-out-accessible-description", default-features = false } +blitz-traits = { git = "https://github.com/hovinen/blitz", branch = "flesh-out-accessible-description", default-features = false } dioxus-core = { git = "https://github.com/DioxusLabs/dioxus" } dioxus-html = { git = "https://github.com/DioxusLabs/dioxus" } dioxus-native-dom = { git = "https://github.com/DioxusLabs/dioxus" } @@ -23,8 +23,8 @@ tokio = { version = "1.48", features = ["time"] } tracing = { version = "0.1.41" } [patch.crates-io] -blitz-dom = { git = "https://github.com/hovinen/blitz", branch = "support-html-label-for-accessible-name" } -blitz-traits = { git = "https://github.com/hovinen/blitz", branch = "support-html-label-for-accessible-name" } +blitz-dom = { git = "https://github.com/hovinen/blitz", branch = "flesh-out-accessible-description" } +blitz-traits = { git = "https://github.com/hovinen/blitz", branch = "flesh-out-accessible-description" } [dev-dependencies] dioxus= { git = "https://github.com/DioxusLabs/dioxus" } diff --git a/src/query.rs b/src/query.rs index 78598de..c3fd0eb 100644 --- a/src/query.rs +++ b/src/query.rs @@ -473,6 +473,7 @@ type OptionStringSliceMatcher = dyn for<'a> Matcher>; pub struct QueryByAriaProperties<'parent> { role: Option, name: Option>, + description: Option>, level: Option>>, hidden: Option, expanded: Option, @@ -576,6 +577,100 @@ impl<'parent> QueryByAriaProperties<'parent> { } } + /// Restricts this query to elements having an accessible description matched by the given + /// matcher. + /// + /// See [W3C documentation](https://w3c.github.io/aria/accname/#dfn-accessible-description) for + /// information on the accessible description of an element. + /// + /// ``` + /// use dioxus::prelude::*; + /// use dioxus_test::{Role, by_role, by_testid, matchers::{eq, inner_html}, render}; + /// + /// #[component] + /// fn MyComponent() -> Element { + /// let mut output = use_signal(|| ""); + /// rsx! { + /// button { + /// onclick: move |_| { + /// output.set("Wrong button clicked") + /// }, + /// "aria-description": "Do not click!", + /// "Generic buton" + /// } + /// button { + /// onclick: move |_| { + /// output.set("Right button clicked") + /// }, + /// "aria-description": "Click me!", + /// "Generic button" + /// } + /// div { + /// "data-testid": "output", + /// {output} + /// } + /// } + /// } + /// + /// # async fn test_fn() { + /// let tester = render(MyComponent); + /// tester + /// .query(by_role(Role::Button).having_description(eq("Click me!"))) + /// .click() + /// .await + /// .unwrap(); + /// + /// tester + /// .query(by_testid("output")) + /// .expect(inner_html(eq("Right button clicked"))) + /// .immediately() + /// .unwrap(); + /// # } + /// # tokio::runtime::Builder::new_current_thread().enable_time().build().unwrap().block_on(test_fn()); + /// ``` + /// + /// See [`by_name`] for more information about the matchers one can use with this method. + pub fn having_description(self, description: impl for<'a> Matcher<&'a str> + 'static) -> Self { + Self { + description: Some(Rc::new(some(description))), + ..self + } + } + + /// Restricts this query to elements having no accessible description as defined by the + /// [W3C specification](https://w3c.github.io/accname/#dfn-accessible-description). + /// + /// ``` + /// use dioxus::prelude::*; + /// use dioxus_test::{Role, by_role, by_testid, matchers::{eq, inner_html, len}, render}; + /// + /// #[component] + /// fn MyComponent() -> Element { + /// rsx! { + /// div {} + /// div { + /// "aria-description": "This div has an accessible description" + /// } + /// } + /// } + /// + /// # async fn test_fn() { + /// let tester = render(MyComponent); + /// tester + /// .query_all(by_role(Role::GenericContainer).having_no_description()) + /// .expect(len(eq(1))) + /// .await + /// .unwrap(); + /// # } + /// # tokio::runtime::Builder::new_current_thread().enable_time().build().unwrap().block_on(test_fn()); + /// ``` + pub fn having_no_description(self) -> Self { + Self { + description: Some(Rc::new(none())), + ..self + } + } + /// Restricts this query to elements having an ARIA level matched by the given matcher. /// /// The level is one-based, as in the @@ -991,6 +1086,10 @@ impl<'parent> QueryByAriaProperties<'parent> { name.matches(&if is_hidden { None } else { node.label() }) .is_match() }) + && self + .description + .as_ref() + .is_none_or(|description| description.matches(&node.description()).is_match()) && self.level.as_ref().is_none_or(|level| { // accesskit levels are zero-based, while ARIA levels are one-based. // See https://docs.rs/accesskit/latest/accesskit/struct.Node.html#method.level @@ -1024,6 +1123,14 @@ impl<'parent> QueryByAriaProperties<'parent> { } else if let Some(name) = &self.name { write!(result, "name {}", name.describe(MatcherResult::Match)).unwrap(); // Infallible } + if let Some(description) = &self.description { + write!( + result, + " having accessible description {}", + description.describe(MatcherResult::Match) + ) + .unwrap(); // Infallible + } if let Some(level) = &self.level { write!( result, @@ -1075,6 +1182,13 @@ impl<'parent> std::fmt::Display for QueryByAriaProperties<'parent> { } else if let Some(name) = &self.name { write!(f, r#"name {}"#, name.describe(MatcherResult::Match))?; } + if let Some(description) = &self.description { + write!( + f, + r#" having description {}"#, + description.describe(MatcherResult::Match) + )?; + } if let Some(level) = &self.level { write!( f, @@ -1232,6 +1346,13 @@ mod tests { verify_that!(format!("{query}"), contains_substring("A button")) } + #[test] + fn by_role_display_format_contains_description() -> TestResult<()> { + let query = by_role(Role::Button).having_description(eq("A button")); + + verify_that!(format!("{query}"), contains_substring("A button")) + } + #[test] fn failure_message_for_query_by_role_includes_name() -> TestResult<()> { #[component] @@ -1247,6 +1368,21 @@ mod tests { verify_that!(result, err(displays_as(contains_substring("A button")))) } + #[test] + fn failure_message_for_query_by_role_includes_description() -> TestResult<()> { + #[component] + fn TestComponent() -> Element { + rsx! {} + } + let tester = render(TestComponent); + + let result = tester + .query(by_role(Role::Button).having_description(eq("A button"))) + .immediately(); + + verify_that!(result, err(displays_as(contains_substring("A button")))) + } + #[test] fn by_role_display_format_contains_level() -> TestResult<()> { let query = by_role(Role::Heading).having_level(eq(3)); @@ -1325,6 +1461,133 @@ mod tests { .immediately() } + #[test] + fn having_description_gets_description_from_aria_describedby_target() -> crate::Result<()> { + #[component] + fn TestComponent() -> Element { + rsx! { + button { "aria-describedby": "description", "A button" } + span { id: "description", "A description" } + } + } + let tester = render(TestComponent); + + tester + .query_all(by_role(Role::Button).having_description(eq("A description"))) + .expect(len(eq(1))) + .immediately() + } + + #[test] + fn having_description_gets_description_from_aria_description() -> crate::Result<()> { + #[component] + fn TestComponent() -> Element { + rsx! { + button { "aria-description": "A description", "A button" } + } + } + let tester = render(TestComponent); + + tester + .query_all(by_role(Role::Button).having_description(eq("A description"))) + .expect(len(eq(1))) + .immediately() + } + + #[test] + fn having_description_selects_element_by_its_own_description() -> crate::Result<()> { + #[component] + fn TestComponent() -> Element { + rsx! { + button { "aria-description": "Wrong description", "First button" } + button { "aria-description": "Right description", "Second button" } + } + } + let tester = render(TestComponent); + + tester + .query(by_role(Role::Button).having_description(eq("Right description"))) + .expect(inner_html(eq("Second button"))) + .immediately() + } + + #[test] + fn having_description_with_empty_string_does_not_match_undescribed_element() -> crate::Result<()> + { + #[component] + fn TestComponent() -> Element { + rsx! { + button { "A button" } + } + } + let tester = render(TestComponent); + + tester + .query(by_role(Role::Button).having_description(eq(""))) + .expect_no_matching_element() + .immediately() + } + + #[test] + fn having_no_description_matches_undescribed_element() -> crate::Result<()> { + #[component] + fn TestComponent() -> Element { + rsx! { + button { "Undescribed button" } + button { "aria-description": "A description", "Described button" } + } + } + let tester = render(TestComponent); + + tester + .query_all(by_role(Role::Button).having_no_description()) + .expect(len(eq(1))) + .immediately()?; + tester + .query(by_role(Role::Button).having_no_description()) + .expect(inner_html(eq("Undescribed button"))) + .immediately() + } + + #[test] + fn having_no_description_does_not_match_element_described_by_aria_describedby() + -> crate::Result<()> { + #[component] + fn TestComponent() -> Element { + rsx! { + button { "aria-describedby": "description", "A button" } + span { id: "description", "A description" } + } + } + let tester = render(TestComponent); + + tester + .query(by_role(Role::Button).having_no_description()) + .expect_no_matching_element() + .immediately() + } + + #[test] + fn having_description_combines_with_name() -> crate::Result<()> { + #[component] + fn TestComponent() -> Element { + rsx! { + button { "aria-description": "Shared description", "First button" } + button { "aria-description": "Shared description", "Second button" } + } + } + let tester = render(TestComponent); + + tester + .query( + by_role(Role::Button) + .having_name(eq("Second button")) + .having_description(eq("Shared description")), + ) + .expect(inner_html(eq("Second button"))) + .immediately() + } + #[test] fn failure_message_for_query_by_role_includes_level() -> TestResult<()> { #[component]