import { isPromise, sleep, run, runSafely, retry } from "@/utils/async-utils"; describe("isPromise", () => { test("returns true when input is a Promise", () => { const promise = new Promise(resolve => resolve(undefined)); expect(isPromise(promise)).toBe(true); }); test("returns false when input is not a Promise", () => { const notAPromise = {}; expect(isPromise(notAPromise)).toBe(false); }); }); describe("sleep", () => { beforeEach(() => jest.useFakeTimers()); afterEach(() => jest.useRealTimers()); test("resolves after specified time", async () => { const start = Date.now(); const promise = sleep(1000); await jest.advanceTimersByTimeAsync(1000); await promise; const elapsed = Date.now() - start; return expect(elapsed).toBe(1000); }); test("resolves immediately if time is less than or equal to 0", async () => { const start = Date.now(); const promise = sleep(-10); await promise; const elapsed = Date.now() - start; return expect(elapsed).toBe(0); }); }); describe("run", () => { test("runs the provided function asynchronously", async () => { const func = jest.fn().mockResolvedValue(42); const result = await run(func); expect(func).toHaveBeenCalledTimes(1); expect(func).toHaveBeenCalledWith(); expect(result).toBe(42); }); }); describe("runSafely", () => { test("returns result and undefined error when function succeeds", async () => { const func = jest.fn().mockResolvedValue(42); const [result, error] = await runSafely(func); expect(func).toHaveBeenCalledTimes(1); expect(func).toHaveBeenCalledWith(); expect(result).toBe(42); expect(error).toBeUndefined(); }); test("returns undefined result and error when function fails", async () => { const func = jest.fn().mockRejectedValue(new Error("Error occurred")); const [result, error] = await runSafely(func); expect(func).toHaveBeenCalledTimes(1); expect(func).toHaveBeenCalledWith(); expect(result).toBeUndefined(); expect(error).toEqual(new Error("Error occurred")); }); }); describe("retry", () => { test("retries the function when it fails", async () => { const func = jest.fn().mockRejectedValueOnce(new Error("Error occurred")).mockResolvedValue(42); const result = await retry(func, { maxAttempts: 2 }); expect(func).toHaveBeenCalledTimes(2); expect(result).toBe(42); }); test("does not retry the function when error is not recoverable", async () => { const func = jest.fn().mockRejectedValue(new Error("Error occurred")); const onError = jest.fn().mockResolvedValue(false); await expect(retry(func, { onError, maxAttempts: 2 })).rejects.toThrow("Error occurred"); expect(func).toHaveBeenCalledTimes(1); expect(onError).toHaveBeenCalledTimes(1); }); test("stops retrying after max attempts", async () => { const func = jest.fn().mockRejectedValue(new Error("Error occurred")); await expect(retry(func, { maxAttempts: 2 })).rejects.toThrow("Error occurred"); expect(func).toHaveBeenCalledTimes(2); }); });