testing_library_dom/queries/
display_value.rs

1use wasm_bindgen::JsCast;
2use web_sys::{HtmlElement, HtmlInputElement, HtmlOptionElement, HtmlSelectElement};
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::{html_collection_to_vec, node_list_to_vec},
11};
12
13pub fn _query_all_by_display_value<M: Into<Matcher>>(
14    container: &HtmlElement,
15    value: M,
16    options: MatcherOptions,
17) -> Result<Vec<HtmlElement>, QueryError> {
18    let value = value.into();
19    let matcher = match options.exact.unwrap_or(true) {
20        true => matches,
21        false => fuzzy_matches,
22    };
23    let match_normalizer = make_normalizer(NormalizerOptions {
24        trim: options.trim,
25        collapse_whitespace: options.collapse_whitespace,
26        normalizer: options.normalizer,
27    })?;
28
29    Ok(node_list_to_vec::<HtmlElement>(
30        container
31            .query_selector_all("input,textarea,select")
32            .map_err(QueryError::JsError)?,
33    )
34    .into_iter()
35    .filter(|node| {
36        if node.tag_name() == "SELECT" {
37            html_collection_to_vec::<HtmlOptionElement>(
38                node.unchecked_ref::<HtmlSelectElement>().options().into(),
39            )
40            .into_iter()
41            .filter(|option| option.selected())
42            .any(|option_node| {
43                matcher(
44                    Some(get_node_text(&option_node)),
45                    Some(&option_node),
46                    &value,
47                    match_normalizer.as_ref(),
48                )
49            })
50        } else {
51            matcher(
52                Some(node.unchecked_ref::<HtmlInputElement>().value()),
53                Some(node),
54                &value,
55                match_normalizer.as_ref(),
56            )
57        }
58    })
59    .collect())
60}
61
62fn get_multiple_error(
63    _container: &HtmlElement,
64    value: Matcher,
65    _options: MatcherOptions,
66) -> Result<String, QueryError> {
67    Ok(format!(
68        "Found multiple elements with the display value: {value}"
69    ))
70}
71
72fn get_missing_error(
73    _container: &HtmlElement,
74    value: Matcher,
75    _options: MatcherOptions,
76) -> Result<String, QueryError> {
77    Ok(format!(
78        "Unable to find an element with the display value: {value}"
79    ))
80}
81
82build_queries!(
83    _query_all_by_display_value,
84    get_multiple_error,
85    get_missing_error,
86    display_value,
87    crate::types::Matcher,
88    crate::types::MatcherOptions
89);
90
91pub use internal::{
92    find_all_by_display_value, find_by_display_value, get_all_by_display_value,
93    get_by_display_value, query_all_by_display_value, query_by_display_value,
94};