diff --git a/apps/admin/src/lib/auth/session.test.ts b/apps/admin/src/lib/auth/session.test.ts index 2c623e5d..13365654 100644 --- a/apps/admin/src/lib/auth/session.test.ts +++ b/apps/admin/src/lib/auth/session.test.ts @@ -1,44 +1,59 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; -const { removeAccessToken, removeAdminApiEnvironment, saveAdminApiEnvironment } = vi.hoisted(() => ({ +const { removeAccessToken } = vi.hoisted(() => ({ removeAccessToken: vi.fn(), - removeAdminApiEnvironment: vi.fn(), - saveAdminApiEnvironment: vi.fn(), })); vi.mock("@/lib/api/auth", () => ({ reissueAccessTokenApi: vi.fn(), })); -vi.mock("@/lib/utils/localStorage", () => ({ - loadAccessToken: vi.fn(), - removeAccessToken, - removeAdminApiEnvironment, - saveAccessToken: vi.fn(), - saveAdminApiEnvironment, -})); +// 환경(stage/prod) 저장·조회 함수는 실제 구현(jsdom localStorage)을 그대로 사용해, +// clearSession()이 저장된 환경 값을 건드리지 않는지 회귀 테스트로 검증한다. +vi.mock("@/lib/utils/localStorage", async (importOriginal) => { + const actual = await importOriginal(); + return { + ...actual, + loadAccessToken: vi.fn(), + removeAccessToken, + saveAccessToken: vi.fn(), + }; +}); describe("switchAdminApiEnvironment", () => { beforeEach(() => { removeAccessToken.mockReset(); - removeAdminApiEnvironment.mockReset(); - saveAdminApiEnvironment.mockReset(); + localStorage.clear(); }); - it("세션(access token, 환경 값)을 모두 지운 뒤 새 환경을 저장한다", async () => { + it("access token을 지운 뒤 새 환경을 저장하고 로그인 페이지로 리다이렉트한다", async () => { const { switchAdminApiEnvironment } = await import("./session"); + const { loadAdminApiEnvironment } = await import("@/lib/utils/localStorage"); const redirect = vi.fn(); - const callOrder: string[] = []; - - removeAdminApiEnvironment.mockImplementation(() => callOrder.push("removeAdminApiEnvironment")); - saveAdminApiEnvironment.mockImplementation(() => callOrder.push("saveAdminApiEnvironment")); switchAdminApiEnvironment("prod", redirect); expect(removeAccessToken).toHaveBeenCalledOnce(); - expect(removeAdminApiEnvironment).toHaveBeenCalledOnce(); - expect(saveAdminApiEnvironment).toHaveBeenCalledWith("prod"); - expect(callOrder).toEqual(["removeAdminApiEnvironment", "saveAdminApiEnvironment"]); + expect(loadAdminApiEnvironment()).toBe("prod"); expect(redirect).toHaveBeenCalledWith("/auth/login"); }); }); + +describe("clearSession", () => { + beforeEach(() => { + removeAccessToken.mockReset(); + localStorage.clear(); + }); + + it("access token은 지우지만 저장된 어드민 API 환경 값은 유지한다 (회귀 테스트)", async () => { + const { clearSession } = await import("./session"); + const { loadAdminApiEnvironment, saveAdminApiEnvironment } = await import("@/lib/utils/localStorage"); + + saveAdminApiEnvironment("stage"); + + clearSession(); + + expect(removeAccessToken).toHaveBeenCalledOnce(); + expect(loadAdminApiEnvironment()).toBe("stage"); + }); +}); diff --git a/apps/admin/src/lib/auth/session.ts b/apps/admin/src/lib/auth/session.ts index daa7ebfd..ebd349fc 100644 --- a/apps/admin/src/lib/auth/session.ts +++ b/apps/admin/src/lib/auth/session.ts @@ -1,13 +1,7 @@ import { reissueAccessTokenApi } from "@/lib/api/auth"; import type { AdminApiEnvironment } from "@/lib/auth/environment"; import { isTokenExpired } from "@/lib/utils/jwtUtils"; -import { - loadAccessToken, - removeAccessToken, - removeAdminApiEnvironment, - saveAccessToken, - saveAdminApiEnvironment, -} from "@/lib/utils/localStorage"; +import { loadAccessToken, removeAccessToken, saveAccessToken, saveAdminApiEnvironment } from "@/lib/utils/localStorage"; let reissuePromise: Promise | null = null; let sessionVersion = 0; @@ -30,13 +24,11 @@ export const clearSession = () => { sessionVersion += 1; reissuePromise = null; removeAccessToken(); - removeAdminApiEnvironment(); }; /** - * 어드민 API 환경(stage/prod)을 전환한다. clearSession()이 환경 저장 키까지 함께 지우므로, - * 반드시 clearSession → saveAdminApiEnvironment 순서로 처리해야 새 환경 값이 유지된다. - * 이후 react-query 캐시 등 메모리 상태를 확실히 비우기 위해 전체 페이지 이동으로 리다이렉트한다. + * 어드민 API 환경(stage/prod)을 전환한다. 세션(access token)을 정리한 뒤 새 환경 값을 저장하고, + * react-query 캐시 등 메모리 상태를 확실히 비우기 위해 전체 페이지 이동으로 리다이렉트한다. * redirect는 테스트에서 주입할 수 있도록 매개변수로 분리했다. */ export const switchAdminApiEnvironment = ( diff --git a/apps/admin/src/lib/utils/localStorage.test.ts b/apps/admin/src/lib/utils/localStorage.test.ts index e88eb955..b33f6dbb 100644 --- a/apps/admin/src/lib/utils/localStorage.test.ts +++ b/apps/admin/src/lib/utils/localStorage.test.ts @@ -4,7 +4,6 @@ import { loadAccessToken, loadAdminApiEnvironment, removeAccessToken, - removeAdminApiEnvironment, saveAccessToken, saveAdminApiEnvironment, } from "./localStorage"; @@ -55,14 +54,6 @@ describe("어드민 API 환경 localStorage 저장", () => { expect(loadAdminApiEnvironment()).toBe("prod"); }); - it("환경 값을 제거한다", () => { - saveAdminApiEnvironment("stage"); - - removeAdminApiEnvironment(); - - expect(loadAdminApiEnvironment()).toBeNull(); - }); - it("레거시 값 'dev'는 'stage'로 해석한다", () => { localStorage.setItem(ADMIN_API_ENVIRONMENT_KEY, "dev"); diff --git a/apps/admin/src/lib/utils/localStorage.ts b/apps/admin/src/lib/utils/localStorage.ts index e68a6058..a71c019d 100644 --- a/apps/admin/src/lib/utils/localStorage.ts +++ b/apps/admin/src/lib/utils/localStorage.ts @@ -53,11 +53,3 @@ export const saveAdminApiEnvironment = (environment: AdminApiEnvironment) => { console.error("Could not save admin api environment", err); } }; - -export const removeAdminApiEnvironment = () => { - try { - localStorage.removeItem(ADMIN_API_ENVIRONMENT_KEY); - } catch (err) { - console.error("Could not remove admin api environment", err); - } -};