diff --git a/src/api/client.js b/src/api/client.js index df5d38f..7a90a58 100644 --- a/src/api/client.js +++ b/src/api/client.js @@ -88,6 +88,8 @@ apiClient.interceptors.response.use( // Refresh failed: clear auth and redirect to login deleteCookie("luciaToken"); + deleteCookie("luciaRefreshToken"); + deleteCookie("isLuciaLoggedIn"); window.location.href = "/login"; return Promise.reject(refreshError); } diff --git a/tests/api/client.test.js b/tests/api/client.test.js new file mode 100644 index 0000000..1918c4c --- /dev/null +++ b/tests/api/client.test.js @@ -0,0 +1,56 @@ +// The Lucia project. +// Copyright 2026-2026 DSP, inc. All rights reserved. +// Authors: +// imacat.yang@dsp.im (imacat), 2026/03/08 + +import { beforeEach, describe, expect, it, vi } from "vitest"; + +const { mockAxiosCreate, mockRequestUse, mockResponseUse, mockDeleteCookie } = + vi.hoisted(() => ({ + mockAxiosCreate: vi.fn(), + mockRequestUse: vi.fn(), + mockResponseUse: vi.fn(), + mockDeleteCookie: vi.fn(), + })); + +vi.mock("axios", () => ({ + default: { + create: mockAxiosCreate, + }, +})); + +vi.mock("@/utils/cookieUtil.js", () => ({ + getCookie: vi.fn(() => null), + deleteCookie: mockDeleteCookie, +})); + +vi.mock("@/api/auth.js", () => ({ + refreshTokenAndGetNew: vi.fn().mockRejectedValue(new Error("401")), +})); + +describe("apiClient response interceptor", () => { + beforeEach(() => { + vi.clearAllMocks(); + mockAxiosCreate.mockReturnValue({ + interceptors: { + request: { use: mockRequestUse }, + response: { use: mockResponseUse }, + }, + }); + }); + + it("clears all auth cookies when token refresh fails", async () => { + await import("@/api/client.js"); + const rejectedHandler = mockResponseUse.mock.calls[0][1]; + await expect( + rejectedHandler({ + response: { status: 401 }, + config: { url: "/api/my-account", headers: {} }, + }), + ).rejects.toThrow("401"); + + expect(mockDeleteCookie).toHaveBeenCalledWith("luciaToken"); + expect(mockDeleteCookie).toHaveBeenCalledWith("luciaRefreshToken"); + expect(mockDeleteCookie).toHaveBeenCalledWith("isLuciaLoggedIn"); + }); +});