87 lines
2.8 KiB
TypeScript
87 lines
2.8 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
import { createPinia, setActivePinia } from "pinia";
|
|
|
|
vi.mock("../router", () => ({
|
|
default: {
|
|
replace: vi.fn(),
|
|
},
|
|
}));
|
|
|
|
vi.mock("../api/authClient", () => ({
|
|
extendToken: vi.fn(),
|
|
unlockSession: vi.fn(),
|
|
}));
|
|
|
|
describe("session manager idle recovery", () => {
|
|
beforeEach(() => {
|
|
vi.resetModules();
|
|
vi.useFakeTimers();
|
|
setActivePinia(createPinia());
|
|
const storage = (() => {
|
|
const data = new Map<string, string>();
|
|
return {
|
|
getItem: (key: string) => data.get(key) ?? null,
|
|
setItem: (key: string, value: string) => {
|
|
data.set(key, String(value));
|
|
},
|
|
removeItem: (key: string) => {
|
|
data.delete(key);
|
|
},
|
|
clear: () => {
|
|
data.clear();
|
|
},
|
|
};
|
|
})();
|
|
Object.defineProperty(window, "localStorage", {
|
|
value: storage,
|
|
configurable: true,
|
|
});
|
|
Object.defineProperty(window, "sessionStorage", {
|
|
value: storage,
|
|
configurable: true,
|
|
});
|
|
Object.defineProperty(window, "BroadcastChannel", {
|
|
value: class {
|
|
onmessage: ((event: MessageEvent) => void) | null = null;
|
|
postMessage() {}
|
|
close() {}
|
|
},
|
|
configurable: true,
|
|
});
|
|
});
|
|
|
|
it("locks instead of refreshing activity after long inactivity when user activity resumes", async () => {
|
|
vi.setSystemTime(new Date("2026-03-10T01:00:00.000Z"));
|
|
const { useSessionStore } = await import("../store/session");
|
|
const { IDLE_TIMEOUT_MINUTES, AUTO_LOGOUT_TIMEOUT_HOURS, markUserActive } = await import("./sessionManager");
|
|
const session = useSessionStore();
|
|
const oldTs = Date.now() - (IDLE_TIMEOUT_MINUTES * 60 * 1000 + 1_000);
|
|
|
|
session.recordUserActivity(oldTs);
|
|
session.recordNetworkActivity(oldTs);
|
|
|
|
markUserActive(Date.now());
|
|
|
|
expect(session.locked).toBe(true);
|
|
expect(session.lockReason).toBe("idle");
|
|
expect(session.lockAutoLogoutDeadlineAt).toBe(oldTs + AUTO_LOGOUT_TIMEOUT_HOURS * 60 * 60 * 1000);
|
|
});
|
|
|
|
it("locks instead of refreshing activity after long inactivity when network activity resumes", async () => {
|
|
vi.setSystemTime(new Date("2026-03-10T01:00:00.000Z"));
|
|
const { useSessionStore } = await import("../store/session");
|
|
const { IDLE_TIMEOUT_MINUTES, AUTO_LOGOUT_TIMEOUT_HOURS, markNetworkActive } = await import("./sessionManager");
|
|
const session = useSessionStore();
|
|
const oldTs = Date.now() - (IDLE_TIMEOUT_MINUTES * 60 * 1000 + 1_000);
|
|
|
|
session.recordUserActivity(oldTs);
|
|
session.recordNetworkActivity(oldTs);
|
|
|
|
markNetworkActive(Date.now());
|
|
|
|
expect(session.locked).toBe(true);
|
|
expect(session.lockReason).toBe("idle");
|
|
expect(session.lockAutoLogoutDeadlineAt).toBe(oldTs + AUTO_LOGOUT_TIMEOUT_HOURS * 60 * 60 * 1000);
|
|
});
|
|
});
|