1import { describe, expect, it } from "@effect/vitest"
2import { Cause } from "effect"
3import { AsyncResult } from "effect/reactivity"
4
5describe("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})