|
1 | 1 | import { describe, expect, it } from "bun:test" |
2 | 2 | import type { TryCtx } from "../../types/core" |
3 | | -import { CancellationError, Panic, TimeoutError, UnhandledException } from "../../errors" |
| 3 | +import { |
| 4 | + CancellationError, |
| 5 | + Panic, |
| 6 | + RetryExhaustedError, |
| 7 | + TimeoutError, |
| 8 | + UnhandledException, |
| 9 | +} from "../../errors" |
4 | 10 | import { sleep } from "../../utils" |
5 | 11 | import { executeRun } from "../run" |
6 | 12 |
|
@@ -64,6 +70,39 @@ describe("executeRun", () => { |
64 | 70 | expect((error as Panic).code).toBe("RUN_CATCH_HANDLER_REJECT") |
65 | 71 | } |
66 | 72 | }) |
| 73 | + |
| 74 | + it("returns RetryExhaustedError and skips catch when retries are exhausted", async () => { |
| 75 | + let attempts = 0 |
| 76 | + let mapped = false |
| 77 | + const cause = new Error("boom") |
| 78 | + |
| 79 | + const result = (await executeRun( |
| 80 | + { |
| 81 | + retry: { backoff: "constant", delayMs: 0, limit: 2 }, |
| 82 | + }, |
| 83 | + { |
| 84 | + catch: () => { |
| 85 | + mapped = true |
| 86 | + return "mapped" |
| 87 | + }, |
| 88 | + try: async () => { |
| 89 | + await Promise.resolve() |
| 90 | + attempts += 1 |
| 91 | + throw cause |
| 92 | + }, |
| 93 | + } |
| 94 | + )) as unknown as object |
| 95 | + |
| 96 | + expect(result).toBeInstanceOf(RetryExhaustedError) |
| 97 | + |
| 98 | + if (!(result instanceof RetryExhaustedError)) { |
| 99 | + expect.unreachable("should return RetryExhaustedError") |
| 100 | + } |
| 101 | + |
| 102 | + expect(result.cause).toBe(cause) |
| 103 | + expect(attempts).toBe(2) |
| 104 | + expect(mapped).toBe(false) |
| 105 | + }) |
67 | 106 | }) |
68 | 107 |
|
69 | 108 | describe("timeout behavior", () => { |
|
0 commit comments