// @vitest-environment jsdom // // S6 — the per-user download-cookies section is WRITE-ONLY: the stored blob is never fetched or // shown back, so opening "Set"/"Update" always reveals an EMPTY field, and saving posts exactly the // pasted value to the matching host. This drives the real DownloadAuth against a mocked api so we can // assert the field never carries a prior value and the right host is written. import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; import { render, screen, cleanup, fireEvent, waitFor } from "@testing-library/react"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; const h = vi.hoisted(() => ({ downloadCredentials: vi.fn(), setDownloadCredential: vi.fn(), deleteDownloadCredential: vi.fn(), })); vi.mock("react-i18next", async (importOriginal) => { const actual = await importOriginal(); return { ...actual, useTranslation: () => ({ t: (key: string) => key, i18n: { language: "en" } }), }; }); vi.mock("../lib/api", () => ({ api: h })); // Partial mock: SettingsPanel's module graph (PrefsProvider) also pulls getNotifSettings from here. vi.mock("../lib/notifications", async (importOriginal) => { const actual = await importOriginal(); return { ...actual, notify: vi.fn() }; }); vi.mock("./ConfirmProvider", () => ({ useConfirm: () => vi.fn(async () => true) })); import { DownloadAuth } from "./SettingsPanel"; const HOSTS = [ { host_key: "facebook", label: "Facebook", configured: false, updated_at: null }, { host_key: "instagram", label: "Instagram", configured: true, updated_at: "2026-08-01T00:00:00Z", }, ]; function renderPanel() { const qc = new QueryClient({ defaultOptions: { queries: { retry: false } } }); return render( , ); } describe("DownloadAuth (write-only cookies)", () => { beforeEach(() => { h.downloadCredentials.mockResolvedValue({ hosts: HOSTS }); h.setDownloadCredential.mockResolvedValue({ ok: true, hosts: HOSTS }); h.deleteDownloadCredential.mockResolvedValue({ ok: true, hosts: HOSTS }); }); afterEach(cleanup); it("lists every supported host with its configured state", async () => { renderPanel(); await screen.findByTestId("cookie-host-facebook"); expect(screen.getByTestId("cookie-status-facebook").textContent).toContain( "settings.downloadAuth.notSet", ); expect(screen.getByTestId("cookie-status-instagram").textContent).toContain( "settings.downloadAuth.configured", ); }); it("opens an EMPTY field on Set and posts the pasted value to that host", async () => { renderPanel(); await screen.findByTestId("cookie-host-facebook"); // The Set button is the outline action on the facebook row. const setBtn = screen.getByText("settings.downloadAuth.set"); fireEvent.click(setBtn); const field = (await screen.findByTestId("cookie-input-facebook")) as HTMLTextAreaElement; expect(field.value).toBe(""); // write-only: never prefilled fireEvent.change(field, { target: { value: "# Netscape\n.facebook.com\tTRUE\t/\tT\t0\tc\t1\n" }, }); fireEvent.click(screen.getByText("settings.downloadAuth.save")); await waitFor(() => expect(h.setDownloadCredential).toHaveBeenCalledWith( "facebook", "# Netscape\n.facebook.com\tTRUE\t/\tT\t0\tc\t1\n", ), ); }); it("re-opening Update on a configured host still shows an empty field", async () => { renderPanel(); await screen.findByTestId("cookie-host-instagram"); fireEvent.click(screen.getByText("settings.downloadAuth.update")); const field = (await screen.findByTestId("cookie-input-instagram")) as HTMLTextAreaElement; expect(field.value).toBe(""); // the stored blob is never fetched into the field }); it("renders an honest error state with retry when the fetch fails, not an empty section", async () => { // Honest-states: a failed load must NOT render as a bare empty section (no host rows). h.downloadCredentials.mockRejectedValueOnce(new Error("boom")); h.downloadCredentials.mockResolvedValue({ hosts: HOSTS }); renderPanel(); // The error message shows and no host rows render. await screen.findByText("settings.downloadAuth.loadError"); expect(screen.queryByTestId("cookie-host-facebook")).toBeNull(); // Retry refetches → the list appears. fireEvent.click(screen.getByText("common.retry")); await screen.findByTestId("cookie-host-facebook"); }); });