Eric Bower
·
2025-06-06
compose.test.ts
1import { Err, Ok, type Result, compose, run, safe, sleep } from "../index.js";
2import { expect, test } from "../test.js";
3
4test("should compose middleware", async () => {
5 const mdw = compose<{ one: string; three: string; result: Result<void> }>([
6 function* (ctx, next) {
7 ctx.one = "two";
8 yield* next();
9 },
10 function* (ctx, next) {
11 ctx.three = "four";
12 yield* next();
13 },
14 ]);
15 const actual = await run(function* () {
16 const ctx = { one: "", three: "", result: Ok(void 0) };
17 yield* mdw(ctx);
18 return ctx;
19 });
20
21 const expected = {
22 // we should see the mutation
23 one: "two",
24 three: "four",
25 result: Ok(void 0),
26 };
27 expect(actual).toEqual(expected);
28});
29
30test("order of execution", async () => {
31 const mdw = compose<{ actual: string; result: Result<void> }>([
32 function* (ctx, next) {
33 ctx.actual += "a";
34 yield* next();
35 ctx.actual += "g";
36 },
37 function* (ctx, next) {
38 yield* sleep(10);
39 ctx.actual += "b";
40 yield* next();
41 yield* sleep(10);
42 ctx.actual += "f";
43 },
44 function* (ctx, next) {
45 ctx.actual += "c";
46 yield* next();
47 ctx.actual += "d";
48 yield* sleep(30);
49 ctx.actual += "e";
50 },
51 ]);
52
53 const actual = await run(function* () {
54 const ctx = { actual: "", result: Ok(void 0) };
55 yield* mdw(ctx);
56 return ctx;
57 });
58 const expected = {
59 actual: "abcdefg",
60 result: Ok(void 0),
61 };
62 expect(actual).toEqual(expected);
63});
64
65test("when error is discovered, it should throw", async () => {
66 const err = new Error("boom");
67 const mdw = compose([
68 function* (_, next) {
69 yield* next();
70 expect.fail();
71 },
72 function* (_, next) {
73 yield* next();
74 throw err;
75 },
76 ]);
77 const actual = await run(function* () {
78 const ctx = {};
79 const result = yield* safe(() => mdw(ctx));
80 return result;
81 });
82
83 const expected = Err(err);
84 expect(actual).toEqual(expected);
85});