#![feature(proc_macro_hygiene)] #![cfg(target_arch = "wasm32")] use simi::interop::element_events::Event; use simi::prelude::*; use wasm_bindgen::prelude::*; use wasm_bindgen::JsCast; use wasm_bindgen_test::*; wasm_bindgen_test_configure!(run_in_browser); #[simi_app] struct TestApp { count: i32, string_value: String, bool_value: bool, check_value: bool, radio_value: &'static str, controlled_select_value: Option, controlled_select_index: Option, } enum Msg { Up, Down, InputTextChange(simi::interop::element_events::Event), ToggleBoolValue, TextAreaChange(simi::interop::element_events::Event), SetStringValue(String), CheckValue(Event), RadioValue(&'static str), ControlledValueSelect(Event), ControlledIndexSelect(Event), } impl Application for TestApp { type Message = Msg; type Context = (); type Parent = (); fn init() -> Self { Self { count: 2018, string_value: "Simi".to_string(), bool_value: false, radio_value: "DefaultValue", check_value: true, controlled_select_value: None, controlled_select_index: None, } } fn update(&mut self, m: Self::Message, _main: ContextPlus) -> UpdateView { match m { Msg::Up => self.count += 1, Msg::Down => self.count -= 1, Msg::InputTextChange(input) => self.update_string_value_from_input(input), Msg::ToggleBoolValue => self.bool_value = !self.bool_value, Msg::TextAreaChange(input) => self.update_string_value_from_textarea(input), Msg::SetStringValue(value) => self.string_value = value.to_string(), Msg::CheckValue(input) => self.update_check_value(input), Msg::RadioValue(value) => self.radio_value = value, Msg::ControlledValueSelect(event) => self.update_controlled_select_value(event), Msg::ControlledIndexSelect(event) => self.update_controlled_select_index(event), } true } fn render(&self, context: RenderContext) { let default_init_index = 1usize; application! { //@debug // Test classes div (id="classes" class="class1 class2" class="class3" "toggle-class1"=self.bool_value "toggle-class2"=!self.bool_value) // Test integer value and click event div (id="count-value") { "Count value: " self.count } button (id="button-count-up" onclick=#Msg::Up) { "Up" } button (id="button-count-down" onclick=#Msg::Down) { "Down" } // No update div (id="no-update-count") { "Initial value of count: " #self.count } #div (id="no-update-element") { "Initial value of count: " self.count } // Test input text and change event div (id="string-value"){ self.string_value } input (id="input-string-value" value=self.string_value onchange=#Msg::InputTextChange(?)) // Test checkbox input (id="checkbox" type="checkbox" checked=self.bool_value onclick=#Msg::ToggleBoolValue) // Test textarea and change event textarea (id="textarea" value=self.string_value onchange=#Msg::TextAreaChange(?)) // Custom attributes div (id="custom-attributes" data-user-name="Limira" data-user-skill="0" data-to-update=self.string_value) // Checkbox div { input (id="literal-check-true" type="checkbox" name="test-check" value="literal-true" checked=true) input (id="literal-check-false" type="checkbox" name="test-check" value="literal-false" checked=false) input (id="no-update-check" type="checkbox" name="test-check" value="expr-value-no-update" checked=#self.check_value) input (id="tracking-check" type="checkbox" name="test-check" value="expr-value" checked=self.check_value onchange=Msg::CheckValue(?)) } // Radio div { input (id="radio1" type="radio" name="test-radio" value="radio-value1" checked=self.radio_checked("RadioValue1") onchange=Msg::RadioValue("RadioValue1")) input (id="radio2" type="radio" name="test-radio" value="radio-value2" checked=self.radio_checked("RadioValue2") onchange=Msg::RadioValue("RadioValue2")) input (id="radio3" type="radio" name="test-radio" value="radio-value3" checked=self.radio_checked("RadioValue3") onchange=Msg::RadioValue("RadioValue3")) input (id="radio4" type="radio" name="test-radio" value="radio-value4" checked=self.radio_checked("RadioValue4") onchange=Msg::RadioValue("RadioValue4")) } // Select value div { select (id="init-value-select" value="second".to_string()) { option (id="init-value-select-option1" value="first") { "First Option" } option (id="init-value-select-option2" value="second") { "Second Option" } option (id="init-value-select-option3" value="third") { "Third Option" } } select (id="controlled-by-value-select" size="6" value=?self.controlled_select_value onchange=Msg::ControlledValueSelect(?) ) { option (id="controlled-by-value-select-option1" value="first") { "First Option" } option (id="controlled-by-value-select-option2" value="second") { "Second Option" } option (id="controlled-by-value-select-option3" value="third") { "Third Option" } } } // Select index div { select (id="init-index-select" index=default_init_index){ option (id="init-index-select-option1" value="first") { "First Option" } option (id="init-index-select-option2" value="second") { "Second Option" } option (id="init-index-select-option3" value="third") { "Third Option" } } select (id="controlled-by-index-select" index=?self.controlled_select_index onchange=Msg::ControlledIndexSelect(?) ) { option (id="controlled-by-index-select-option1" value="first") { "First Option" } option (id="controlled-by-index-select-option2" value="second") { "Second Option" } option (id="controlled-by-index-select-option3" value="third") { "Third Option" } } } } } } impl TestApp { fn update_string_value_from_input(&mut self, event: simi::interop::element_events::Event) { let target = event.target().expect("Must have a target"); let input: &web_sys::HtmlInputElement = target.unchecked_ref(); self.string_value = input.value(); } fn update_string_value_from_textarea(&mut self, event: simi::interop::element_events::Event) { let target = event.target().expect("Must have a target"); let input: &web_sys::HtmlTextAreaElement = target.unchecked_ref(); self.string_value = input.value(); } fn update_check_value(&mut self, event: Event) { let target = event.target().expect("Must have a target"); let input: &web_sys::HtmlInputElement = target.unchecked_ref(); self.check_value = input.checked(); } fn radio_checked(&self, value: &str) -> bool { self.radio_value == value } fn update_controlled_select_value(&mut self, event: Event) { let target = event.target().expect("Must have a target"); let se: &web_sys::HtmlSelectElement = target.unchecked_ref(); if se.selected_index() < 0 { self.controlled_select_value = None; } else { self.controlled_select_value = Some(se.value()); } } fn update_controlled_select_index(&mut self, event: Event) { let target = event.target().expect("Must have a target"); let se: &web_sys::HtmlSelectElement = target.unchecked_ref(); if se.selected_index() < 0 { self.controlled_select_index = None; } else { self.controlled_select_index = Some(se.selected_index() as usize); } } } #[wasm_bindgen_test] fn classes_and_conditional_classes() { let main: RcMain = simi_test::start_app(); let div = simi_test::Element::id("classes"); let classes = div.as_element().class_list(); assert_eq!(true, classes.contains("class1")); assert_eq!(true, classes.contains("class2")); assert_eq!(true, classes.contains("class3")); assert_eq!(false, classes.contains("toggle-class1")); assert_eq!(true, classes.contains("toggle-class2")); main.send_message(Msg::ToggleBoolValue); assert_eq!(true, classes.contains("class1")); assert_eq!(true, classes.contains("class2")); assert_eq!(true, classes.contains("class3")); assert_eq!(true, classes.contains("toggle-class1")); assert_eq!(false, classes.contains("toggle-class2")); } fn check_no_update() { let nu1 = simi_test::Element::id("no-update-count"); let nu2 = simi_test::Element::id("no-update-element"); assert_eq!( "Initial value of count: 2018", nu1.as_node().text_content().expect("div content") ); assert_eq!( "Initial value of count: 2018", nu2.as_node().text_content().expect("div content") ); } #[wasm_bindgen_test] fn content_and_no_update() { let main: RcMain = simi_test::start_app(); let div = simi_test::Element::id("count-value"); assert_eq!( "Count value: 2018", div.as_node().text_content().expect("div content") ); check_no_update(); main.send_message(Msg::Down); assert_eq!( "Count value: 2017", div.as_node().text_content().expect("div content") ); check_no_update(); main.send_message(Msg::Up); assert_eq!( "Count value: 2018", div.as_node().text_content().expect("div content") ); check_no_update(); let bup = simi_test::Element::id("button-count-up"); bup.click(); assert_eq!( "Count value: 2019", div.as_node().text_content().expect("div content") ); check_no_update(); let bdown = simi_test::Element::id("button-count-down"); bdown.click(); assert_eq!( "Count value: 2018", div.as_node().text_content().expect("div content") ); check_no_update(); } #[wasm_bindgen_test] fn input_checkbox() { let main: RcMain = simi_test::start_app(); let cb = simi_test::Element::id("checkbox"); assert_eq!(false, cb.as_input().checked()); cb.click(); assert_eq!(true, cb.as_input().checked()); main.send_message(Msg::ToggleBoolValue); assert_eq!(false, cb.as_input().checked()); } #[wasm_bindgen_test] fn input_text() { let _main: RcMain = simi_test::start_app(); let div = simi_test::Element::id("string-value"); let input = simi_test::Element::id("input-string-value"); assert_eq!("Simi", div.as_node().text_content().expect("div content")); assert_eq!("Simi", input.as_input().value()); input.change_input("Simi v0.2"); assert_eq!( "Simi v0.2", div.as_node().text_content().expect("div content") ); assert_eq!("Simi v0.2", input.as_input().value()); } #[wasm_bindgen_test] fn textarea() { let _main: RcMain = simi_test::start_app(); let div = simi_test::Element::id("string-value"); let ta = simi_test::Element::id("textarea"); assert_eq!("Simi", div.as_node().text_content().expect("div content")); assert_eq!("Simi", ta.as_textarea().value()); ta.change_textarea("Simi v0.2"); assert_eq!( "Simi v0.2", div.as_node().text_content().expect("div content") ); assert_eq!("Simi v0.2", ta.as_textarea().value()); } #[wasm_bindgen_test] fn custom_attributes() { let main: RcMain = simi_test::start_app(); let div = simi_test::Element::id("custom-attributes"); assert_eq!( Some("Limira".to_string()), div.as_element().get_attribute("data-user-name") ); assert_eq!( Some("0".to_string()), div.as_element().get_attribute("data-user-skill") ); assert_eq!( Some("Simi".to_string()), div.as_element().get_attribute("data-to-update") ); main.send_message(Msg::SetStringValue("Simi v0.2".to_string())); assert_eq!( Some("Simi v0.2".to_string()), div.as_element().get_attribute("data-to-update") ); } #[wasm_bindgen_test] fn checkboxes() { let _main: RcMain = simi_test::start_app(); let no_update = simi_test::Element::id("no-update-check"); let to_update = simi_test::Element::id("tracking-check"); // Test literal value let i = simi_test::Element::id("literal-check-true"); assert_eq!(true, i.as_input().checked()); let i = simi_test::Element::id("literal-check-false"); assert_eq!(false, i.as_input().checked()); // Initial values assert_eq!(true, to_update.as_input().checked()); assert_eq!(true, no_update.as_input().checked()); // Check off to_update.click(); assert_eq!(false, to_update.as_input().checked()); assert_eq!(true, no_update.as_input().checked()); // Check on to_update.click(); assert_eq!(true, to_update.as_input().checked()); assert_eq!(true, no_update.as_input().checked()); } #[wasm_bindgen_test] fn radios() { let _main: RcMain = simi_test::start_app(); let radio1 = simi_test::Element::id("radio1"); let radio2 = simi_test::Element::id("radio2"); let radio3 = simi_test::Element::id("radio3"); let radio4 = simi_test::Element::id("radio4"); assert_eq!(false, radio1.as_input().checked()); assert_eq!(false, radio2.as_input().checked()); assert_eq!(false, radio3.as_input().checked()); assert_eq!(false, radio4.as_input().checked()); // Select 'radio1' radio1.click(); assert_eq!(true, radio1.as_input().checked()); assert_eq!(false, radio2.as_input().checked()); assert_eq!(false, radio3.as_input().checked()); assert_eq!(false, radio4.as_input().checked()); // Select 'radio2' radio2.click(); assert_eq!(false, radio1.as_input().checked()); assert_eq!(true, radio2.as_input().checked()); assert_eq!(false, radio3.as_input().checked()); assert_eq!(false, radio4.as_input().checked()); } #[wasm_bindgen_test] fn select_value() { let _main: RcMain = simi_test::start_app(); let s = simi_test::Element::id("init-value-select"); assert_eq!("second", s.as_select().value()); assert_eq!(1, s.as_select().selected_index()); let s = simi_test::Element::id("controlled-by-value-select"); assert_eq!(6, s.as_select().size()); assert_eq!("", s.as_select().value()); assert_eq!(-1, s.as_select().selected_index()); let select = s; select.change_select("third"); assert_eq!("third", select.as_select().value()); assert_eq!(2, select.as_select().selected_index()); let o = simi_test::Element::id("controlled-by-value-select-option3"); assert_eq!(true, o.as_option().selected()); assert_eq!(2, o.as_option().index()); } #[wasm_bindgen_test] fn select_index() { let _main: RcMain = simi_test::start_app(); let s = simi_test::Element::id("init-index-select"); assert_eq!("second", s.as_select().value()); assert_eq!(1, s.as_select().selected_index()); let s = simi_test::Element::id("controlled-by-index-select"); assert_eq!("", s.as_select().value()); assert_eq!(-1, s.as_select().selected_index()); let select = s; select.change_index(0); assert_eq!("first", select.as_select().value()); assert_eq!(0, select.as_select().selected_index()); let o = simi_test::Element::id("controlled-by-index-select-option1"); assert_eq!(true, o.as_option().selected()); assert_eq!(0, o.as_option().index()); select.change_index(2); assert_eq!("third", select.as_select().value()); assert_eq!(2, select.as_select().selected_index()); let o = simi_test::Element::id("controlled-by-index-select-option3"); assert_eq!(true, o.as_option().selected()); assert_eq!(2, o.as_option().index()); }