use crate::styles::{get_palette, get_size, get_style, Palette, Size, Style};
use stylist::{css, StyleSource};
use wasm_bindgen_test::*;
use web_sys::window;
use yew::prelude::*;
use yew::{utils, App};
pub struct Button {
link: ComponentLink<Self>,
props: ButtonProps,
}
#[derive(PartialEq)]
struct ButtonProps {
button_palette: String,
button_size: String,
button_style: String,
class_name: String,
id: String,
key: String,
code_ref: NodeRef,
onclick_signal: Callback<MouseEvent>,
styles: StyleSource<'static>,
children: Children,
}
impl From<Props> for ButtonProps {
fn from(props: Props) -> Self {
ButtonProps {
button_palette: get_palette(props.button_palette),
button_size: get_size(props.button_size),
button_style: get_style(props.button_style),
class_name: props.class_name,
id: props.id,
key: props.key,
code_ref: props.code_ref,
onclick_signal: props.onclick_signal,
styles: props.styles,
children: props.children,
}
}
}
#[derive(Clone, Properties, PartialEq)]
pub struct Props {
#[prop_or(Palette::Standard)]
pub button_palette: Palette,
#[prop_or_default]
pub class_name: String,
#[prop_or_default]
pub id: String,
#[prop_or_default]
pub code_ref: NodeRef,
#[prop_or_default]
pub key: String,
#[prop_or(Size::Medium)]
pub button_size: Size,
#[prop_or(Style::Regular)]
pub button_style: Style,
pub onclick_signal: Callback<MouseEvent>,
#[prop_or(css!(""))]
pub styles: StyleSource<'static>,
pub children: Children,
}
pub enum Msg {
Clicked(MouseEvent),
}
impl Component for Button {
type Message = Msg;
type Properties = Props;
fn create(props: Self::Properties, link: ComponentLink<Self>) -> Self {
Self {
link,
props: ButtonProps::from(props),
}
}
fn update(&mut self, msg: Self::Message) -> ShouldRender {
match msg {
Msg::Clicked(mouse_event) => {
self.props.onclick_signal.emit(mouse_event);
}
};
true
}
fn change(&mut self, props: Self::Properties) -> ShouldRender {
let prop_mapped = ButtonProps::from(props);
if self.props != prop_mapped {
self.props = prop_mapped;
return true;
}
true
}
fn view(&self) -> Html {
html! {
<button
onclick=self.link.callback(Msg::Clicked)
class=classes!("button",
self.props.button_palette.clone(),
self.props.button_size.clone(),
self.props.button_style.clone(),
self.props.class_name.clone(),
self.props.styles.clone(),
)
key=self.props.key.clone()
ref=self.props.code_ref.clone()
id=self.props.id.clone()
> { self.props.children.clone() }
</button>
}
}
}
wasm_bindgen_test_configure!(run_in_browser);
#[wasm_bindgen_test]
fn should_trigger_action_when_button_clicked() {
let body = window().unwrap().document().unwrap().body().unwrap();
let element = window()
.unwrap()
.document()
.unwrap()
.create_element("div")
.unwrap();
element.set_text_content(Some("home"));
element.set_id("menu");
body.append_child(&element).unwrap();
let onchange_name = Callback::from(|_| {
let content = window()
.unwrap()
.document()
.unwrap()
.get_element_by_id("menu")
.unwrap();
content.set_text_content(Some("about"));
});
let props = Props {
class_name: String::from("test-button"),
id: String::from("button-id-test"),
key: "".to_string(),
code_ref: NodeRef::default(),
button_size: Size::Medium,
button_style: Style::Regular,
onclick_signal: onchange_name,
button_palette: Palette::Standard,
styles: css!("background-color: #918d94;"),
children: Children::new(vec![html! {<div id="submenu">{"another menu"}</div>}]),
};
let mouse_event = MouseEvent::new("click").unwrap();
props.onclick_signal.emit(mouse_event);
let updated_content = window()
.unwrap()
.document()
.unwrap()
.get_element_by_id("menu")
.unwrap()
.text_content()
.unwrap();
assert_eq!(updated_content, String::from("about"));
}
#[wasm_bindgen_test]
fn should_create_button_component() {
let props = Props {
class_name: String::from("test-button"),
id: String::from("button-id-test"),
key: "".to_string(),
code_ref: NodeRef::default(),
button_size: Size::Medium,
button_style: Style::Regular,
onclick_signal: Callback::noop(),
button_palette: Palette::Standard,
styles: css!("background-color: #918d94;"),
children: Children::new(vec![html! {<div id="result">{"result"}</div>}]),
};
let button: App<Button> = App::new();
button.mount_with_props(
utils::document().get_element_by_id("output").unwrap(),
props,
);
let button_element = utils::document()
.get_elements_by_tag_name("button")
.get_with_index(0)
.unwrap();
let child = button_element.first_element_child().unwrap();
assert_eq!(button_element.tag_name(), "BUTTON");
assert_eq!(child.id(), "result");
}