1import { wrapWorkflowStep } from "@/Cloudflare/Workflows/WorkflowBridge.ts";
2import { describe, expect, it } from "alchemy-test";
3import * as Cause from "effect/Cause";
4import * as Effect from "effect/Effect";
5import * as Exit from "effect/Exit";
6
7describe(
8 "WorkflowBridge",
9 {
10 tags: [
11 "unit",
12 "provider:cloudflare",
13 "provider:cloudflare:worker",
14 "provider:cloudflare:workflow",
15 "local",
16 ],
17 },
18 () => {
19 it.effect("preserves native Workflow control-flow rejections", () =>
20 Effect.gen(function* () {
21 const controlError = new Error("Aborting engine: User called pause");
22 const rejectWithControlError = () =>
23 Effect.runPromise(Effect.die(controlError));
24 const step = wrapWorkflowStep({
25 do: rejectWithControlError,
26 sleep: rejectWithControlError,
27 sleepUntil: rejectWithControlError,
28 waitForEvent: rejectWithControlError,
29 });
30
31 const effects = [
32 step.do({ name: "task", effect: Effect.succeed("done") }),
33 step.sleep("sleep", "1 second"),
34 step.sleepUntil("sleep-until", 1),
35 step.waitForEvent("event", { type: "test-event" }),
36 ];
37
38 for (const effect of effects) {
39 const exit = yield* Effect.exit(effect);
40 expect(Exit.isFailure(exit)).toBe(true);
41 if (Exit.isFailure(exit)) {
42 expect(Cause.squash(exit.cause)).toBe(controlError);
43 }
44 }
45 }),
46 );
47
48 it.effect(
49 "omits undefined config keys so retries-only steps keep the engine timeout default",
50 () =>
51 Effect.gen(function* () {
52 const doCalls: Array<unknown> = [];
53 const step = wrapWorkflowStep({
54 do: (...args: unknown[]) => {
55 doCalls.push(args);
56 return Promise.resolve("done");
57 },
58 sleep: () => Promise.resolve(),
59 sleepUntil: () => Promise.resolve(),
60 waitForEvent: () => Promise.resolve(),
61 });
62
63 yield* step.do({
64 name: "retries-only",
65 effect: Effect.succeed("done"),
66 retries: { limit: 3, delay: "10 seconds", backoff: "exponential" },
67 });
68
69 expect(doCalls).toHaveLength(1);
70 const config = (doCalls[0] as Array<unknown>)[1];
71 expect(config).toEqual({
72 retries: {
73 limit: 3,
74 delay: "10 seconds",
75 backoff: "exponential",
76 },
77 });
78 expect("timeout" in (config as object)).toBe(false);
79 }),
80 );
81 },
82);