优化桌面端界面布局
This commit is contained in:
@@ -8,14 +8,32 @@ vi.mock("../router", () => ({
|
||||
}));
|
||||
|
||||
const channelPostMessage = vi.fn();
|
||||
const runtimeMocks = vi.hoisted(() => ({
|
||||
isTauriRuntime: vi.fn(() => false),
|
||||
}));
|
||||
|
||||
vi.mock("../runtime", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../runtime")>();
|
||||
return {
|
||||
...actual,
|
||||
isTauriRuntime: runtimeMocks.isTauriRuntime,
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../api/authClient", () => ({
|
||||
extendToken: vi.fn(),
|
||||
}));
|
||||
|
||||
const encodeJson = (value: unknown): string => Buffer.from(JSON.stringify(value)).toString("base64url");
|
||||
|
||||
const createJwt = (expiresAtMs: number): string =>
|
||||
`${encodeJson({ alg: "none", typ: "JWT" })}.${encodeJson({ exp: Math.floor(expiresAtMs / 1000) })}.signature`;
|
||||
|
||||
describe("session manager idle logout", () => {
|
||||
beforeEach(() => {
|
||||
vi.resetModules();
|
||||
vi.clearAllMocks();
|
||||
runtimeMocks.isTauriRuntime.mockReturnValue(false);
|
||||
vi.useFakeTimers();
|
||||
setActivePinia(createPinia());
|
||||
const storage = (() => {
|
||||
@@ -82,6 +100,24 @@ describe("session manager idle logout", () => {
|
||||
expect(router.replace).toHaveBeenCalledWith("/login");
|
||||
});
|
||||
|
||||
it("does not force desktop logout after local inactivity", async () => {
|
||||
runtimeMocks.isTauriRuntime.mockReturnValue(true);
|
||||
vi.setSystemTime(new Date("2026-03-10T01:00:00.000Z"));
|
||||
const { useSessionStore } = await import("../store/session");
|
||||
const router = (await import("../router")).default;
|
||||
const { IDLE_TIMEOUT_MINUTES, markUserActive } = await import("./sessionManager");
|
||||
const session = useSessionStore();
|
||||
const oldTs = Date.now() - (IDLE_TIMEOUT_MINUTES * 60 * 1000 + 1_000);
|
||||
|
||||
session.recordUserActivity(oldTs);
|
||||
|
||||
markUserActive(Date.now());
|
||||
|
||||
expect(window.sessionStorage.getItem("ctms_logout_reason")).toBeNull();
|
||||
expect(router.replace).not.toHaveBeenCalled();
|
||||
expect(session.timeoutWarningVisible).toBe(false);
|
||||
});
|
||||
|
||||
it("clears the timeout warning when user activity resumes", async () => {
|
||||
vi.setSystemTime(new Date("2026-03-10T01:00:00.000Z"));
|
||||
const { useSessionStore } = await import("../store/session");
|
||||
@@ -115,4 +151,27 @@ describe("session manager idle logout", () => {
|
||||
expect(channelPostMessage).toHaveBeenCalledWith({ type: "TOKEN_UPDATED", token: "new-token" });
|
||||
expect(window.localStorage.getItem("ctms_auth_broadcast")).toBeNull();
|
||||
});
|
||||
|
||||
it("extends desktop tokens even when there has been no recent local activity", async () => {
|
||||
vi.setSystemTime(new Date("2026-03-10T01:00:00.000Z"));
|
||||
const { setToken } = await import("../utils/auth");
|
||||
await setToken(createJwt(Date.now() + 30_000));
|
||||
runtimeMocks.isTauriRuntime.mockReturnValue(true);
|
||||
const { extendToken } = await import("../api/authClient");
|
||||
vi.mocked(extendToken).mockResolvedValue({
|
||||
data: {
|
||||
accessToken: createJwt(Date.now() + 3_600_000),
|
||||
expiresAt: "2026-03-10T02:00:00.000Z",
|
||||
},
|
||||
} as any);
|
||||
const { useSessionStore } = await import("../store/session");
|
||||
const { IDLE_TIMEOUT_MINUTES, startTokenKeepAlive } = await import("./sessionManager");
|
||||
const session = useSessionStore();
|
||||
session.recordUserActivity(Date.now() - (IDLE_TIMEOUT_MINUTES * 60 * 1000 + 1_000));
|
||||
|
||||
startTokenKeepAlive();
|
||||
await vi.advanceTimersByTimeAsync(10_000);
|
||||
|
||||
expect(extendToken).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user