import { act, renderHook } from "@testing-library/react";
import { describe, it, vi, expect } from "vitest";
import { useAsyncCallback } from "./index";
describe("useAsyncCallback", () => {
    it("should handle successful resolution", async () => {
        let fn = vi.fn(async () => {
            return;
        });
        let { result } = renderHook(() => useAsyncCallback(fn));
        let [callback, state] = result.current;
        expect(state.loading).toBe(false);
        expect(state.error).toBe(null);
        await act(async () => {
            await callback();
        });
        expect(result.current[1].loading).toBe(false);
        expect(result.current[1].error).toBe(null);
        expect(fn).toHaveBeenCalledTimes(1);
    });
    it("should handle rejection", async () => {
        let error = new Error("fail");
        let fn = vi.fn(async () => {
            throw error;
        });
        let { result } = renderHook(() => useAsyncCallback(fn));
        await act(async () => {
            await result.current[0]();
        });
        expect(result.current[1].loading).toBe(false);
        expect(result.current[1].error).toBe(error);
    });
    it("should abort previous call", async () => {
        vi.useFakeTimers();
        let signals = [];
        let fn = vi.fn(async (signal) => {
            signals.push(signal);
            await new Promise((resolve) => setTimeout(resolve, 10));
        });
        let { result } = renderHook(() => useAsyncCallback(fn));
        await act(async () => {
            result.current[0]();
            // Yield to event loop to allow first call to start
            vi.advanceTimersByTime(1);
            result.current[0]();
        });
        // Fast-forward to complete the second call
        await act(async () => {
            vi.advanceTimersByTime(10);
        });
        expect(signals.length).toBe(2);
        expect(signals[0].aborted).toBeTruthy();
        expect(signals[1].aborted).toBe(false);
        vi.useRealTimers();
    });
});
