Files
jobtrackingapp/job-tracker-ui/src/microsoft-legacy-relink-page.test.tsx
T

67 lines
3.4 KiB
TypeScript

import React from "react";
import "@testing-library/jest-dom";
import { act, fireEvent, render, screen, waitFor } from "@testing-library/react";
import { MemoryRouter } from "react-router-dom";
import { api } from "./api";
import { I18nProvider } from "./i18n/I18nProvider";
import MicrosoftLegacyRelinkPage from "./views/MicrosoftLegacyRelinkPage";
import { getMicrosoftMsalInstance } from "./components/MicrosoftAuthCard";
jest.mock("./api", () => ({
api: {
get: jest.fn(), post: jest.fn(), put: jest.fn(), patch: jest.fn(), delete: jest.fn(),
interceptors: { request: { use: jest.fn() }, response: { use: jest.fn() } },
},
getApiErrorMessage: (_error: unknown, fallback: string) => fallback,
}));
jest.mock("./components/MicrosoftAuthCard", () => ({ getMicrosoftMsalInstance: jest.fn() }));
test("legacy Microsoft recovery requires the emailed proof and a fresh matching Microsoft token", async () => {
process.env.NEXT_PUBLIC_MICROSOFT_CLIENT_ID = "test-client";
(getMicrosoftMsalInstance as jest.Mock).mockReturnValue({
initialize: jest.fn().mockResolvedValue(undefined),
loginPopup: jest.fn().mockResolvedValue({ idToken: "fresh-microsoft-token" }),
});
(api.post as jest.Mock).mockResolvedValue({ data: {} });
window.history.pushState({}, "", "/microsoft-legacy-relink?userId=user-1&tenantId=tenant-1&objectId=object-1&token=recovery-token");
render(
<MemoryRouter>
<I18nProvider><MicrosoftLegacyRelinkPage /></I18nProvider>
</MemoryRouter>,
);
fireEvent.click(screen.getByRole("button", { name: "Continue with Microsoft" }));
await waitFor(() => expect(api.post).toHaveBeenCalledWith("/auth/microsoft/legacy-relink/confirm", {
userId: "user-1",
tenantId: "tenant-1",
objectId: "object-1",
recoveryToken: "recovery-token",
microsoftToken: "fresh-microsoft-token",
}));
expect(await screen.findByText("Microsoft sign-in was relinked. You can now sign in normally.")).toBeInTheDocument();
});
test("pending Microsoft recovery keeps a named action and announces progress before the real confirmation boundary", async () => {
process.env.NEXT_PUBLIC_MICROSOFT_CLIENT_ID = "test-client";
let resolvePopup!: (result: { idToken: string }) => void;
const popup = new Promise<{ idToken: string }>(resolve => { resolvePopup = resolve; });
(getMicrosoftMsalInstance as jest.Mock).mockReturnValue({
initialize: jest.fn().mockResolvedValue(undefined),
loginPopup: jest.fn().mockReturnValue(popup),
});
(api.post as jest.Mock).mockReset().mockResolvedValue({ data: {} });
window.history.replaceState({}, "", "/microsoft-legacy-relink?userId=user-1&tenantId=tenant-1&objectId=object-1&token=recovery-token");
render(<MemoryRouter><I18nProvider><MicrosoftLegacyRelinkPage /></I18nProvider></MemoryRouter>);
fireEvent.click(screen.getByRole("button", { name: "Continue with Microsoft" }));
expect(screen.getByRole("button", { name: "Continue with Microsoft" })).toBeDisabled();
expect(screen.getByRole("status")).toHaveTextContent("Loading...");
expect(api.post).not.toHaveBeenCalled();
await act(async () => resolvePopup({ idToken: "fresh-microsoft-token" }));
expect(await screen.findByRole("status")).toHaveTextContent("Microsoft sign-in was relinked.");
expect(api.post).toHaveBeenCalledWith("/auth/microsoft/legacy-relink/confirm", {
userId: "user-1", tenantId: "tenant-1", objectId: "object-1", recoveryToken: "recovery-token", microsoftToken: "fresh-microsoft-token",
});
});