# Yewlish Testing Tools
[![crates.io](https://img.shields.io/crates/v/yewlish-testing-tools.svg)](https://crates.io/crates/yewlish-testing-tools)
[![docs.rs](https://docs.rs/yewlish-testing-tools/badge.svg)](https://docs.rs/yewlish-testing-tools)
[![License: MIT OR Apache-2.0](https://img.shields.io/crates/l/yewlish-testing-tools.svg)](https://opensource.org/licenses/MIT)
**Yewlish Testing Tools** is a set of utilities designed to simplify testing components and hooks in the [Yew](https://yew.rs) 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`:
```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:
```rust
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! {
{ props.text }
}
}
#[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! {
}
})
.await;
assert!(t.query_by_text("Hello, World!").exists());
}
}
```
### Component Testing
You can test Yew components using the render! macro:
```rust
#[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! {
}
})
.await;
assert_eq!(*t.get_remembered_value::>(), 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::>(), 1);
}
}
```
### Hook Testing
You can test custom hooks using the render_hook! macro:
```rust
#[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::>());
}
#[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::>(), 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, action: Self::Action) -> Rc {
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::>().count, 0);
t.act(|| {
t.get_remembered_value::>()
.dispatch(CounterAction::Increment);
})
.await;
assert_eq!(t.get_remembered_value::>().count, 1);
t.act(|| {
t.get_remembered_value::>()
.dispatch(CounterAction::Decrement);
})
.await;
assert_eq!(t.get_remembered_value::>().count, 0);
}
}
```
## Documentation
The full documentation for Yewlish Testing Tools is available on [docs.rs](https://docs.rs/yewlish-testing-tools). 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](https://github.com/patchwork-body/yewlish).
## 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](https://testing-library.com) 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](mailto:personal.gugfug@gmail.com)