repos / starfx

supercharged async flow control library.
git clone https://github.com/neurosnap/starfx.git

starfx / test
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});