freya_testing/lib.rs
1//! # Testing
2//!
3//! `freya-testing` is a headless renderer for freya components, which means you can simulate a graphical environment
4//! with no need to actually draw anything, a perfect fit for testing.
5//!
6//! First you would need to use [launch_test](crate::prelude::launch_test) or [launch_test_with_config](crate::prelude::launch_test_with_config) and pass the component you want to test.
7//!
8//! This will return you a [TestingHandler](crate::prelude::TestingHandler) with a set of utilities.
9//!
10//! Also, I recommend using [tokio::test] to wrap your async tests.
11//!
12//! ## Stateless example
13//!
14//! Simply asserts that the component renders a label with the text `"Hello World!"`.
15//!
16//! ```rust, no_run
17//! # use freya::prelude::*;
18//! # use freya_testing::prelude::*;
19//! # async fn test() {
20//! fn our_component() -> Element {
21//! rsx!(
22//! label {
23//! "Hello World!"
24//! }
25//! )
26//! }
27//!
28//! let mut utils = launch_test(our_component);
29//!
30//! let root = utils.root(); // Get the root element of your app
31//! let label = root.get(0); // Get the children of the root in the index 0
32//! let label_text = label.get(0);
33//!
34//! assert_eq!(label_text.text(), Some("Hello World!"));
35//! # }
36//! ```
37//!
38//! ## Stateful example
39//!
40//! If the component has logic that might execute asynchronously, you need to wait for the component
41//! to update using the `wait_for_update` function before asserting the result.
42//!
43//! Here, the component has a state that is `false` by default, but once mounted, it updates the state to `true`.
44//!
45//! ```rust, no_run
46//! # use freya::prelude::*;
47//! # use freya_testing::prelude::*;
48//! # async fn dynamic_test() {
49//! fn dynamic_component() -> Element {
50//! let mut state = use_signal(|| false);
51//!
52//! use_hook(move || {
53//! state.set(true);
54//! });
55//!
56//! rsx!(
57//! label {
58//! "Is enabled? {state}"
59//! }
60//! )
61//! }
62//!
63//! let mut utils = launch_test(dynamic_component);
64//!
65//! let root = utils.root();
66//! let label = root.get(0);
67//!
68//! assert_eq!(label.get(0).text(), Some("Is enabled? false"));
69//!
70//! // This will poll the VirtualDOM and apply the new changes
71//! utils.wait_for_update().await;
72//!
73//! assert_eq!(label.get(0).text(), Some("Is enabled? true"));
74//! # }
75//! ```
76//!
77//! ## Events example
78//!
79//! You can simulate events on the component, for example, simulate a click event on a `rect` and assert that the state was updated.
80//!
81//! ```rust, no_run
82//! # use freya::prelude::*;
83//! # use freya_testing::prelude::*;
84//! # async fn event_test() {
85//! fn event_component() -> Element {
86//! let mut enabled = use_signal(|| false);
87//!
88//! rsx!(
89//! rect {
90//! width: "100%",
91//! height: "100%",
92//! background: "red",
93//! onclick: move |_| {
94//! enabled.set(true);
95//! },
96//! label {
97//! "Is enabled? {enabled}"
98//! }
99//! }
100//! )
101//! }
102//!
103//! let mut utils = launch_test(event_component);
104//!
105//! let rect = utils.root().get(0);
106//! let label = rect.get(0);
107//!
108//! utils.wait_for_update().await;
109//!
110//! let text = label.get(0);
111//! assert_eq!(text.text(), Some("Is enabled? false"));
112//!
113//! // Push a click event to the events queue
114//! utils.push_event(TestEvent::Mouse {
115//! name: EventName::Click,
116//! cursor: (5.0, 5.0).into(),
117//! button: Some(MouseButton::Left),
118//! });
119//!
120//! // Poll the VirtualDOM with the new events
121//! utils.wait_for_update().await;
122//!
123//! // Because the click event was sent, and the state updated, the text was changed as well!
124//! let text = label.get(0);
125//! assert_eq!(text.text(), Some("Is enabled? true"));
126//! # }
127//! ```
128//!
129//! ## Configuration example
130//!
131//! The `launch_test` comes with a default configuration, but you can pass your own config with the `launch_test_with_config` function.
132//!
133//! Here is an example of how to can set our custom window size:
134//!
135//! ```rust, no_run
136//! # use freya::prelude::*;
137//! # use freya_testing::prelude::*;
138//! # async fn test() {
139//! fn our_component() -> Element {
140//! rsx!(
141//! label {
142//! "Hello World!"
143//! }
144//! )
145//! }
146//!
147//! let mut utils = launch_test_with_config(
148//! our_component,
149//! TestingConfig::<()> {
150//! size: (500.0, 800.0).into(),
151//! ..TestingConfig::default()
152//! },
153//! );
154//!
155//! let root = utils.root();
156//! let label = root.get(0);
157//! let label_text = label.get(0);
158//!
159//! assert_eq!(label_text.text(), Some("Hello World!"));
160//! # }
161//! ````
162
163pub mod config;
164pub mod event;
165pub mod launch;
166pub mod test_handler;
167pub mod test_node;
168pub mod test_utils;
169
170const SCALE_FACTOR: f64 = 1.0;
171
172pub mod prelude {
173 pub use freya_core::{
174 accessibility::*,
175 custom_attributes::*,
176 events::*,
177 parsing::*,
178 platform::*,
179 states::*,
180 values::*,
181 };
182
183 pub use crate::{
184 config::*,
185 event::*,
186 launch::*,
187 test_handler::*,
188 test_node::*,
189 test_utils::*,
190 };
191}