import { describe, it, expect, vi } from "vitest";
import { naAntwoord } from "./naAntwoord";

describe("naAntwoord", () => {
  it("valt terug op fire-and-forget wanneer after() buiten een requestscope wordt aangeroepen (bv. in een test)", async () => {
    // In dit testbestand draait geen Next.js-requestcontext, dus after() gooit
    // synchroon "called outside a request scope" — naAntwoord vangt dat op en
    // voert de taak alsnog uit, zonder de aanroeper te blokkeren of te laten falen.
    const taak = vi.fn().mockResolvedValue(undefined);
    expect(() => naAntwoord(taak)).not.toThrow();
    // De taak is (asynchroon) effectief gestart.
    await vi.waitFor(() => expect(taak).toHaveBeenCalledTimes(1));
  });

  it("een falende taak in de fallback laat de aanroeper nooit falen (nooit een onafgehandelde promise-afwijzing)", async () => {
    const taak = vi.fn().mockRejectedValue(new Error("netwerkfout"));
    expect(() => naAntwoord(taak)).not.toThrow();
    await vi.waitFor(() => expect(taak).toHaveBeenCalledTimes(1));
  });

  it("aanvaardt een PromiseLike (bv. een Supabase-querybuilder), niet enkel een echte Promise", async () => {
    let opgelost = false;
    // Minimale thenable, geen echte Promise — zoals een Supabase-querybuilder.
    // Structurele PromiseLike-typing is te strikt om hier letterlijk te
    // volgen; het runtime-gedrag (opgevangen door naAntwoord) is wat telt.
    const thenable = {
      then(onfulfilled?: (v: unknown) => unknown) {
        opgelost = true;
        onfulfilled?.(undefined);
      },
    } as PromiseLike<unknown>;
    expect(() => naAntwoord(() => thenable)).not.toThrow();
    await vi.waitFor(() => expect(opgelost).toBe(true));
  });
});
