Eric Bower
·
04 Mar 24
take-helper.test.ts
1import { describe, expect, it } from "../test.ts";
2import { createStore } from "../store/mod.ts";
3import type { AnyAction } from "../mod.ts";
4import { sleep, take, takeEvery, takeLatest, takeLeading } from "../mod.ts";
5import { spawn } from "../deps.ts";
6
7const testEvery = describe("takeEvery()");
8const testLatest = describe("takeLatest()");
9const testLeading = describe("takeLeading()");
10
11it(testLatest, "should cancel previous tasks and only use latest", async () => {
12 const actual: string[] = [];
13 function* worker(action: AnyAction) {
14 if (action.payload !== "3") {
15 yield* sleep(3000);
16 }
17 actual.push(action.payload);
18 }
19
20 function* root() {
21 const task = yield* spawn(() => takeLatest("ACTION", worker));
22 yield* take("CANCEL_WATCHER");
23 yield* task.halt();
24 }
25 const store = createStore({ initialState: {} });
26 const task = store.run(root);
27
28 store.dispatch({ type: "ACTION", payload: "1" });
29 store.dispatch({ type: "ACTION", payload: "2" });
30 store.dispatch({ type: "ACTION", payload: "3" });
31 store.dispatch({ type: "CANCEL_WATCHER" });
32
33 await task;
34
35 expect(actual).toEqual(["3"]);
36});
37
38it(testLeading, "should keep first action and discard the rest", async () => {
39 let called = 0;
40 const actual: string[] = [];
41 function* worker(action: AnyAction) {
42 called += 1;
43 yield* sleep(100);
44 actual.push(action.payload);
45 }
46
47 function* root() {
48 const task = yield* spawn(() => takeLeading("ACTION", worker));
49 yield* sleep(150);
50 yield* task.halt();
51 }
52 const store = createStore({ initialState: {} });
53 const task = store.run(root);
54
55 store.dispatch({ type: "ACTION", payload: "1" });
56 store.dispatch({ type: "ACTION", payload: "2" });
57 store.dispatch({ type: "ACTION", payload: "3" });
58
59 await task;
60
61 expect(actual).toEqual(["1"]);
62 expect(called).toEqual(1);
63});
64
65it(testEvery, "should receive all actions", async () => {
66 const loop = 10;
67 const actual: string[][] = [];
68
69 function* root() {
70 const task = yield* spawn(() =>
71 takeEvery(
72 "ACTION",
73 (action) => worker("a1", "a2", action),
74 )
75 );
76 yield* take("CANCEL_WATCHER");
77 yield* task.halt();
78 }
79
80 // deno-lint-ignore require-yield
81 function* worker(arg1: string, arg2: string, action: AnyAction) {
82 actual.push([arg1, arg2, action.payload]);
83 }
84
85 const store = createStore({ initialState: {} });
86 const task = store.run(root);
87
88 for (let i = 1; i <= loop / 2; i += 1) {
89 store.dispatch({
90 type: "ACTION",
91 payload: i,
92 });
93 }
94
95 // no further task should be forked after this
96 store.dispatch({
97 type: "CANCEL_WATCHER",
98 });
99
100 for (let i = loop / 2 + 1; i <= loop; i += 1) {
101 store.dispatch({
102 type: "ACTION",
103 payload: i,
104 });
105 }
106 await task;
107
108 expect(actual).toEqual([
109 ["a1", "a2", 1],
110 ["a1", "a2", 2],
111 ["a1", "a2", 3],
112 ["a1", "a2", 4],
113 ["a1", "a2", 5],
114 ]);
115});