Files
pi-ku/frontend/src/api/apiClient.test.ts
T
RamVignesh B 3c9c72d25f Feature/ssl integration (#1)
* feat: update E2E testing configuration to use ssl

* fix: add IPv6 loopback support to mkcert generation command in CI workflow

* feat: centralize SSL certificate generation into a reusable workflow job

* fix: use static ip  in mkcert command

* fix: correct mkcert command args

* feat: implement certificate caching in CI workflow to persist SSL files across jobs

* refactor: optimize CI workflow caching

* ci: implement certificate caching in workflow

* fix: correct certificate caching keys and fix environment file paths in CI workflows

* fix: correct environment file paths and parallelize frontend dependency installation in CI workflow

* test: set TZ environment variable to Asia/Kolkata in vitest configuration

* fix: force en-US locale in Intl formatters to ensure consistent date and time output

* fix: update MAILPIT_API_URL protocol from https to http in e2e environment example

* chore: set test timezone to Asia/Kolkata

* ci: add sll support and enhance e2e workflow

* ci: improve compatibility for docker-compose execution

* refactor: improve container orchestration detection and fallback logic in e2e test script

* feat: add container runtime validation and force docker usage in CI environment

* feat: add caching for Playwright dependencies in CI workflow

* chore: update restart policy to unless-stopped for postgres and mailpit services in e2e docker-compose

---------

Co-authored-by: ramvignesh-b <ramvignesh-b@github.com>
2026-04-17 02:04:11 +05:30

144 lines
4.0 KiB
TypeScript

import { HttpResponse, http } from "msw";
import {
afterAll,
beforeAll,
beforeEach,
describe,
expect,
it,
vi,
} from "vitest";
import { mockUser } from "../../test/fixtures/user.fixture";
import { server } from "../../test/mocks/server";
import { useAuthStore } from "../store/useAuthStore";
import { api } from "./apiClient";
const VITE_API_URL = "http://piku-server";
beforeEach(() => {
useAuthStore.setState({
accessToken: null,
user: null,
isInitializing: false,
});
});
beforeAll(() => {
vi.stubEnv("VITE_API_URL", VITE_API_URL);
});
afterAll(() => {
vi.unstubAllEnvs();
});
describe("request interceptor", () => {
it("should attach Bearer token from the auth store to outgoing requests", async () => {
useAuthStore.getState().setAuth("my-token", mockUser);
let capturedAuthHeader = "";
server.use(
http.get(`${VITE_API_URL}/api/auth/me/`, ({ request }) => {
capturedAuthHeader = request.headers.get("Authorization") ?? "";
return HttpResponse.json(mockUser);
}),
);
await api.get("/api/auth/me/");
expect(capturedAuthHeader).toBe("Bearer my-token");
});
it("should not send Authorization header when the store has no token", async () => {
let capturedAuthHeader: string | null = "";
server.use(
http.get(`${VITE_API_URL}/api/auth/me/`, ({ request }) => {
capturedAuthHeader = request.headers.get("Authorization");
return HttpResponse.json({});
}),
);
await api.get("/api/auth/me/");
expect(capturedAuthHeader).toBeNull();
});
});
describe("response interceptor", () => {
it("should call /refresh once on 401, then retry the original request with the new token", async () => {
useAuthStore.getState().setAuth("expired-token", mockUser);
let meApiCallCount = 0;
let _refreshApiCallCount = 0;
server.use(
http.get(`${VITE_API_URL}/api/auth/me/`, ({ request }) => {
meApiCallCount++;
if (request.headers.get("Authorization") === "Bearer expired-token") {
return new HttpResponse(null, { status: 401 });
}
return HttpResponse.json(mockUser);
}),
http.post(`${VITE_API_URL}/api/auth/refresh/`, () => {
_refreshApiCallCount++;
return HttpResponse.json({ access: "refreshed-token" });
}),
);
const response = await api.get("/api/auth/me/");
expect(_refreshApiCallCount).toBe(1);
expect(meApiCallCount).toBe(2);
expect(response.data).toEqual(mockUser);
});
it("should update the auth store access token after a successful refresh", async () => {
useAuthStore.getState().setAuth("expired-token", mockUser);
server.use(
http.get(`${VITE_API_URL}/api/auth/me/`, ({ request }) => {
if (request.headers.get("Authorization") === "Bearer expired-token") {
return new HttpResponse(null, { status: 401 });
}
return HttpResponse.json(mockUser);
}),
http.post(`${VITE_API_URL}/api/auth/refresh/`, () =>
HttpResponse.json({ access: "refreshed-token" }),
),
);
await api.get("/api/auth/me/");
expect(useAuthStore.getState().accessToken).toBe("refreshed-token");
});
it("should call clearAuth and return the latest error when refresh also fails", async () => {
useAuthStore.getState().setAuth("expired-token", mockUser);
server.use(
http.get(
`${VITE_API_URL}/api/auth/me/`,
() =>
new HttpResponse(JSON.stringify({ detail: "Invalid token" }), {
status: 401,
}),
),
http.post(
`${VITE_API_URL}/api/auth/refresh/`,
() =>
new HttpResponse(JSON.stringify({ detail: "Refresh failed" }), {
status: 401,
}),
),
);
await expect(api.get("/api/auth/me/")).rejects.toThrow(
expect.objectContaining({
response: expect.objectContaining({
data: { detail: "Refresh failed" },
}),
}),
);
expect(useAuthStore.getState().accessToken).toBeNull();
expect(useAuthStore.getState().user).toBeNull();
});
});