From 9333c354fa47fc5bb2accec73d03f34d9a8f27bf Mon Sep 17 00:00:00 2001 From: manNomi Date: Sun, 2 Aug 2026 01:44:22 +0900 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20=EC=84=B8=EC=85=98=20=EC=A0=95?= =?UTF-8?q?=EB=A6=AC=20=EC=8B=9C=20=EC=96=B4=EB=93=9C=EB=AF=BC=20API=20?= =?UTF-8?q?=ED=99=98=EA=B2=BD=20=EC=84=A0=ED=83=9D=EC=9D=B4=20=EC=B4=88?= =?UTF-8?q?=EA=B8=B0=ED=99=94=EB=90=98=EB=8A=94=20=EB=AC=B8=EC=A0=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/admin/src/lib/auth/session.test.ts | 55 ++++++++++++------- apps/admin/src/lib/auth/session.ts | 14 +---- apps/admin/src/lib/utils/localStorage.test.ts | 9 --- apps/admin/src/lib/utils/localStorage.ts | 8 --- 4 files changed, 38 insertions(+), 48 deletions(-) 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); - } -};