123import { afterEach, describe, expect, it, vi } from "vitest";45import { flushView, renderView } from "./view-test-utils";67const snoozeMock = vi.fn(async () => {});8const silenceMock = vi.fn(async () => {});910vi.mock("../../shared/pro-nudge", () => ({11 snoozeProNudge: () => snoozeMock(),12 silenceProNudge: () => silenceMock(),13}));1415const { ProNudgeView } = await import("./ProNudge");1617function button(container: HTMLElement, label: string): HTMLButtonElement {18 const match = [...container.querySelectorAll("button")].find((b) => b.textContent?.trim() === label);19 if (!match) throw new Error(`no button "${label}"`);20 return match;21}2223describe("ProNudgeView", () => {24 let dispose: (() => void) | undefined;2526 afterEach(() => {27 dispose?.();28 vi.clearAllMocks();29 });3031 it("snoozes for 90 days, then dismisses", async () => {32 const onDismiss = vi.fn();33 const view = renderView(() => <ProNudgeView onSeePro={() => {}} onDismiss={onDismiss} />);34 dispose = view.dispose;3536 button(view.container, "Remind me in 90 days").click();37 await flushView();3839 expect(snoozeMock).toHaveBeenCalledOnce();40 expect(silenceMock).not.toHaveBeenCalled();41 expect(onDismiss).toHaveBeenCalledOnce();42 });4344 it("silences permanently, then dismisses", async () => {45 const onDismiss = vi.fn();46 const view = renderView(() => <ProNudgeView onSeePro={() => {}} onDismiss={onDismiss} />);47 dispose = view.dispose;4849 button(view.container, "Don't show again").click();50 await flushView();5152 expect(silenceMock).toHaveBeenCalledOnce();53 expect(onDismiss).toHaveBeenCalledOnce();54 });5556 it("still dismisses when storage fails", async () => {57 silenceMock.mockRejectedValueOnce(new Error("quota"));58 const onDismiss = vi.fn();59 const view = renderView(() => <ProNudgeView onSeePro={() => {}} onDismiss={onDismiss} />);60 dispose = view.dispose;6162 button(view.container, "Don't show again").click();63 await flushView();6465 expect(onDismiss).toHaveBeenCalledOnce();66 });6768 it("opens Pro without recording a dismissal", () => {69 const onSeePro = vi.fn();70 const view = renderView(() => <ProNudgeView onSeePro={onSeePro} onDismiss={() => {}} />);71 dispose = view.dispose;7273 button(view.container, "See Peach Pro").click();7475 expect(onSeePro).toHaveBeenCalledOnce();76 expect(snoozeMock).not.toHaveBeenCalled();77 expect(silenceMock).not.toHaveBeenCalled();78 });79});