simi-test 0.1.0

Some helpers for testing wasm app base on the Simi framework
Documentation
//! Provide structs and functions to help testing simi apps.
//! Maybe move into its own crate?
use simi::prelude::{Application, RcMain};
use wasm_bindgen::JsCast;
use web_sys::Node;

pub fn start_app<A: Application<Parent = ()>>() -> RcMain<A> {
    let test_element_id = "div-element-use-for-testing-a-simi-app";
    let doc = simi::interop::document();
    if doc.get_element_by_id(test_element_id).is_none() {
        let div = doc
            .create_element("div")
            .expect("Create div element for testing");
        div.set_id(test_element_id);
        let body = doc.body().expect("Get body of the Document");
        (body.as_ref() as &Node)
            .append_child(div.as_ref())
            .expect("Add div element to the body element");
    }
    RcMain::start_in_element_id(test_element_id, ())
}

/// A wrapper helps access real DOM element for testing
pub struct Element {
    /// The element in real dom to test
    element: web_sys::Element,
}

impl Element {
    /// Return true if there is no element with id=element_id
    pub fn no_id(element_id: &str) -> bool {
        simi::interop::document()
            .get_element_by_id(element_id)
            .map_or(true, |_| false)
    }

    /// Create a new TestHelper
    pub fn element(element: web_sys::Element) -> Self {
        Self { element }
    }

    /// Create a new TestHelper from element_id
    pub fn id(element_id: &str) -> Self {
        Self {
            element: simi::interop::document()
                .get_element_by_id(element_id)
                .unwrap_or_else(|| panic!("No element with id = '{}'", element_id)),
        }
    }

    /// Query an element by a selector string, panic if none
    pub fn selector(s: &str) -> Self {
        Self {
            element: simi::interop::document()
                .query_selector(s)
                .expect(s)
                .expect(s),
        }
    }

    /// As a reference to web_sys::EventTarget
    pub fn as_event_target(&self) -> &web_sys::EventTarget {
        self.element.as_ref()
    }

    /// As a reference to web_sys::Node
    pub fn as_node(&self) -> &web_sys::Node {
        self.element.as_ref()
    }

    /// Reference to the element
    pub fn as_element(&self) -> &web_sys::Element {
        &self.element
    }

    /// As a reference to web_sys::HtmlInputElement
    pub fn as_input(&self) -> &web_sys::HtmlInputElement {
        self.element.unchecked_ref()
    }

    /// As a reference to web_sys::HtmlSelectElement
    pub fn as_select(&self) -> &web_sys::HtmlSelectElement {
        self.element.unchecked_ref()
    }

    /// As a reference to web_sys::HtmlOptionElement
    pub fn as_option(&self) -> &web_sys::HtmlOptionElement {
        self.element.unchecked_ref()
    }

    /// As a reference to web_sys::HtmlTextAreaElement
    pub fn as_textarea(&self) -> &web_sys::HtmlTextAreaElement {
        self.element.unchecked_ref()
    }

    /// Simulate a click on the element
    pub fn click(&self) {
        let clickable: &web_sys::HtmlElement = self.element.unchecked_ref();
        clickable.click();
    }

    /// Set input element value then trigger an input event
    pub fn input_input(&self, value: &str) {
        self.as_input().set_value(value);
        self.as_event_target()
            .dispatch_event(
                web_sys::InputEvent::new("input")
                    .expect("Create input event must succeed")
                    .as_ref(),
            )
            .expect("Dispatch input event");
    }

    /// Set input element value then trigger a change event
    pub fn change_input(&self, value: &str) {
        self.as_input().set_value(value);
        self.as_event_target()
            .dispatch_event(
                web_sys::InputEvent::new("change")
                    .expect("Create change event must succeed")
                    .as_ref(),
            )
            .expect("Dispatch change event");
    }

    /// Set select element value then trigger a change event
    pub fn change_select(&self, value: &str) {
        self.as_select().set_value(value);
        self.as_event_target()
            .dispatch_event(
                &web_sys::Event::new("change").expect("Create change event must succeed"),
            )
            .expect("Dispatch change event");
    }

    /// Set select element index then trigger a change event
    pub fn change_index(&self, index: usize) {
        self.as_select().set_selected_index(index as i32);
        self.as_event_target()
            .dispatch_event(
                &web_sys::Event::new("change").expect("Create change event must succeed"),
            )
            .expect("Dispatch change event");
    }

    /// Set textarea element value then trigger a change event
    pub fn change_textarea(&self, value: &str) {
        self.as_textarea().set_value(value);
        self.as_event_target()
            .dispatch_event(
                &web_sys::Event::new("change").expect("Create change event must succeed"),
            )
            .expect("Dispatch change event");
    }
}