forked from yewstack/yew
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhash_router.rs
145 lines (120 loc) · 3.65 KB
/
hash_router.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
use std::time::Duration;
use serde::{Deserialize, Serialize};
use wasm_bindgen_test::{wasm_bindgen_test as test, wasm_bindgen_test_configure};
use yew::functional::function_component;
use yew::platform::time::sleep;
use yew::prelude::*;
use yew_router::prelude::*;
mod utils;
use utils::*;
wasm_bindgen_test_configure!(run_in_browser);
#[derive(Serialize, Deserialize)]
struct Query {
foo: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Routable)]
enum Routes {
#[at("/")]
Home,
#[at("/no/:id")]
No { id: u32 },
#[at("/404")]
NotFound,
}
#[derive(Properties, PartialEq, Clone)]
struct NoProps {
id: u32,
}
#[function_component(No)]
fn no(props: &NoProps) -> Html {
let route = props.id.to_string();
let location = use_location().unwrap();
html! {
<>
<div id="result-params">{ route }</div>
<div id="result-query">{ location.query::<Query>().unwrap().foo }</div>
</>
}
}
#[function_component(Comp)]
fn component() -> Html {
let navigator = use_navigator().unwrap();
let switch = move |routes| {
let navigator_clone = navigator.clone();
let replace_route = Callback::from(move |_| {
navigator_clone
.replace_with_query(
&Routes::No { id: 2 },
&Query {
foo: "bar".to_string(),
},
)
.unwrap();
});
let navigator_clone = navigator.clone();
let push_route = Callback::from(move |_| {
navigator_clone
.push_with_query(
&Routes::No { id: 3 },
&Query {
foo: "baz".to_string(),
},
)
.unwrap();
});
match routes {
Routes::Home => html! {
<>
<div id="result">{"Home"}</div>
<button onclick={replace_route}>{"replace a route"}</button>
</>
},
Routes::No { id } => html! {
<>
<No id={id} />
<button onclick={push_route}>{"push a route"}</button>
</>
},
Routes::NotFound => html! { <div id="result">{"404"}</div> },
}
};
html! {
<Switch<Routes> render={switch} />
}
}
#[function_component(Root)]
fn root() -> Html {
html! {
<HashRouter>
<Comp />
</HashRouter>
}
}
// all the tests are in place because document state isn't being reset between tests
// different routes at the time of execution are set and it causes weird behavior (tests
// failing randomly)
// this test tests
// - routing
// - parameters in the path
// - query parameters
// - 404 redirects
#[test]
async fn router_works() {
yew::Renderer::<Root>::with_root(gloo::utils::document().get_element_by_id("output").unwrap())
.render();
sleep(Duration::ZERO).await;
assert_eq!("Home", obtain_result_by_id("result"));
sleep(Duration::ZERO).await;
let initial_length = history_length();
sleep(Duration::ZERO).await;
click("button"); // replacing the current route
sleep(Duration::ZERO).await;
assert_eq!("2", obtain_result_by_id("result-params"));
assert_eq!("bar", obtain_result_by_id("result-query"));
assert_eq!(initial_length, history_length());
click("button"); // pushing a new route
sleep(Duration::ZERO).await;
assert_eq!("3", obtain_result_by_id("result-params"));
assert_eq!("baz", obtain_result_by_id("result-query"));
assert_eq!(initial_length + 1, history_length());
}