forked from baron/baron-sso
89 lines
3.1 KiB
TypeScript
89 lines
3.1 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
|
const getUserMock = vi.fn();
|
|
const findPersistedOidcUserMock = vi.fn();
|
|
const removeUserMock = vi.fn();
|
|
const shouldStartLoginRedirectMock = vi.fn();
|
|
const shouldSuppressDevelopmentSessionRedirectMock = vi.fn();
|
|
|
|
vi.mock("./auth", () => ({
|
|
userManager: {
|
|
getUser: (...args: unknown[]) => getUserMock(...args),
|
|
removeUser: (...args: unknown[]) => removeUserMock(...args),
|
|
},
|
|
}));
|
|
|
|
vi.mock("./oidcStorage", () => ({
|
|
findPersistedOidcUser: (...args: unknown[]) =>
|
|
findPersistedOidcUserMock(...args),
|
|
}));
|
|
|
|
vi.mock("../../../common/core/auth", () => ({
|
|
shouldStartLoginRedirect: (...args: unknown[]) =>
|
|
shouldStartLoginRedirectMock(...args),
|
|
}));
|
|
|
|
vi.mock("../../../common/core/session", () => ({
|
|
shouldSuppressDevelopmentSessionRedirect: (...args: unknown[]) =>
|
|
shouldSuppressDevelopmentSessionRedirectMock(...args),
|
|
}));
|
|
|
|
describe("apiClient", () => {
|
|
beforeEach(() => {
|
|
vi.resetModules();
|
|
vi.stubEnv("MODE", "test");
|
|
(
|
|
window as Window & typeof globalThis & { _IS_TEST_MODE?: boolean }
|
|
)._IS_TEST_MODE = true;
|
|
window.localStorage.clear();
|
|
getUserMock.mockResolvedValue(null);
|
|
findPersistedOidcUserMock.mockReturnValue(undefined);
|
|
removeUserMock.mockResolvedValue(undefined);
|
|
shouldStartLoginRedirectMock.mockReturnValue(true);
|
|
shouldSuppressDevelopmentSessionRedirectMock.mockReturnValue(false);
|
|
});
|
|
|
|
it("injects authorization and tenant headers into requests", async () => {
|
|
getUserMock.mockResolvedValueOnce({ access_token: "live-token" });
|
|
window.localStorage.setItem("dev_tenant_id", "tenant-1");
|
|
|
|
const { default: apiClient } = await import("./apiClient");
|
|
const requestHandler =
|
|
apiClient.interceptors.request.handlers[0]?.fulfilled;
|
|
|
|
const result = await requestHandler?.({ headers: {} });
|
|
|
|
expect(result.headers.Authorization).toBe("Bearer live-token");
|
|
expect(result.headers["X-Tenant-ID"]).toBe("tenant-1");
|
|
});
|
|
|
|
it("rejects non-auth response errors without redirecting", async () => {
|
|
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
|
|
const { default: apiClient } = await import("./apiClient");
|
|
const responseHandler =
|
|
apiClient.interceptors.response.handlers[0]?.rejected;
|
|
const error = { response: { status: 500, data: { error: "boom" } } };
|
|
|
|
await expect(responseHandler?.(error)).rejects.toBe(error);
|
|
expect(warnSpy).not.toHaveBeenCalled();
|
|
expect(removeUserMock).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("warns and rejects auth failures in test mode", async () => {
|
|
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
|
|
const { default: apiClient } = await import("./apiClient");
|
|
const responseHandler =
|
|
apiClient.interceptors.response.handlers[0]?.rejected;
|
|
const error = {
|
|
response: {
|
|
status: 403,
|
|
data: { error: "authentication required" },
|
|
},
|
|
};
|
|
|
|
await expect(responseHandler?.(error)).rejects.toBe(error);
|
|
expect(warnSpy).toHaveBeenCalled();
|
|
expect(removeUserMock).not.toHaveBeenCalled();
|
|
});
|
|
});
|