1 | module vweb |
2 | |
3 | struct RoutePair { |
4 | url string |
5 | route string |
6 | } |
7 | |
8 | fn (rp RoutePair) test() ?[]string { |
9 | url := rp.url.split('/').filter(it != '') |
10 | route := rp.route.split('/').filter(it != '') |
11 | return route_matches(url, route) |
12 | } |
13 | |
14 | fn (rp RoutePair) test_match() { |
15 | rp.test() or { panic('should match: ${rp}') } |
16 | } |
17 | |
18 | fn (rp RoutePair) test_no_match() { |
19 | rp.test() or { return } |
20 | panic('should not match: ${rp}') |
21 | } |
22 | |
23 | fn (rp RoutePair) test_param(expected []string) { |
24 | res := rp.test() or { panic('should match: ${rp}') } |
25 | assert res == expected |
26 | } |
27 | |
28 | fn test_route_no_match() { |
29 | tests := [ |
30 | RoutePair{ |
31 | url: '/a' |
32 | route: '/a/b/c' |
33 | }, |
34 | RoutePair{ |
35 | url: '/a/' |
36 | route: '/a/b/c' |
37 | }, |
38 | RoutePair{ |
39 | url: '/a/b' |
40 | route: '/a/b/c' |
41 | }, |
42 | RoutePair{ |
43 | url: '/a/b/' |
44 | route: '/a/b/c' |
45 | }, |
46 | RoutePair{ |
47 | url: '/a/c/b' |
48 | route: '/a/b/c' |
49 | }, |
50 | RoutePair{ |
51 | url: '/a/c/b/' |
52 | route: '/a/b/c' |
53 | }, |
54 | RoutePair{ |
55 | url: '/a/b/c/d' |
56 | route: '/a/b/c' |
57 | }, |
58 | RoutePair{ |
59 | url: '/a/b/c' |
60 | route: '/' |
61 | }, |
62 | ] |
63 | for test in tests { |
64 | test.test_no_match() |
65 | } |
66 | } |
67 | |
68 | fn test_route_exact_match() { |
69 | tests := [ |
70 | RoutePair{ |
71 | url: '/a/b/c' |
72 | route: '/a/b/c' |
73 | }, |
74 | RoutePair{ |
75 | url: '/a/b/c/' |
76 | route: '/a/b/c' |
77 | }, |
78 | RoutePair{ |
79 | url: '/a' |
80 | route: '/a' |
81 | }, |
82 | RoutePair{ |
83 | url: '/' |
84 | route: '/' |
85 | }, |
86 | ] |
87 | for test in tests { |
88 | test.test_match() |
89 | } |
90 | } |
91 | |
92 | fn test_route_params_match() { |
93 | RoutePair{ |
94 | url: '/a/b/c' |
95 | route: '/:a/b/c' |
96 | }.test_match() |
97 | |
98 | RoutePair{ |
99 | url: '/a/b/c' |
100 | route: '/a/:b/c' |
101 | }.test_match() |
102 | |
103 | RoutePair{ |
104 | url: '/a/b/c' |
105 | route: '/a/b/:c' |
106 | }.test_match() |
107 | |
108 | RoutePair{ |
109 | url: '/a/b/c' |
110 | route: '/:a/b/:c' |
111 | }.test_match() |
112 | |
113 | RoutePair{ |
114 | url: '/a/b/c' |
115 | route: '/:a/:b/:c' |
116 | }.test_match() |
117 | |
118 | RoutePair{ |
119 | url: '/one/two/three' |
120 | route: '/:a/:b/:c' |
121 | }.test_match() |
122 | |
123 | RoutePair{ |
124 | url: '/one/b/c' |
125 | route: '/:a/b/c' |
126 | }.test_match() |
127 | |
128 | RoutePair{ |
129 | url: '/one/two/three' |
130 | route: '/:a/b/c' |
131 | }.test_no_match() |
132 | |
133 | RoutePair{ |
134 | url: '/one/two/three' |
135 | route: '/:a/:b/c' |
136 | }.test_no_match() |
137 | |
138 | RoutePair{ |
139 | url: '/one/two/three' |
140 | route: '/:a/b/:c' |
141 | }.test_no_match() |
142 | |
143 | RoutePair{ |
144 | url: '/a/b/c/d' |
145 | route: '/:a/:b/:c' |
146 | }.test_no_match() |
147 | |
148 | RoutePair{ |
149 | url: '/1/2/3/4' |
150 | route: '/:a/:b/:c' |
151 | }.test_no_match() |
152 | |
153 | RoutePair{ |
154 | url: '/a/b' |
155 | route: '/:a/:b/:c' |
156 | }.test_no_match() |
157 | |
158 | RoutePair{ |
159 | url: '/1/2' |
160 | route: '/:a/:b/:c' |
161 | }.test_no_match() |
162 | } |
163 | |
164 | fn test_route_params() { |
165 | RoutePair{ |
166 | url: '/a/b/c' |
167 | route: '/:a/b/c' |
168 | }.test_param(['a']) |
169 | |
170 | RoutePair{ |
171 | url: '/one/b/c' |
172 | route: '/:a/b/c' |
173 | }.test_param(['one']) |
174 | |
175 | RoutePair{ |
176 | url: '/one/two/c' |
177 | route: '/:a/:b/c' |
178 | }.test_param(['one', 'two']) |
179 | |
180 | RoutePair{ |
181 | url: '/one/two/three' |
182 | route: '/:a/:b/:c' |
183 | }.test_param(['one', 'two', 'three']) |
184 | |
185 | RoutePair{ |
186 | url: '/one/b/three' |
187 | route: '/:a/b/:c' |
188 | }.test_param(['one', 'three']) |
189 | } |
190 | |
191 | fn test_route_params_array_match() { |
192 | // array can only be used on the last word (TODO: add parsing / tests to ensure this) |
193 | |
194 | RoutePair{ |
195 | url: '/a/b/c' |
196 | route: '/a/b/:c...' |
197 | }.test_match() |
198 | |
199 | RoutePair{ |
200 | url: '/a/b/c/d' |
201 | route: '/a/b/:c...' |
202 | }.test_match() |
203 | |
204 | RoutePair{ |
205 | url: '/a/b/c/d/e' |
206 | route: '/a/b/:c...' |
207 | }.test_match() |
208 | |
209 | RoutePair{ |
210 | url: '/one/b/c/d/e' |
211 | route: '/:a/b/:c...' |
212 | }.test_match() |
213 | |
214 | RoutePair{ |
215 | url: '/one/two/c/d/e' |
216 | route: '/:a/:b/:c...' |
217 | }.test_match() |
218 | |
219 | RoutePair{ |
220 | url: '/one/two/three/four/five' |
221 | route: '/:a/:b/:c...' |
222 | }.test_match() |
223 | |
224 | RoutePair{ |
225 | url: '/a/b' |
226 | route: '/:a/:b/:c...' |
227 | }.test_no_match() |
228 | |
229 | RoutePair{ |
230 | url: '/a/b/' |
231 | route: '/:a/:b/:c...' |
232 | }.test_no_match() |
233 | } |
234 | |
235 | fn test_route_params_array() { |
236 | RoutePair{ |
237 | url: '/a/b/c' |
238 | route: '/a/b/:c...' |
239 | }.test_param(['c']) |
240 | |
241 | RoutePair{ |
242 | url: '/a/b/c/d' |
243 | route: '/a/b/:c...' |
244 | }.test_param(['c/d']) |
245 | |
246 | RoutePair{ |
247 | url: '/a/b/c/d/' |
248 | route: '/a/b/:c...' |
249 | }.test_param(['c/d']) |
250 | |
251 | RoutePair{ |
252 | url: '/a/b/c/d/e' |
253 | route: '/a/b/:c...' |
254 | }.test_param(['c/d/e']) |
255 | |
256 | RoutePair{ |
257 | url: '/one/b/c/d/e' |
258 | route: '/:a/b/:c...' |
259 | }.test_param(['one', 'c/d/e']) |
260 | |
261 | RoutePair{ |
262 | url: '/one/two/c/d/e' |
263 | route: '/:a/:b/:c...' |
264 | }.test_param(['one', 'two', 'c/d/e']) |
265 | |
266 | RoutePair{ |
267 | url: '/one/two/three/d/e' |
268 | route: '/:a/:b/:c...' |
269 | }.test_param(['one', 'two', 'three/d/e']) |
270 | } |
271 | |
272 | fn test_route_index_path() { |
273 | RoutePair{ |
274 | url: '/' |
275 | route: '/:path...' |
276 | }.test_param(['/']) |
277 | |
278 | RoutePair{ |
279 | url: '/foo/bar' |
280 | route: '/:path...' |
281 | }.test_param(['/foo/bar']) |
282 | } |