| 1 | import { describe, expect, it } from "@effect/vitest" |
| 2 | import { Cause } from "effect" |
| 3 | import { AsyncResult } from "effect/reactivity" |
| 4 | |
| 5 | describe("AsyncResult", () => { |
| 6 | it("waiting dispatches with optional options", () => { |
| 7 | const result = AsyncResult.success(1) |
| 8 | |
| 9 | expect(AsyncResult.waiting(result).waiting).toBe(true) |
| 10 | expect(AsyncResult.waiting(result, { touch: false }).waiting).toBe(true) |
| 11 | expect(AsyncResult.waiting()(result).waiting).toBe(true) |
| 12 | expect(AsyncResult.waiting({ touch: false })(result).waiting).toBe(true) |
| 13 | }) |
| 14 | |
| 15 | describe("builder", () => { |
| 16 | it("onDefect handles defects", () => { |
| 17 | const defect = new Error("boom") |
| 18 | const result = AsyncResult.failure<number, string>(Cause.die(defect)) |
| 19 | |
| 20 | const handled = AsyncResult.builder(result) |
| 21 | .onDefect((received) => received) |
| 22 | .orElse(() => null) |
| 23 | |
| 24 | expect(handled).toBe(defect) |
| 25 | }) |
| 26 | |
| 27 | it("onDefect does not handle typed errors", () => { |
| 28 | const handled = AsyncResult.builder(AsyncResult.fail("error")) |
| 29 | .onDefect(() => "defect") |
| 30 | .orElse(() => "fallback") |
| 31 | |
| 32 | expect(handled).toEqual("fallback") |
| 33 | }) |
| 34 | |
| 35 | it("exhaustive returns output when typed errors are handled", () => { |
| 36 | const handled = AsyncResult.builder( |
| 37 | AsyncResult.fail<{ readonly _tag: "NotFoundError"; readonly resource: string }>({ |
| 38 | _tag: "NotFoundError", |
| 39 | resource: "user" |
| 40 | }) |
| 41 | ) |
| 42 | .onErrorTag("NotFoundError", (error) => `missing:${error.resource}`) |
| 43 | .onDefect(() => "failure") |
| 44 | .onInterrupt(() => "interrupt") |
| 45 | .exhaustive() |
| 46 | |
| 47 | expect(handled).toEqual("missing:user") |
| 48 | }) |
| 49 | }) |
| 50 | }) |