testing_library_dom/queries/
title.rs1use wasm_bindgen::JsCast;
2use web_sys::{Element, HtmlElement};
3
4use crate::{
5 build_queries,
6 error::QueryError,
7 get_node_text::get_node_text,
8 matches::{fuzzy_matches, make_normalizer, matches},
9 types::{Matcher, MatcherOptions, NormalizerOptions},
10 util::node_list_to_vec,
11};
12
13fn is_svg_title(node: &HtmlElement) -> bool {
14 node.tag_name().to_lowercase() == "title"
15 && node
16 .parent_node()
17 .and_then(|parent_node| parent_node.dyn_into::<Element>().ok())
18 .is_some_and(|parent_node| parent_node.tag_name().to_lowercase() == "svg")
19}
20
21pub fn _query_all_by_title<M: Into<Matcher>>(
22 container: &HtmlElement,
23 text: M,
24 options: MatcherOptions,
25) -> Result<Vec<HtmlElement>, QueryError> {
26 let text = text.into();
27 let matcher = match options.exact.unwrap_or(true) {
28 true => matches,
29 false => fuzzy_matches,
30 };
31 let match_normalizer = make_normalizer(NormalizerOptions {
32 trim: options.trim,
33 collapse_whitespace: options.collapse_whitespace,
34 normalizer: options.normalizer,
35 })?;
36
37 Ok(node_list_to_vec::<HtmlElement>(
38 container
39 .query_selector_all("[title], svg > title")
40 .map_err(QueryError::JsError)?,
41 )
42 .into_iter()
43 .filter(|node| {
44 matcher(
45 node.get_attribute("title"),
46 Some(node),
47 &text,
48 match_normalizer.as_ref(),
49 ) || (is_svg_title(node)
50 && matcher(
51 Some(get_node_text(node)),
52 Some(node),
53 &text,
54 match_normalizer.as_ref(),
55 ))
56 })
57 .collect())
58}
59
60fn get_multiple_error(
61 _container: &HtmlElement,
62 title: Matcher,
63 _options: MatcherOptions,
64) -> Result<String, QueryError> {
65 Ok(format!("Found multiple elements with the title: {title}"))
66}
67
68fn get_missing_error(
69 _container: &HtmlElement,
70 title: Matcher,
71 _options: MatcherOptions,
72) -> Result<String, QueryError> {
73 Ok(format!("Unable to find an element with the title: {title}"))
74}
75
76build_queries!(
77 _query_all_by_title,
78 get_multiple_error,
79 get_missing_error,
80 title,
81 crate::types::Matcher,
82 crate::types::MatcherOptions
83);
84
85pub use internal::{
86 find_all_by_title, find_by_title, get_all_by_title, get_by_title, query_all_by_title,
87 query_by_title,
88};