// The Lucia project. // Copyright 2026-2026 DSP, inc. All rights reserved. // Authors: // imacat.yang@dsp.im (imacat), 2026/03/06 import { describe, it, expect, beforeEach } from "vitest"; import { decodeReturnTo } from "@/utils/returnToEncoding"; import { evaluateAuthNavigation } from "@/router/authGuard"; describe("router beforeEach guard logic", () => { beforeEach(() => { // Clear cookies document.cookie.split(";").forEach((c) => { const name = c.split("=")[0].trim(); if (name) { document.cookie = name + "=; Max-Age=-99999999; path=/"; } }); }); // Run the real auth guard decision logic from src/router/authGuard.ts async function runGuard(to, options = {}) { const { refreshSucceeds = true } = options; return evaluateAuthNavigation(to, { getCookie: (name) => { const cookieArr = document.cookie.split(";"); for (const cookie of cookieArr) { const c = cookie.trim(); if (c.startsWith(`${name}=`)) { return c.slice(name.length + 1); } } return null; }, refreshSession: async () => { if (!refreshSucceeds) { throw new Error("refresh failed"); } }, setLoginMarker: () => { document.cookie = "isLuciaLoggedIn=true"; }, encodeReturnTo: (path) => btoa(path), }); } it("redirects logged-in user from Login to Files", () => { document.cookie = "isLuciaLoggedIn=true"; document.cookie = "luciaToken=token"; return expect(runGuard({ name: "Login" })).resolves.toEqual({ name: "Files", }); }); it("allows unauthenticated user to visit Login", () => { return expect(runGuard({ name: "Login" })).resolves.toBeUndefined(); }); it("redirects unauthenticated user when route requiresAuth", async () => { const result = await runGuard({ name: "Files", path: "/files", fullPath: "/files", matched: [{ meta: { requiresAuth: true } }], }); expect(result.path).toBe("/login"); expect(decodeReturnTo(result.query["return-to"])).toBe("/files"); }); it("allows requiresAuth route when refresh token can refresh session", () => { document.cookie = "luciaRefreshToken=refresh-token"; return expect( runGuard( { name: "Files", path: "/files", fullPath: "/files", matched: [{ meta: { requiresAuth: true } }], }, { refreshSucceeds: true }, ), ).resolves.toBeUndefined(); }); it("redirects to login with return-to when refresh fails", async () => { document.cookie = "luciaRefreshToken=refresh-token"; const result = await runGuard( { name: "Map", path: "/discover/log/1/map", fullPath: "/discover/log/1/map?view=summary#node-2", matched: [{ meta: { requiresAuth: true } }], }, { refreshSucceeds: false }, ); expect(result.path).toBe("/login"); expect(decodeReturnTo(result.query["return-to"])).toBe( "/discover/log/1/map?view=summary#node-2", ); }); it("does not interfere with non-Login routes", () => { document.cookie = "isLuciaLoggedIn=true"; document.cookie = "luciaToken=token"; return expect( runGuard({ name: "Files", path: "/files", fullPath: "/files", matched: [{ meta: { requiresAuth: true } }], }), ).resolves.toBeUndefined(); }); });