testing_library_dom/queries/
title.rs

1use 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};