repos / starfx

a micro-mvc framework for react apps
git clone https://github.com/neurosnap/starfx.git

starfx / src / test
Eric Bower  ·  2025-06-06

take-helper.test.ts

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