// 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"; 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=/"; } }); }); // Simulate the guard logic from router/index.ts async function runGuard(to, options = {}) { const { refreshSucceeds = true } = options; const hasLoginMarker = document.cookie .split(";") .some((c) => c.trim().startsWith("isLuciaLoggedIn=")); const hasAccessToken = document.cookie .split(";") .some((c) => c.trim().startsWith("luciaToken=")); const hasRefreshToken = document.cookie .split(";") .some((c) => c.trim().startsWith("luciaRefreshToken=")); const isAuthenticated = hasLoginMarker && hasAccessToken; if (to.name === "Login") { if (isAuthenticated) return { name: "Files" }; } const requiresAuth = (to.matched || []).some((r) => r.meta?.requiresAuth); if (requiresAuth && !isAuthenticated) { if (hasRefreshToken) { if (refreshSucceeds) return undefined; } return { path: "/login", query: { "return-to": btoa(to.fullPath || to.path || "/"), }, }; } return undefined; } 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(atob(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(atob(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(); }); });