Eric Bower
·
2025-06-06
put.test.ts
1import { ActionContext, each, put, sleep, spawn, take } from "../index.js";
2import { createStore } from "../store/index.js";
3import { expect, test } from "../test.js";
4
5test("should send actions through channel", async () => {
6 const actual: string[] = [];
7
8 function* genFn(arg: string) {
9 const actions = yield* ActionContext.expect();
10 const task = yield* spawn(function* () {
11 for (const action of yield* each(actions)) {
12 actual.push(action.type);
13 yield* each.next();
14 }
15 });
16
17 yield* put({
18 type: arg,
19 });
20 yield* put({
21 type: "2",
22 });
23 actions.close();
24 yield* task;
25 }
26
27 const store = createStore({ initialState: {} });
28 await store.run(() => genFn("arg"));
29
30 const expected = ["arg", "2"];
31 expect(actual).toEqual(expected);
32});
33
34test("should handle nested puts", async () => {
35 const actual: string[] = [];
36
37 function* genA() {
38 yield* put({
39 type: "a",
40 });
41 actual.push("put a");
42 }
43
44 function* genB() {
45 yield* take(["a"]);
46 yield* put({
47 type: "b",
48 });
49 actual.push("put b");
50 }
51
52 function* root() {
53 yield* spawn(genB);
54 yield* spawn(genA);
55 }
56
57 const store = createStore({ initialState: {} });
58 await store.run(() => root());
59
60 const expected = ["put b", "put a"];
61 expect(actual).toEqual(expected);
62});
63
64test("should not cause stack overflow when puts are emitted while dispatching saga", async () => {
65 function* root() {
66 for (let i = 0; i < 10_000; i += 1) {
67 yield* put({ type: "test" });
68 }
69 yield* sleep(0);
70 }
71
72 const store = createStore({ initialState: {} });
73 await store.run(() => root());
74 expect(true).toBe(true);
75});
76
77test("should not miss `put` that was emitted directly after creating a task (caused by another `put`)", async () => {
78 const actual: string[] = [];
79
80 function* root() {
81 yield* spawn(function* firstspawn() {
82 yield* sleep(10);
83 yield* put({ type: "c" });
84 yield* put({ type: "do not miss" });
85 });
86
87 yield* take("c");
88
89 const tsk = yield* spawn(function* () {
90 yield* take("do not miss");
91 actual.push("didn't get missed");
92 });
93 yield* tsk;
94 }
95
96 const store = createStore({ initialState: {} });
97 await store.run(root);
98 const expected = ["didn't get missed"];
99 expect(actual).toEqual(expected);
100});