ProNudge.test.tsx

2.4 KB · raw

1// @vitest-environment jsdom23import { 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});