wal_core/router/
builder.rs1use super::{not_found_component::NotFoundComponent, PageRenderer, Router};
2use crate::{
3 component::{node::AnyComponentNode, Component},
4 virtual_dom::dom,
5};
6use std::collections::HashMap;
7
8pub struct RouterBuilder {
10 pages: HashMap<&'static str, PageRenderer>,
11 not_found_page: Option<PageRenderer>,
12}
13
14impl Default for RouterBuilder {
15 fn default() -> Self {
17 RouterBuilder {
18 pages: HashMap::new(),
19 not_found_page: None,
20 }
21 }
22}
23
24impl RouterBuilder {
25 pub fn add_page<C>(mut self, path: &'static str) -> RouterBuilder
27 where
28 C: Component + Default + 'static,
29 {
30 let mut pages = self.pages;
31 pages.insert(
32 path,
33 PageRenderer::new(|| {
34 AnyComponentNode::new_root_routing(C::default(), dom::get_root_element())
35 }),
36 );
37 self.pages = pages;
38
39 self
44 }
45
46 pub fn add_not_found_page<C>(self) -> RouterBuilder
50 where
51 C: Component + Default + 'static,
52 {
53 RouterBuilder {
54 pages: self.pages,
55 not_found_page: Some(PageRenderer::new(|| {
56 AnyComponentNode::new_root_routing(C::default(), dom::get_root_element())
57 })),
58 }
59 }
60}
61
62impl RouterBuilder {
63 pub fn build(self) -> Router {
65 if let Some(not_found_page) = self.not_found_page {
66 Router::new(self.pages, not_found_page)
67 } else {
68 Router::new(
69 self.pages,
70 PageRenderer::new(|| {
71 AnyComponentNode::new_root_routing(NotFoundComponent, dom::get_root_element())
72 }),
73 )
74 }
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 use super::RouterBuilder;
81 use crate::{
82 component::{behavior::Behavior, Component},
83 virtual_dom::{VNode, VText},
84 };
85 use wasm_bindgen_test::wasm_bindgen_test;
86 wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
87
88 const VALID_TEXT: &str = "";
89
90 #[wasm_bindgen_test]
91 fn invalid() {
92 let invalid = RouterBuilder::default();
93 assert!(invalid.not_found_page.is_none());
94 }
95
96 struct Root;
97 impl Default for Root {
98 fn default() -> Self {
99 Self::new(())
100 }
101 }
102 impl Component for Root {
103 type Message = ();
104 type Properties = ();
105 fn new(_props: Self::Properties) -> Self {
106 Root
107 }
108 fn view(&self, _behavior: &mut impl Behavior<Self>) -> VNode {
109 VText::new(VALID_TEXT).into()
110 }
111 fn update(&mut self, _message: Self::Message) -> bool {
112 false
113 }
114 }
115
116 #[wasm_bindgen_test]
117 fn valid_one_page() {
118 let valid = RouterBuilder::default().add_page::<Root>("/");
119 assert!(valid.pages.contains_key("/"));
120 assert_eq!(valid.pages.len(), 1);
121 assert!(valid.not_found_page.is_none());
122 }
123
124 struct Root2;
125 impl Default for Root2 {
126 fn default() -> Self {
127 Self::new(())
128 }
129 }
130 impl Component for Root2 {
131 type Message = ();
132 type Properties = ();
133 fn new(_props: Self::Properties) -> Self {
134 Root2
135 }
136 fn view(&self, _behavior: &mut impl Behavior<Self>) -> VNode {
137 VText::new(VALID_TEXT).into()
138 }
139 fn update(&mut self, _message: Self::Message) -> bool {
140 false
141 }
142 }
143
144 #[wasm_bindgen_test]
145 fn valid_multiple_pages() {
146 let valid = RouterBuilder::default()
147 .add_page::<Root>("/")
148 .add_page::<Root2>("/2");
149 assert!(valid.pages.contains_key("/"));
150 assert!(valid.pages.contains_key("/2"));
151 assert_eq!(valid.pages.len(), 2);
152 assert!(valid.not_found_page.is_none());
153 }
154
155 #[wasm_bindgen_test]
156 fn build_valid_multiple_pages() {
157 let valid = RouterBuilder::default()
158 .add_page::<Root>("/")
159 .add_page::<Root2>("/2");
160 assert!(valid.pages.contains_key("/"));
161 assert!(valid.pages.contains_key("/2"));
162 assert_eq!(valid.pages.len(), 2);
163 assert!(valid.not_found_page.is_none());
164
165 let router = valid.build();
166 assert!(router.pages.contains_key("/"));
167 assert!(router.pages.contains_key("/2"));
168 assert_eq!(router.pages.len(), 2);
169 assert!(router.current.is_none());
170 }
171
172 #[wasm_bindgen_test]
173 fn build_valid_custom_not_found_page() {
174 let valid = RouterBuilder::default().add_not_found_page::<Root>();
175 assert_eq!(valid.pages.len(), 0);
176 assert!(valid.not_found_page.is_some());
177
178 let router = valid.build();
179 assert_eq!(router.pages.len(), 0);
180 assert!(router.current.is_none());
181 }
182
183 #[wasm_bindgen_test]
184 fn build_valid_default_not_found_page() {
185 let path = "/";
186 let valid = RouterBuilder::default().add_page::<Root>(path);
187 assert!(valid.pages.contains_key(path));
188 assert_eq!(valid.pages.len(), 1);
189 assert!(valid.not_found_page.is_none());
190
191 let router = valid.build();
192 assert!(router.pages.contains_key(path));
193 assert_eq!(router.pages.len(), 1);
194 assert!(router.current.is_none());
195 }
196
197 #[wasm_bindgen_test]
198 fn build() {
199 let valid = RouterBuilder::default()
200 .add_page::<Root>("/")
201 .add_page::<Root2>("/2")
202 .build();
203
204 assert_eq!(valid.pages.len(), 2);
205 assert!(valid.pages.contains_key("/"));
206 assert!(valid.pages.contains_key("/2"));
207 assert!(valid.current.is_none());
208 }
209}