first commit
This commit is contained in:
138
packages/admin/tests/components/SetupWizard.test.tsx
Normal file
138
packages/admin/tests/components/SetupWizard.test.tsx
Normal file
@@ -0,0 +1,138 @@
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import * as React from "react";
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import { render } from "vitest-browser-react";
|
||||
|
||||
// Mock API
|
||||
vi.mock("../../src/lib/api/client", async () => {
|
||||
const actual = await vi.importActual("../../src/lib/api/client");
|
||||
return {
|
||||
...actual,
|
||||
apiFetch: vi.fn().mockImplementation((url: string) => {
|
||||
if (url.includes("/setup/status")) {
|
||||
return Promise.resolve(
|
||||
new Response(JSON.stringify({ data: { needsSetup: true, authMode: "passkey" } }), {
|
||||
status: 200,
|
||||
}),
|
||||
);
|
||||
}
|
||||
if (url.includes("/setup/admin")) {
|
||||
return Promise.resolve(
|
||||
new Response(JSON.stringify({ data: { success: true } }), { status: 200 }),
|
||||
);
|
||||
}
|
||||
if (url.includes("/setup") && !url.includes("status")) {
|
||||
return Promise.resolve(
|
||||
new Response(JSON.stringify({ data: { success: true } }), { status: 200 }),
|
||||
);
|
||||
}
|
||||
return Promise.resolve(new Response(JSON.stringify({ data: {} }), { status: 200 }));
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
// Mock WebAuthn so PasskeyRegistration doesn't bail out
|
||||
Object.defineProperty(window, "PublicKeyCredential", {
|
||||
value: function PublicKeyCredential() {},
|
||||
writable: true,
|
||||
});
|
||||
|
||||
// Import after mocks
|
||||
const { SetupWizard } = await import("../../src/components/SetupWizard");
|
||||
|
||||
function QueryWrapper({ children }: { children: React.ReactNode }) {
|
||||
const qc = new QueryClient({
|
||||
defaultOptions: { queries: { retry: false }, mutations: { retry: false } },
|
||||
});
|
||||
return <QueryClientProvider client={qc}>{children}</QueryClientProvider>;
|
||||
}
|
||||
|
||||
describe("SetupWizard", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it("shows site setup step first with title input", async () => {
|
||||
const screen = await render(
|
||||
<QueryWrapper>
|
||||
<SetupWizard />
|
||||
</QueryWrapper>,
|
||||
);
|
||||
await expect.element(screen.getByText("Set up your site")).toBeInTheDocument();
|
||||
await expect.element(screen.getByPlaceholder("My Awesome Blog")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("empty title prevents advancing and shows validation error", async () => {
|
||||
const screen = await render(
|
||||
<QueryWrapper>
|
||||
<SetupWizard />
|
||||
</QueryWrapper>,
|
||||
);
|
||||
// Wait for setup status to load
|
||||
await expect.element(screen.getByText("Set up your site")).toBeInTheDocument();
|
||||
// Click Continue without filling title
|
||||
await screen.getByText("Continue →").click();
|
||||
await expect.element(screen.getByText("Site title is required")).toBeInTheDocument();
|
||||
// Should still be on site step
|
||||
await expect.element(screen.getByText("Set up your site")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("filling title and clicking Next advances to admin step", async () => {
|
||||
const screen = await render(
|
||||
<QueryWrapper>
|
||||
<SetupWizard />
|
||||
</QueryWrapper>,
|
||||
);
|
||||
await expect.element(screen.getByText("Set up your site")).toBeInTheDocument();
|
||||
// Fill in the title
|
||||
await screen.getByPlaceholder("My Awesome Blog").fill("Test Site");
|
||||
// Click continue
|
||||
await screen.getByText("Continue →").click();
|
||||
// Should advance to admin step
|
||||
await expect.element(screen.getByText("Create your account")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("admin step shows email input", async () => {
|
||||
const screen = await render(
|
||||
<QueryWrapper>
|
||||
<SetupWizard />
|
||||
</QueryWrapper>,
|
||||
);
|
||||
await expect.element(screen.getByText("Set up your site")).toBeInTheDocument();
|
||||
// Fill title and advance
|
||||
await screen.getByPlaceholder("My Awesome Blog").fill("Test Site");
|
||||
await screen.getByText("Continue →").click();
|
||||
// Should see email input on admin step
|
||||
await expect.element(screen.getByText("Create your account")).toBeInTheDocument();
|
||||
await expect.element(screen.getByPlaceholder("you@example.com")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("empty email prevents advancing on admin step", async () => {
|
||||
const screen = await render(
|
||||
<QueryWrapper>
|
||||
<SetupWizard />
|
||||
</QueryWrapper>,
|
||||
);
|
||||
await expect.element(screen.getByText("Set up your site")).toBeInTheDocument();
|
||||
// Fill title and advance
|
||||
await screen.getByPlaceholder("My Awesome Blog").fill("Test Site");
|
||||
await screen.getByText("Continue →").click();
|
||||
await expect.element(screen.getByText("Create your account")).toBeInTheDocument();
|
||||
// Click Continue without filling email
|
||||
await screen.getByText("Continue →").click();
|
||||
// Should show validation error
|
||||
await expect.element(screen.getByText("Email is required")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("step indicator shows three steps", async () => {
|
||||
const screen = await render(
|
||||
<QueryWrapper>
|
||||
<SetupWizard />
|
||||
</QueryWrapper>,
|
||||
);
|
||||
await expect.element(screen.getByText("Set up your site")).toBeInTheDocument();
|
||||
// Step indicator labels - use exact matching via role
|
||||
await expect.element(screen.getByText("Account")).toBeInTheDocument();
|
||||
await expect.element(screen.getByText("Passkey")).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user