61 lines
1.9 KiB
React
61 lines
1.9 KiB
React
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
|
|
import { vi } from "vitest";
|
|
import { BrowserRouter } from "react-router-dom";
|
|
import LoginPage from "./LoginPage";
|
|
import { AuthProvider } from "../contexts/AuthContext";
|
|
import i18n from "../i18n";
|
|
|
|
vi.mock("../api/client", async (importOriginal) => {
|
|
const actual = await importOriginal();
|
|
return { ...actual, apiPost: vi.fn() };
|
|
});
|
|
|
|
const { apiPost } = await import("../api/client");
|
|
|
|
function renderLogin() {
|
|
return render(
|
|
<AuthProvider>
|
|
<BrowserRouter>
|
|
<LoginPage />
|
|
</BrowserRouter>
|
|
</AuthProvider>
|
|
);
|
|
}
|
|
|
|
describe("LoginPage", () => {
|
|
beforeEach(async () => {
|
|
vi.clearAllMocks();
|
|
await i18n.changeLanguage("en");
|
|
});
|
|
|
|
it("renders phone input and send code button", () => {
|
|
renderLogin();
|
|
expect(screen.getByLabelText(/phone number/i)).toBeInTheDocument();
|
|
expect(screen.getByRole("button", { name: "Send code" })).toBeInTheDocument();
|
|
});
|
|
|
|
it("shows verify step after successful OTP request", async () => {
|
|
apiPost.mockResolvedValueOnce({ request_id: "abc-123", expires_at: "2025-01-01T12:00:00Z" });
|
|
renderLogin();
|
|
|
|
fireEvent.change(screen.getByLabelText(/phone number/i), { target: { value: "+966512345678" } });
|
|
fireEvent.click(screen.getByRole("button", { name: "Send code" }));
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByLabelText(/verification code/i)).toBeInTheDocument();
|
|
});
|
|
});
|
|
|
|
it("shows error when OTP request fails", async () => {
|
|
apiPost.mockRejectedValueOnce(new Error("Rate limited"));
|
|
renderLogin();
|
|
|
|
fireEvent.change(screen.getByLabelText(/phone number/i), { target: { value: "+966512345678" } });
|
|
fireEvent.click(screen.getByRole("button", { name: "Send code" }));
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByText("Rate limited")).toBeInTheDocument();
|
|
});
|
|
});
|
|
});
|