import { act, render, screen, waitFor } from "@testing-library/react";
import { beforeEach, expect, test, vi } from "vitest";
import { AuthProvider } from "@/app/auth/AuthProvider.jsx";
import * as authApi from "@/features/auth/api";
import { setAccessToken, setRefreshHandler, setUnauthorizedHandler } from "@/shared/api/request";
import { AuthenticatedOpsCenter } from "./OpsCenterEntry.jsx";
vi.mock("@/features/auth/api", () => ({
getMe: vi.fn(),
login: vi.fn(),
logout: vi.fn(),
refreshSession: vi.fn(),
}));
vi.mock("./OpsCenterApp.jsx", () => ({
OpsCenterApp: ({ can }) => (
),
}));
beforeEach(() => {
vi.clearAllMocks();
setAccessToken("");
setRefreshHandler(null);
setUnauthorizedHandler(null);
});
test("does not mount the dashboard without a session and redirects to login with the full ops path", async () => {
authApi.refreshSession.mockRejectedValue(new Error("no session"));
const targetWindow = fakeWindow("/ops-center/", "?view=configs", "#dynamic_v3");
render(
,
);
// refresh 尚未结束以及确定无用户后的跳转窗口都只展示骨架,Dashboard 不会发出任何业务请求。
expect(screen.queryByTestId("ops-center-app")).toBeNull();
await waitFor(() => {
expect(targetWindow.location.replace).toHaveBeenCalledWith(
"/login?redirect=%2Fops-center%2F%3Fview%3Dconfigs%23dynamic_v3",
);
});
expect(screen.queryByTestId("ops-center-app")).toBeNull();
});
test("waits for stale-token refresh fallback before mounting the dashboard", async () => {
const refresh = deferred();
const me = deferred();
setAccessToken("stale-token");
authApi.refreshSession.mockReturnValue(refresh.promise);
authApi.getMe.mockReturnValue(me.promise);
const targetWindow = fakeWindow("/ops-center/", "?view=overview", "");
render(
,
);
expect(screen.queryByTestId("ops-center-app")).toBeNull();
await act(async () => {
refresh.reject(new Error("refresh cookie expired"));
});
await waitFor(() => expect(authApi.getMe).toHaveBeenCalledTimes(1));
expect(screen.queryByTestId("ops-center-app")).toBeNull();
await act(async () => {
me.resolve({
accessToken: "fresh-token",
permissions: ["lucky-gift:pool-credit"],
user: { id: 1, username: "ops" },
});
});
expect(await screen.findByTestId("ops-center-app")).toHaveAttribute("data-can-credit", "true");
expect(targetWindow.location.replace).not.toHaveBeenCalled();
});
function fakeWindow(pathname, search, hash) {
return {
location: {
hash,
pathname,
replace: vi.fn(),
search,
},
};
}
function deferred() {
let resolve;
let reject;
const promise = new Promise((resolvePromise, rejectPromise) => {
resolve = resolvePromise;
reject = rejectPromise;
});
return { promise, reject, resolve };
}