13 releases (7 stable)

1.3.0 Nov 18, 2024
1.2.1 Oct 17, 2024
0.1.4 Sep 18, 2024
0.1.2 Aug 31, 2024

#230 in Web programming

Download history 394/week @ 2024-08-30 21/week @ 2024-09-06 107/week @ 2024-09-13 58/week @ 2024-09-20 102/week @ 2024-09-27 214/week @ 2024-10-04 597/week @ 2024-10-11 91/week @ 2024-10-18 15/week @ 2024-10-25 17/week @ 2024-11-01 6/week @ 2024-11-08 261/week @ 2024-11-15 61/week @ 2024-11-22 33/week @ 2024-11-29 67/week @ 2024-12-06

423 downloads per month
Used in 6 crates

MIT/Apache

105KB
2.5K SLoC

Yewlish Testing Tools

crates.io docs.rs License: MIT OR Apache-2.0

Yewlish Testing Tools is a set of utilities designed to simplify testing components and hooks in the Yew framework. It provides a fluent API for querying, interacting with, and extracting information from rendered Yew components, making it easier to write and maintain tests for Yew applications.

Features

  • Component Rendering: Easily render Yew components or custom hooks with using the render! macro.
  • Querying: Query elements by role, text, and custom test IDs.
  • Events: Simulate user interactions such as clicks and key presses.
  • Attribute and Text Extraction: Extract attributes and text content from elements.

Installation

To use Yewlish Testing Tools in your project, add the following to your Cargo.toml:

[dev-dependencies]
yewlish-testing-tools = "1.2.1"

Prerequisites

Ensure that your project is set up to run tests in a browser environment, as this library is designed for testing web components.

Usage

Basic Example

Here’s a simple example of how to use Yewlish Testing Tools to render and test a Yew component:

use yew::prelude::*;
use yewlish_testing_tools::{render, Query};

#[derive(Properties, Clone, PartialEq)]
struct Props {
    text: &'static str,
}

#[function_component(TestComponent)]
fn test_component(props: &Props) -> Html {
    html! { <div>{ props.text }</div> }
}

#[cfg(test)]
mod tests {
    use super::*;
    use wasm_bindgen_test::*;

    wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);

    #[wasm_bindgen_test]
    async fn test_render() {
        let t = render!({
            html! {
                <TestComponent text="Hello, World!" />
            }
        })
        .await;

        assert!(t.query_by_text("Hello, World!").exists());
    }
}

Component Testing

You can test Yew components using the render! macro:

#[cfg(test)]
mod tests {
    use crate::{render, Query, TesterEvent};
    use wasm_bindgen_test::*;
    use yew::prelude::*;

    wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);

    #[wasm_bindgen_test]
    async fn test_render() {
        let t = render!({
            let counter = use_state(|| 0);

            let increment = use_callback(counter.clone(), |_event: MouseEvent, counter| {
                counter.set(**counter + 1);
            });

            use_remember_value(counter.clone());

            html! {
                <button onclick={&increment}>{"Click me "}{*counter}</button>
            }
        })
        .await;

        assert_eq!(*t.get_remembered_value::<UseStateHandle<i32>>(), 0);

        let button = t.query_by_role("button");
        assert!(button.exists());
        assert!(button.text().contains("Click me 0"));

        let button = button.click().await;
        assert!(button.text().contains("Click me 1"));

        assert_eq!(*t.get_remembered_value::<UseStateHandle<i32>>(), 1);
    }
}

Hook Testing

You can test custom hooks using the render_hook! macro:

#[cfg(test)]
mod tests {
    use crate::{render, Extractor, Query, TesterEvent};
    use wasm_bindgen_test::*;
    use yew::prelude::*;

    wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);

    #[wasm_bindgen_test]
    async fn test_render_with_state() {
        let t = render!({
            let state = use_state(|| true);
            use_remember_value(state);

            html! {}
        })
        .await;

        assert!(*t.get_remembered_value::<UseStateHandle<bool>>());
    }

    #[wasm_bindgen_test]
    async fn test_render_with_effect() {
        let t = render!({
            let state = use_state(|| 0);

            {
                let state = state.clone();

                use_effect_with((), move |_| {
                    state.set(100);
                });
            }

            use_remember_value(state.clone());

            html! {}
        })
        .await;

        assert_eq!(*t.get_remembered_value::<UseStateHandle<i32>>(), 100);
    }

    #[wasm_bindgen_test]
    async fn test_render_with_reducer() {
        #[derive(Clone, PartialEq)]
        struct Counter {
            count: i32,
        }

        enum CounterAction {
            Increment,
            Decrement,
        }

        impl Reducible for Counter {
            type Action = CounterAction;

            fn reduce(self: Rc<Self>, action: Self::Action) -> Rc<Self> {
                match action {
                    CounterAction::Increment => Self {
                        count: self.count + 1,
                    }
                    .into(),
                    CounterAction::Decrement => Self {
                        count: self.count - 1,
                    }
                    .into(),
                }
            }
        }

        let t = render!({
            let state = use_reducer(|| Counter { count: 0 });
            use_remember_value(state.clone());

            html! {}
        })
        .await;

        assert_eq!(t.get_remembered_value::<UseReducerHandle<Counter>>().count, 0);

        t.act(|| {
            t.get_remembered_value::<UseReducerHandle<Counter>>()
                .dispatch(CounterAction::Increment);
        })
        .await;

        assert_eq!(t.get_remembered_value::<UseReducerHandle<Counter>>().count, 1);

        t.act(|| {
            t.get_remembered_value::<UseReducerHandle<Counter>>()
                .dispatch(CounterAction::Decrement);
        })
        .await;

        assert_eq!(t.get_remembered_value::<UseReducerHandle<Counter>>().count, 0);
    }
}

Documentation

The full documentation for Yewlish Testing Tools is available on docs.rs. It includes detailed examples and API references to help you get the most out of this library.

Contributing

Contributions are welcome! If you encounter any issues or have suggestions for improvements, please open an issue or submit a pull request on GitHub.

License

Yewlish Testing Tools is dual-licensed under the MIT and Apache 2.0 licenses. You may choose to use either license at your option.

Acknowledgements

This project is inspired by the need for robust testing tools in the Yew ecosystem and is influenced by the principles of the testing-library from the JavaScript world. Special thanks to the Yew community for their continued support and contributions to the framework.

Contact

For any questions or inquiries, feel free to reach out to the author:

Kirill Korotkov Email: personal.gugfug@gmail.com

Dependencies

~12–21MB
~291K SLoC