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}