1use crate::assert_js;
2
3#[test]
4fn case_on_error() {
5 assert_js!(
6 r#"
7fn a_result() { Error(1) }
8
9pub fn main() {
10 case a_result() {
11 Error(_) -> 1
12 _ -> 2
13 }
14}"#
15 );
16}
17
18#[test]
19fn tuple_and_guard() {
20 assert_js!(
21 r#"
22pub fn go(x) {
23 case #(1, 2) {
24 #(1, a) if a == 2 -> 1
25 #(_, _) -> 2
26 }
27}
28"#,
29 )
30}
31
32#[test]
33fn guard_variable_only_brought_into_scope_when_needed() {
34 assert_js!(
35 r#"
36pub fn go(x) {
37 case x {
38 // We want `a` to be defined before the guard check, and
39 // `b` to be defined only if the predicate on a matches!
40 [a, b] if a == 1 -> a + b
41 _ -> 2
42 }
43}
44"#
45 )
46}
47
48// https://github.com/gleam-lang/gleam/issues/4221
49#[test]
50fn guard_variable_only_brought_into_scope_when_needed_1() {
51 assert_js!(
52 r#"
53pub fn main() {
54 case 1 {
55 i if i == 1 -> True
56 i if i < 2 -> True
57 _ -> False
58 }
59}
60"#
61 )
62}
63
64// https://github.com/gleam-lang/gleam/issues/1187
65#[test]
66fn pointless() {
67 assert_js!(
68 r#"
69pub fn go(x) {
70 case x {
71 _ -> x
72 }
73}
74"#,
75 )
76}
77
78// https://github.com/gleam-lang/gleam/issues/1188
79#[test]
80fn following_todo() {
81 assert_js!(
82 r#"
83pub fn go(x) {
84 case x {
85 True -> todo
86 _ -> 1
87 }
88}
89"#,
90 )
91}
92
93#[test]
94fn multi_subject_catch_all() {
95 assert_js!(
96 r#"
97pub fn go(x, y) {
98 case x, y {
99 True, True -> 1
100 _, _ -> 0
101 }
102}
103"#,
104 )
105}
106
107#[test]
108fn multi_subject_or() {
109 assert_js!(
110 r#"
111pub fn go(x, y) {
112 case x, y {
113 True, _ | _, True -> 1
114 _, _ -> 0
115 }
116}
117"#,
118 )
119}
120
121#[test]
122fn multi_subject_no_catch_all() {
123 assert_js!(
124 r#"
125pub fn go(x, y) {
126 case x, y {
127 True, _ -> 1
128 _, True -> 2
129 False, False -> 0
130 }
131}
132"#,
133 )
134}
135
136#[test]
137fn multi_subject_subject_assignments() {
138 assert_js!(
139 r#"
140pub fn go() {
141 case True, False {
142 True, True -> 1
143 _, _ -> 0
144 }
145}
146"#,
147 )
148}
149
150#[test]
151fn assignment() {
152 assert_js!(
153 r#"
154pub fn go(x) {
155 let y = case x {
156 True -> 1
157 _ -> 0
158 }
159 y
160}
161"#,
162 )
163}
164
165#[test]
166fn preassign_assignment() {
167 assert_js!(
168 r#"
169pub fn go(x) {
170 let y = case x() {
171 True -> 1
172 _ -> 0
173 }
174 y
175}
176"#,
177 )
178}
179
180// https://github.com/gleam-lang/gleam/issues/1237
181#[test]
182fn pipe() {
183 assert_js!(
184 r#"
185pub fn go(x, f) {
186 case x |> f {
187 0 -> 1
188 _ -> 2
189 }
190}
191"#,
192 )
193}
194
195#[test]
196fn result() {
197 assert_js!(
198 r#"
199pub fn go(x) {
200 case x {
201 Ok(_) -> 1
202 Error(_) -> 0
203 }
204}
205"#,
206 )
207}
208
209// https://github.com/gleam-lang/gleam/issues/1506
210#[test]
211fn called_case() {
212 assert_js!(
213 r#"
214pub fn go(x, y) {
215 case x {
216 0 -> y
217 _ -> y
218 }()
219}
220"#,
221 )
222}
223
224// https://github.com/gleam-lang/gleam/issues/1978
225#[test]
226fn case_local_var_in_tuple() {
227 assert_js!(
228 r#"
229pub fn go(x, y) {
230 let z = False
231 case True {
232 x if #(x, z) == #(True, False) -> x
233 _ -> False
234 }
235}
236"#,
237 )
238}
239
240// https://github.com/gleam-lang/gleam/issues/2665
241#[test]
242fn case_branches_guards_are_wrapped_in_parentheses() {
243 assert_js!(
244 r#"
245pub fn anything() -> a {
246 case [] {
247 [a] if False || True -> a
248 _ -> anything()
249 }
250}
251"#,
252 )
253}
254
255// https://github.com/gleam-lang/gleam/issues/2759
256#[test]
257fn nested_string_prefix_match() {
258 assert_js!(
259 r#"
260pub fn main() {
261 case Ok(["a", "b c", "d"]) {
262 Ok(["a", "b " <> _, "d"]) -> 1
263 _ -> 1
264 }
265}
266"#
267 );
268}
269
270// https://github.com/gleam-lang/gleam/issues/2759
271#[test]
272fn nested_string_prefix_match_that_would_crash_on_js() {
273 assert_js!(
274 r#"
275pub fn main() {
276 case Ok(["b c", "d"]) {
277 Ok(["b " <> _, "d"]) -> 1
278 _ -> 1
279 }
280}
281"#
282 );
283}
284
285#[test]
286fn slicing_is_handled_properly_with_multiple_branches() {
287 assert_js!(
288 r#"
289pub fn main() {
290 case "12345" {
291 "0" <> rest -> rest
292 "123" <> rest -> rest
293 _ -> ""
294 }
295}
296"#
297 )
298}
299
300// https://github.com/gleam-lang/gleam/issues/3379
301#[test]
302fn single_clause_variables() {
303 assert_js!(
304 r#"
305pub fn main() {
306 let text = "first defined"
307 case "defined again" {
308 text -> Nil
309 }
310 let text = "a third time"
311}
312"#
313 )
314}
315
316// https://github.com/gleam-lang/gleam/issues/3379
317#[test]
318fn single_clause_variables_assigned() {
319 assert_js!(
320 r#"
321pub fn main() {
322 let text = "first defined"
323 let other = case "defined again" {
324 text -> Nil
325 }
326 let text = "a third time"
327}
328"#
329 )
330}
331
332// https://github.com/gleam-lang/gleam/issues/3894
333#[test]
334fn nested_string_prefix_assignment() {
335 assert_js!(
336 r#"
337type Wibble {
338 Wibble(wobble: String)
339}
340
341pub fn main() {
342 let tmp = Wibble(wobble: "wibble")
343 case tmp {
344 Wibble(wobble: "w" as wibble <> rest) -> wibble <> rest
345 _ -> panic
346 }
347}
348"#
349 )
350}
351
352#[test]
353fn deeply_nested_string_prefix_assignment() {
354 assert_js!(
355 r#"
356type Wibble {
357 Wibble(Wobble)
358}
359type Wobble {
360 Wobble(wabble: Wabble)
361}
362type Wabble {
363 Wabble(tuple: #(Int, String))
364}
365
366pub fn main() {
367 let tmp = Wibble(Wobble(Wabble(#(42, "wibble"))))
368 case tmp {
369 Wibble(Wobble(Wabble(#(_int, "w" as wibble <> rest)))) -> wibble <> rest
370 _ -> panic
371 }
372}
373"#
374 )
375}
376
377// https://github.com/gleam-lang/gleam/issues/4383
378#[test]
379fn record_update_in_pipeline_in_case_clause() {
380 assert_js!(
381 "
382pub type Wibble {
383 Wibble(wibble: Int, wobble: Int)
384}
385
386fn identity(x) {
387 x
388}
389
390pub fn go(x) {
391 case x {
392 Wibble(1, _) -> Wibble(..x, wibble: 4) |> identity
393 Wibble(_, 3) -> Wibble(..x, wobble: 10) |> identity
394 _ -> panic
395 }
396}
397"
398 );
399}
400
401#[test]
402fn pattern_matching_on_aliased_result_constructor() {
403 assert_js!(
404 "
405import gleam.{Error as E, Ok as O}
406
407pub fn go(x) {
408 case x {
409 E(_) -> 1
410 O(_) -> 2
411 }
412}
413"
414 );
415}
416
417#[test]
418fn list_with_guard() {
419 assert_js!(
420 "
421pub fn go(x) {
422 case x {
423 [] -> 0
424 [first, ..] if first < 10 -> first * 2
425 [first, ..] -> first
426 }
427}
428"
429 );
430}
431
432#[test]
433fn list_with_guard_no_binding() {
434 assert_js!(
435 "
436pub fn go(x) {
437 case x {
438 [] -> 0
439 [first, ..] if 1 < 10 -> first * 2
440 [first, ..] -> first
441 }
442}
443"
444 );
445}