mirror of
https://github.com/webadderallorg/Recordly.git
synced 2026-11-09 07:23:14 +00:00
72 lines
2.3 KiB
TypeScript
72 lines
2.3 KiB
TypeScript
import { afterEach, expect, it, vi } from "vitest";
|
|
import { createSaveBeforeCloseController } from "./saveBeforeClose";
|
|
afterEach(() => vi.useRealTimers());
|
|
function fixture(discard = false) {
|
|
let reply!: (saved: boolean) => void;
|
|
const unsubscribe = vi.fn();
|
|
const options = {
|
|
requestSave: vi.fn(),
|
|
subscribe: vi.fn((done: (saved: boolean) => void) => {
|
|
reply = done;
|
|
return unsubscribe;
|
|
}),
|
|
offerDiscard: vi.fn().mockResolvedValue(discard),
|
|
close: vi.fn(),
|
|
cancel: vi.fn(),
|
|
timeoutMs: 100,
|
|
};
|
|
return {
|
|
options,
|
|
unsubscribe,
|
|
reply: (saved: boolean) => reply(saved),
|
|
controller: createSaveBeforeCloseController(options),
|
|
};
|
|
}
|
|
it("closes once after saving and removes the listener", () => {
|
|
const f = fixture();
|
|
f.controller.start();
|
|
f.controller.start();
|
|
f.reply(true);
|
|
f.reply(true);
|
|
expect(f.options.requestSave).toHaveBeenCalledTimes(1);
|
|
expect(f.options.close).toHaveBeenCalledTimes(1);
|
|
expect(f.unsubscribe).toHaveBeenCalledTimes(1);
|
|
expect(f.options.offerDiscard).not.toHaveBeenCalled();
|
|
});
|
|
it.each([true, false])("offers discard/cancel after failed save (discard=%s)", async (discard) => {
|
|
const f = fixture(discard);
|
|
f.controller.start();
|
|
f.reply(false);
|
|
await vi.waitFor(() =>
|
|
expect(discard ? f.options.close : f.options.cancel).toHaveBeenCalledTimes(1),
|
|
);
|
|
expect(f.unsubscribe).toHaveBeenCalledTimes(1);
|
|
if (!discard) {
|
|
f.controller.start();
|
|
expect(f.options.requestSave).toHaveBeenCalledTimes(2);
|
|
}
|
|
});
|
|
it("recovers a hung renderer on timeout and ignores late replies", async () => {
|
|
vi.useFakeTimers();
|
|
const f = fixture();
|
|
f.controller.start();
|
|
await vi.advanceTimersByTimeAsync(100);
|
|
f.reply(true);
|
|
expect(f.options.offerDiscard).toHaveBeenCalledTimes(1);
|
|
expect(f.options.cancel).toHaveBeenCalledTimes(1);
|
|
expect(f.options.close).not.toHaveBeenCalled();
|
|
f.controller.start();
|
|
expect(f.options.requestSave).toHaveBeenCalledTimes(2);
|
|
});
|
|
it("removes a pending timeout/listener when the window is destroyed", async () => {
|
|
vi.useFakeTimers();
|
|
const f = fixture();
|
|
f.controller.start();
|
|
f.controller.dispose();
|
|
await vi.advanceTimersByTimeAsync(100);
|
|
f.reply(true);
|
|
expect(f.unsubscribe).toHaveBeenCalledTimes(1);
|
|
expect(f.options.close).not.toHaveBeenCalled();
|
|
expect(f.options.offerDiscard).not.toHaveBeenCalled();
|
|
});
|