Compare commits

...
3 changed files with 52 additions and 17 deletions
@@ -7069,8 +7069,6 @@ notStarted = "Not started"
cancel = "Cancel"
createKey = "Create key"
done = "Done"
ipAllowlistHelper = "Comma-separated CIDR ranges. Leave blank to allow any IP."
ipAllowlistLabel = "IP allowlist"
keyNameLabel = "Key name"
keyNamePlaceholder = "e.g. Production · ingest"
permissionsLabel = "Permissions"
@@ -0,0 +1,50 @@
import type { ComponentProps } from "react";
import { describe, expect, it, vi } from "vitest";
import { fireEvent, render, screen } from "@testing-library/react";
import { MantineProvider } from "@mantine/core";
// Deterministic i18n: keys returned verbatim, so assertions are stable.
vi.mock("react-i18next", () => ({
useTranslation: () => ({
t: (key: string) => key,
i18n: { changeLanguage: vi.fn() },
}),
}));
import { CreateKeyModal } from "@portal/components/infrastructure/CreateKeyModal";
const K = "portal.infrastructure.createKey";
function renderModal(props: Partial<ComponentProps<typeof CreateKeyModal>>) {
return render(
<MantineProvider>
<CreateKeyModal open onClose={() => {}} {...props} />
</MantineProvider>,
);
}
describe("CreateKeyModal", () => {
it("gates the create button on a name and at least one permission", () => {
renderModal({});
const cta = screen.getByRole("button", { name: `${K}.createKey` });
expect(cta).toBeDisabled();
fireEvent.change(screen.getByPlaceholderText(`${K}.keyNamePlaceholder`), {
target: { value: "Production ingest" },
});
expect(cta).toBeEnabled();
});
it("reveals the generated secret with a store-it warning", () => {
renderModal({});
fireEvent.change(screen.getByPlaceholderText(`${K}.keyNamePlaceholder`), {
target: { value: "Production ingest" },
});
fireEvent.click(screen.getByRole("button", { name: `${K}.createKey` }));
expect(screen.getByText(`${K}.secretWarning`)).toBeInTheDocument();
expect(
screen.getByText("sk_live_demo_key_rotate_in_prod"),
).toBeInTheDocument();
});
});
@@ -27,13 +27,11 @@ export function CreateKeyModal({
const { t } = useTranslation();
const [name, setName] = useState("");
const [perms, setPerms] = useState<ApiKeyPermission[]>(["Read"]);
const [ips, setIps] = useState("");
const [created, setCreated] = useState(false);
function reset() {
setName("");
setPerms(["Read"]);
setIps("");
setCreated(false);
}
@@ -50,8 +48,8 @@ export function CreateKeyModal({
}
function createKey() {
// TODO(backend): POST /v1/infrastructure/api-keys { name, perms, ips }
// and render the one-time secret from the response instead of the fixture.
// TODO(backend): POST /v1/infrastructure/api-keys { name, perms } and render
// the one-time secret from the response instead of the fixture.
setCreated(true);
}
@@ -136,17 +134,6 @@ export function CreateKeyModal({
))}
</div>
</FormField>
<FormField
label={t("portal.infrastructure.createKey.ipAllowlistLabel")}
helperText={t("portal.infrastructure.createKey.ipAllowlistHelper")}
>
<Input
value={ips}
onChange={(e) => setIps(e.target.value)}
placeholder="52.14.0.0/16, 203.0.113.7/32"
/>
</FormField>
</div>
)}
</Modal>