import { describe, expect, it } from "vitest";
import { nextTick } from "vue";
import { useOverlayTransition } from "../../src/vue/composables/use-overlay-transition.js";
import { raf } from "../setup.js";
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
describe("useOverlayTransition", () => {
it("starts hidden", () => {
const transition = useOverlayTransition();
expect(transition.visible.value).toBe(false);
expect(transition.closing.value).toBe(false);
});
it("renders the hidden state first, then flips to visible after nextTick + rAF", async () => {
const transition = useOverlayTransition();
transition.show();
expect(transition.visible.value).toBe(true);
expect(transition.closing.value).toBe(true);
await nextTick();
await raf();
expect(transition.closing.value).toBe(false);
});
it("keeps the element mounted for the closing transition, then unmounts", async () => {
const transition = useOverlayTransition();
transition.show();
await nextTick();
await raf();
transition.hide();
expect(transition.visible.value).toBe(true);
await sleep(150);
expect(transition.visible.value).toBe(true);
await sleep(200);
expect(transition.visible.value).toBe(false);
expect(transition.closing.value).toBe(false);
});
it("a show() during the closing wait cancels the unmount", async () => {
const transition = useOverlayTransition();
transition.show();
await nextTick();
await raf();
transition.hide();
await sleep(100);
transition.show();
await sleep(400);
expect(transition.visible.value).toBe(true);
await nextTick();
await raf();
expect(transition.closing.value).toBe(false);
});
it("cancel() stops the pending unmount without changing state", async () => {
const transition = useOverlayTransition();
transition.show();
await nextTick();
await raf();
transition.hide();
transition.cancel();
await sleep(400);
expect(transition.visible.value).toBe(true);
});
});