diff --git a/Cargo.lock b/Cargo.lock index 7c7da66..676e14f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,18 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" version = "1.1.3" @@ -25,9 +37,12 @@ checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "aria-query" -version = "0.0.4" +version = "0.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4c6e6778de8b9abfa42ebcc484b7295a2e53da985c428bdb473a7bddf124fd7" +checksum = "2d4456c92d34f933d42cdd8d5b4eca7f816c88c323a3b9ab80872c17e2a3d19d" +dependencies = [ + "ordered_hash_map", +] [[package]] name = "bumpalo" @@ -50,6 +65,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + [[package]] name = "dom-accessibility-api" version = "0.0.3" @@ -72,6 +93,15 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28dd6caf6059519a65843af8fe2a3ae298b14b80179855aeb4adc2c1934ee619" +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", +] + [[package]] name = "indoc" version = "2.0.6" @@ -142,6 +172,15 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +[[package]] +name = "ordered_hash_map" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab0e5f22bf6dd04abd854a8874247813a8fa2c8c1260eba6fbb150270ce7c176" +dependencies = [ + "hashbrown", +] + [[package]] name = "paste" version = "1.0.15" @@ -184,6 +223,16 @@ dependencies = [ "web-sys", ] +[[package]] +name = "pretty_assertions" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" +dependencies = [ + "diff", + "yansi", +] + [[package]] name = "proc-macro2" version = "1.0.94" @@ -284,16 +333,28 @@ dependencies = [ "indoc", "log", "mockall", + "ordered_hash_map", "paste", "pretty-format", + "pretty_assertions", "regex", "send_wrapper", + "testing_logger", "thiserror", "wasm-bindgen", "wasm-bindgen-test", "web-sys", ] +[[package]] +name = "testing_logger" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d92b727cb45d33ae956f7f46b966b25f1bc712092aeef9dba5ac798fc89f720" +dependencies = [ + "log", +] + [[package]] name = "thiserror" version = "2.0.12" @@ -320,6 +381,12 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + [[package]] name = "walkdir" version = "2.5.0" @@ -516,3 +583,29 @@ name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "yansi" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" + +[[package]] +name = "zerocopy" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/packages/dom/Cargo.toml b/packages/dom/Cargo.toml index 24aca69..bf77884 100644 --- a/packages/dom/Cargo.toml +++ b/packages/dom/Cargo.toml @@ -10,15 +10,17 @@ repository.workspace = true version.workspace = true [dependencies] -aria-query = "0.0.4" +aria-query = "0.0.5" dom-accessibility-api = "0.0.3" log.workspace = true +ordered_hash_map = "0.4.0" paste = "1.0.15" pretty-format = { path = "../pretty-format", version = "0.0.1" } regex.workspace = true thiserror.workspace = true wasm-bindgen.workspace = true web-sys = { workspace = true, features = [ + "AddEventListenerOptions", "AnimationEvent", "AnimationEventInit", "Attr", @@ -48,6 +50,8 @@ web-sys = { workspace = true, features = [ "InputEventInit", "KeyboardEvent", "KeyboardEventInit", + "MessageEvent", + "MessageEventInit", "MouseEvent", "MouseEventInit", "NamedNodeMap", @@ -75,7 +79,9 @@ web-sys = { workspace = true, features = [ [dev-dependencies] indoc = "2.0.5" mockall = "0.13.0" +pretty_assertions = "1.4.1" send_wrapper = "0.6.0" +testing_logger = "0.1.1" wasm-bindgen-test.workspace = true [lints.rust] diff --git a/packages/dom/src/config.rs b/packages/dom/src/config.rs index 22f176d..a63cec0 100644 --- a/packages/dom/src/config.rs +++ b/packages/dom/src/config.rs @@ -8,10 +8,10 @@ use crate::{ static CONFIG: LazyLock>> = LazyLock::new(|| { Arc::new(Mutex::new(Config { - test_id_attribute: "data-testid".into(), + test_id_attribute: "data-testid".to_owned(), event_wrapper: Arc::new(|cb| cb()), default_hidden: false, - default_ignore: "script, style".into(), + default_ignore: "script, style".to_owned(), show_original_stack_trace: false, throw_suggestions: false, get_element_error: Arc::new(|message, container| { diff --git a/packages/dom/src/dom_element_filter.rs b/packages/dom/src/dom_element_filter.rs index e0f706a..44587e0 100644 --- a/packages/dom/src/dom_element_filter.rs +++ b/packages/dom/src/dom_element_filter.rs @@ -5,14 +5,15 @@ use regex::Regex; use wasm_bindgen::{JsCast, JsValue}; use web_sys::{Comment, Element, Node, Text}; -use crate::util::{named_node_map_to_hashmap, node_list_to_vec}; +use crate::util::{named_node_map_to_hashmap, named_node_map_to_vec, node_list_to_vec}; fn escape_html(text: String) -> String { text.replace('<', "<").replace('>', ">") } fn print_props( - attributes: HashMap, + keys: Vec, + props: HashMap, config: &Config, indentation: String, depth: usize, @@ -21,25 +22,26 @@ fn print_props( ) -> String { let indentation_next = format!("{}{}", indentation, config.indent); - attributes - .into_iter() - .map(|(key, value)| { - let printed = printer( - &JsValue::from_str(&value), - config, - indentation_next.clone(), - depth, - refs.clone(), - None, - ); + keys.into_iter() + .filter_map(|key| { + props.get(&key).map(|value| { + let printed = printer( + &JsValue::from_str(value), + config, + indentation_next.clone(), + depth, + refs.clone(), + None, + ); - format!( - "{}{}{}={}", - config.spacing_inner, - indentation, - config.colors.prop.paint(&key), - config.colors.value.paint(&printed) - ) + format!( + "{}{}{}={}", + config.spacing_inner, + indentation, + config.colors.prop.paint(&key), + config.colors.value.paint(&printed) + ) + }) }) .collect::>() .join("") @@ -67,7 +69,7 @@ fn print_children( if printed_child.is_empty() && child.node_type() != Node::TEXT_NODE { // A plugin serialized this Node to '' meaning we should ignore it. - "".into() + "".to_owned() } else { format!("{}{}{}", config.spacing_outer, indentation, printed_child) } @@ -99,7 +101,7 @@ fn print_element( "<{}{}{}>", r#type, if printed_props.is_empty() { - "".into() + "".to_owned() } else { format!( "{}{}{}{}{}", @@ -112,9 +114,9 @@ fn print_element( }, if printed_children.is_empty() { if !printed_props.is_empty() && !config.min { - "/".into() + "/".to_owned() } else { - " /".into() + " /".to_owned() } } else { format!( @@ -207,7 +209,7 @@ impl Plugin for DomElementFilter { } let r#type = if node_is_fragment(node) { - "DocumentFragment".into() + "DocumentFragment".to_owned() } else { node.unchecked_ref::().tag_name().to_lowercase() }; @@ -220,6 +222,19 @@ impl Plugin for DomElementFilter { print_element( r#type, print_props( + if node_is_fragment(node) { + vec![] + } else { + let mut keys = + named_node_map_to_vec(node.unchecked_ref::().attributes()) + .into_iter() + .map(|attr| attr.name()) + .collect::>(); + + keys.sort(); + + keys + }, if node_is_fragment(node) { HashMap::new() } else { diff --git a/packages/dom/src/events.rs b/packages/dom/src/events.rs index d6c41fb..42ca25e 100644 --- a/packages/dom/src/events.rs +++ b/packages/dom/src/events.rs @@ -3,10 +3,11 @@ use wasm_bindgen::JsValue; use web_sys::{ AnimationEvent, AnimationEventInit, ClipboardEvent, ClipboardEventInit, CompositionEvent, CompositionEventInit, DragEvent, DragEventInit, Event, EventInit, EventTarget, FocusEvent, - FocusEventInit, InputEvent, InputEventInit, KeyboardEvent, KeyboardEventInit, MouseEvent, - MouseEventInit, PageTransitionEvent, PageTransitionEventInit, PointerEvent, PointerEventInit, - PopStateEvent, PopStateEventInit, ProgressEvent, ProgressEventInit, TouchEvent, TouchEventInit, - TransitionEvent, TransitionEventInit, UiEvent, UiEventInit, WheelEvent, WheelEventInit, + FocusEventInit, InputEvent, InputEventInit, KeyboardEvent, KeyboardEventInit, MessageEvent, + MessageEventInit, MouseEvent, MouseEventInit, PageTransitionEvent, PageTransitionEventInit, + PointerEvent, PointerEventInit, PopStateEvent, PopStateEventInit, ProgressEvent, + ProgressEventInit, TouchEvent, TouchEventInit, TransitionEvent, TransitionEventInit, UiEvent, + UiEventInit, WheelEvent, WheelEventInit, }; use crate::{ @@ -282,6 +283,7 @@ generate_event_types!( (FocusEvent, new_with_focus_event_init_dict), (InputEvent, new_with_event_init_dict), (KeyboardEvent, new_with_keyboard_event_init_dict), + (MessageEvent, new_with_event_init_dict), (MouseEvent, new_with_mouse_event_init_dict), (PageTransitionEvent, new_with_event_init_dict), (PointerEvent, new_with_event_init_dict), diff --git a/packages/dom/src/label_helpers.rs b/packages/dom/src/label_helpers.rs index 49dd712..cdf4849 100644 --- a/packages/dom/src/label_helpers.rs +++ b/packages/dom/src/label_helpers.rs @@ -10,7 +10,7 @@ const LABELLED_NODE_NAMES: [&str; 7] = [ fn get_text_content(node: &Node) -> Option { if LABELLED_NODE_NAMES.contains(&node.node_name().to_lowercase().as_str()) { - Some("".into()) + Some("".to_owned()) } else if node.node_type() == Node::TEXT_NODE { node.text_content() } else { @@ -62,7 +62,8 @@ fn is_labelable(element: &Element) -> bool { Regex::new(r"BUTTON|METER|OUTPUT|PROGRESS|SELECT|TEXTAREA") .expect("Regex should be valid.") .is_match(&element.tag_name()) - || element.tag_name() == "INPUT" && element.get_attribute("type") != Some("hidden".into()) + || element.tag_name() == "INPUT" + && element.get_attribute("type") != Some("hidden".to_owned()) } #[derive(Clone, Debug)] @@ -76,7 +77,7 @@ pub fn get_labels( element: &HtmlElement, selector: Option, ) -> Vec