FastAPI + Celery + Next.js + Postgres/Redis app with company monitoring, source collection, LLM-based change analysis, enrichment, and account security (Turnstile, escalating lockout, email verification).
88 lines
3.0 KiB
TypeScript
88 lines
3.0 KiB
TypeScript
import { screen, waitFor } from "@testing-library/react";
|
|
import userEvent from "@testing-library/user-event";
|
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
import { SystemSecretRow } from "@/components/ui/system-secret-row";
|
|
import type { SystemSecretStatus } from "@/lib/types";
|
|
import { renderWithQueryClient } from "./test-utils";
|
|
|
|
const unconfiguredSecret: SystemSecretStatus = {
|
|
key: "turnstile_secret",
|
|
label: "Turnstile Secret Key",
|
|
configured: false,
|
|
value: null,
|
|
};
|
|
|
|
const configuredSecret: SystemSecretStatus = {
|
|
key: "turnstile_site_key",
|
|
label: "Turnstile Site Key",
|
|
configured: true,
|
|
value: "0x-my-site-key",
|
|
};
|
|
|
|
beforeEach(() => {
|
|
vi.stubGlobal("fetch", vi.fn());
|
|
});
|
|
|
|
describe("SystemSecretRow", () => {
|
|
it("shows the label and a masked input for a configured secret", () => {
|
|
renderWithQueryClient(<SystemSecretRow secret={configuredSecret} />);
|
|
expect(screen.getByText("Turnstile Site Key")).toBeInTheDocument();
|
|
const textbox = screen.getByDisplayValue("0x-my-site-key") as HTMLInputElement;
|
|
expect(textbox.type).toBe("password");
|
|
});
|
|
|
|
it("toggles the input between masked and revealed", async () => {
|
|
const user = userEvent.setup();
|
|
renderWithQueryClient(<SystemSecretRow secret={configuredSecret} />);
|
|
const textbox = screen.getByDisplayValue("0x-my-site-key") as HTMLInputElement;
|
|
expect(textbox.type).toBe("password");
|
|
|
|
await user.click(screen.getByTitle(/show key/i));
|
|
expect(textbox.type).toBe("text");
|
|
|
|
await user.click(screen.getByTitle(/hide key/i));
|
|
expect(textbox.type).toBe("password");
|
|
});
|
|
|
|
it("disables Update until the value actually changes", async () => {
|
|
const user = userEvent.setup();
|
|
renderWithQueryClient(<SystemSecretRow secret={unconfiguredSecret} />);
|
|
const updateButton = screen.getByRole("button", { name: /update/i });
|
|
expect(updateButton).toBeDisabled();
|
|
|
|
const textbox = screen.getByPlaceholderText(/not set/i);
|
|
await user.type(textbox, "sk-new-secret");
|
|
expect(updateButton).toBeEnabled();
|
|
});
|
|
|
|
it("submits the new value via PUT to the keyed endpoint and reflects the saved value", async () => {
|
|
const fetchMock = vi.fn().mockResolvedValue({
|
|
ok: true,
|
|
status: 200,
|
|
json: async () => ({ ...unconfiguredSecret, configured: true, value: "sk-new-secret" }),
|
|
});
|
|
vi.stubGlobal("fetch", fetchMock);
|
|
|
|
const user = userEvent.setup();
|
|
renderWithQueryClient(<SystemSecretRow secret={unconfiguredSecret} />);
|
|
|
|
const textbox = screen.getByPlaceholderText(/not set/i);
|
|
await user.type(textbox, "sk-new-secret");
|
|
await user.click(screen.getByRole("button", { name: /update/i }));
|
|
|
|
await waitFor(() => {
|
|
expect(fetchMock).toHaveBeenCalledWith(
|
|
expect.stringContaining("/api/v1/system/secrets/turnstile_secret"),
|
|
expect.objectContaining({
|
|
method: "PUT",
|
|
body: JSON.stringify({ value: "sk-new-secret" }),
|
|
}),
|
|
);
|
|
});
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByDisplayValue("sk-new-secret")).toBeInTheDocument();
|
|
});
|
|
});
|
|
});
|