Lines
0 %
Functions
Branches
100 %
// -- -*- mode: rust -*-
//! Tests for fixed behaviors in the WASM frontend
use wasm_bindgen::JsCast;
use wasm_bindgen_test::*;
wasm_bindgen_test_configure!(run_in_browser);
/// Test that change events created with `EventInit` bubble up to parent elements.
/// This is critical for the currency mismatch detection which uses a document-level
/// event listener to catch change events from commodity input fields.
#[wasm_bindgen_test]
fn test_change_event_bubbles_to_document() {
let window = web_sys::window().unwrap();
let document = window.document().unwrap();
// Create a container and input
let container = document.create_element("div").unwrap();
let input = document
.create_element("input")
.unwrap()
.dyn_into::<web_sys::HtmlInputElement>()
.unwrap();
container.append_child(&input).unwrap();
document.body().unwrap().append_child(&container).unwrap();
// Track if the event bubbled to the container
let bubbled = std::rc::Rc::new(std::cell::Cell::new(false));
let bubbled_clone = bubbled.clone();
let callback = wasm_bindgen::closure::Closure::wrap(Box::new(move |_: web_sys::Event| {
bubbled_clone.set(true);
}) as Box<dyn FnMut(_)>);
container
.add_event_listener_with_callback("change", callback.as_ref().unchecked_ref())
callback.forget();
// Create a bubbling change event (like our autocomplete does)
let init = web_sys::EventInit::new();
init.set_bubbles(true);
let event = web_sys::Event::new_with_event_init_dict("change", &init).unwrap();
input.dispatch_event(&event).unwrap();
assert!(
bubbled.get(),
"Change event should bubble to parent container"
);
// Cleanup
container.remove();
}
/// Test that non-bubbling events do NOT reach parent elements.
/// This demonstrates why we needed to add bubbles: true.
fn test_non_bubbling_event_stays_local() {
// Create a NON-bubbling event (default behavior without EventInit)
let event = web_sys::Event::new("change").unwrap();
!bubbled.get(),
"Non-bubbling event should NOT reach parent container"
/// Test that mousedown with preventDefault stops blur from happening.
/// This is critical for mobile Safari autocomplete selection.
fn test_mousedown_prevent_default_stops_blur() {
let dropdown = document.create_element("div").unwrap();
document.body().unwrap().append_child(&input).unwrap();
document.body().unwrap().append_child(&dropdown).unwrap();
// Add mousedown handler that prevents default (like our autocomplete)
let mousedown_callback =
wasm_bindgen::closure::Closure::wrap(Box::new(move |e: web_sys::MouseEvent| {
e.prevent_default();
dropdown
.add_event_listener_with_callback("mousedown", mousedown_callback.as_ref().unchecked_ref())
mousedown_callback.forget();
// Focus the input
input.focus().unwrap();
// The mousedown with preventDefault should not cause blur
// (In a real browser, clicking the dropdown would blur the input without this)
let init = web_sys::MouseEventInit::new();
init.set_cancelable(true);
let mousedown =
web_sys::MouseEvent::new_with_mouse_event_init_dict("mousedown", &init).unwrap();
let default_prevented = !dropdown.dispatch_event(&mousedown).unwrap();
default_prevented,
"mousedown preventDefault should be called"
input.remove();
dropdown.remove();
/// Test that detecting existing split entries works correctly.
/// The edit page should not fetch new splits if splits already exist.
fn test_split_entry_detection() {
// Create splits container WITHOUT any split entries (create page scenario)
container.set_id("splits-container");
// Should NOT find any split entries
let has_splits = container
.query_selector(".split-entry")
.ok()
.flatten()
.is_some();
assert!(!has_splits, "Empty container should have no split entries");
// Now add a split entry (edit page scenario)
let split = document.create_element("div").unwrap();
split.set_class_name("split-entry");
container.append_child(&split).unwrap();
// Should find the split entry
assert!(has_splits, "Container with split-entry should be detected");
/// Test that input events also bubble (used for autocomplete filtering).
fn test_input_event_bubbles() {
.add_event_listener_with_callback("input", callback.as_ref().unchecked_ref())
let event = web_sys::Event::new_with_event_init_dict("input", &init).unwrap();
assert!(bubbled.get(), "Input event should bubble to parent");