Files
HiveGrid-Wireframes/hivegrid-cloud/packages/view-models/src/auth/session-list.vm.test.ts
T

81 lines
3.1 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { buildSessionListVM, type SessionDeviceInput } from "./session-list.vm.js";
const NOW = Date.UTC(2026, 5, 18, 12, 0, 0);
function session(overrides: Partial<SessionDeviceInput> & { id: string }): SessionDeviceInput {
return {
lastSeenAt: new Date(NOW),
...overrides,
};
}
describe("buildSessionListVM", () => {
it("returns an empty state when there are no sessions", () => {
expect(buildSessionListVM({ sessions: [], currentSessionId: "s1", nowMs: NOW })).toEqual({ status: "empty" });
});
it("flags the current device, forbids revoking it, and counts the others", () => {
const vm = buildSessionListVM({
sessions: [
session({ id: "s1", userAgent: "Firefox", approxLocation: "Germany" }),
session({ id: "s2", deviceLabel: "iPhone", trustedAt: new Date(NOW) }),
],
currentSessionId: "s1",
nowMs: NOW,
});
expect(vm.status).toBe("ready");
if (vm.status !== "ready") return;
const current = vm.data.devices.find((d) => d.id === "s1")!;
const other = vm.data.devices.find((d) => d.id === "s2")!;
expect(current.isCurrent).toBe(true);
expect(current.canRevoke).toBe(false);
expect(current.deviceLabel).toBe("Firefox");
expect(other.isCurrent).toBe(false);
expect(other.canRevoke).toBe(true);
expect(other.trusted).toBe(true);
expect(vm.data.otherActiveCount).toBe(1);
expect(vm.data.canRevokeOthers).toBe(true);
});
it("orders the current device first", () => {
const vm = buildSessionListVM({
sessions: [session({ id: "s2" }), session({ id: "s1" })],
currentSessionId: "s1",
nowMs: NOW,
});
if (vm.status !== "ready") throw new Error("expected ready");
expect(vm.data.devices[0].id).toBe("s1");
});
it("falls back to an i18n key when no device label or user agent is present", () => {
const vm = buildSessionListVM({ sessions: [session({ id: "s1" })], currentSessionId: null, nowMs: NOW });
if (vm.status !== "ready") throw new Error("expected ready");
expect(vm.data.devices[0].deviceLabel).toBeUndefined();
expect(vm.data.devices[0].deviceLabelFallbackKey).toBe("settings.security.sessions.unknownDevice");
});
it.each([
[30 * 1000, "justNow", undefined],
[5 * 60 * 1000, "minutes", 5],
[3 * 60 * 60 * 1000, "hours", 3],
[2 * 24 * 60 * 60 * 1000, "days", 2],
])("buckets last-seen %ims ago as %s", (ago, bucket, count) => {
const vm = buildSessionListVM({
sessions: [session({ id: "s1", lastSeenAt: new Date(NOW - (ago as number)) })],
currentSessionId: "s1",
nowMs: NOW,
});
if (vm.status !== "ready") throw new Error("expected ready");
expect(vm.data.devices[0].lastSeenBucket).toBe(bucket);
expect(vm.data.devices[0].lastSeenCount).toBe(count);
});
it("has no revocable others when only the current device is active", () => {
const vm = buildSessionListVM({ sessions: [session({ id: "s1" })], currentSessionId: "s1", nowMs: NOW });
if (vm.status !== "ready") throw new Error("expected ready");
expect(vm.data.otherActiveCount).toBe(0);
expect(vm.data.canRevokeOthers).toBe(false);
});
});