Browse Source

RHL-003-test(auth): add unit tests for session management and cookie handling

Code_Uwe 1 week ago
parent
commit
1777337204
1 changed files with 146 additions and 0 deletions
  1. 146 0
      lib/auth/session.test.js

+ 146 - 0
lib/auth/session.test.js

@@ -0,0 +1,146 @@
+import { describe, it, expect, vi, beforeEach } from "vitest";
+
+// Mock next/headers to provide a simple in-memory cookie store
+vi.mock("next/headers", () => {
+	let store = new Map();
+
+	return {
+		cookies() {
+			return {
+				get(name) {
+					const entry = store.get(name);
+					if (!entry) return undefined;
+					return { name, value: entry.value };
+				},
+				set(name, value, options) {
+					store.set(name, { value, options });
+				},
+			};
+		},
+		__cookieStore: {
+			clear() {
+				store = new Map();
+			},
+			dump() {
+				return store;
+			},
+		},
+	};
+});
+
+// Import after the mock so the module under test uses the mocked cookies()
+import {
+	createSession,
+	getSession,
+	destroySession,
+	SESSION_COOKIE_NAME,
+	SESSION_MAX_AGE_SECONDS,
+} from "./session";
+import { __cookieStore } from "next/headers";
+
+describe("auth session utilities", () => {
+	beforeEach(() => {
+		__cookieStore.clear();
+		process.env.SESSION_SECRET = "test-session-secret";
+		process.env.NODE_ENV = "test";
+	});
+
+	it("creates a session cookie with a signed JWT", async () => {
+		const jwt = await createSession({
+			userId: "user123",
+			role: "branch",
+			branchId: "NL01",
+		});
+
+		expect(typeof jwt).toBe("string");
+		expect(jwt.length).toBeGreaterThan(10);
+
+		const store = __cookieStore.dump();
+		const cookie = store.get(SESSION_COOKIE_NAME);
+
+		expect(cookie).toBeDefined();
+		expect(cookie.value).toBe(jwt);
+
+		expect(cookie.options).toMatchObject({
+			httpOnly: true,
+			secure: false, // NODE_ENV = "test"
+			sameSite: "lax",
+			path: "/",
+			maxAge: SESSION_MAX_AGE_SECONDS,
+		});
+	});
+
+	it("reads a valid session from cookie", async () => {
+		await createSession({
+			userId: "user456",
+			role: "admin",
+			branchId: null,
+		});
+
+		const session = await getSession();
+
+		expect(session).toEqual({
+			userId: "user456",
+			role: "admin",
+			branchId: null,
+		});
+	});
+
+	it("returns null when no session cookie is present", async () => {
+		const session = await getSession();
+		expect(session).toBeNull();
+	});
+
+	it("returns null and clears cookie when token is invalid", async () => {
+		// Manually set an invalid JWT value
+		const store = __cookieStore.dump();
+		store.set(SESSION_COOKIE_NAME, {
+			value: "not-a-valid-jwt",
+			options: {
+				httpOnly: true,
+				secure: false,
+				sameSite: "lax",
+				path: "/",
+				maxAge: SESSION_MAX_AGE_SECONDS,
+			},
+		});
+
+		const session = await getSession();
+		expect(session).toBeNull();
+
+		const updatedStore = __cookieStore.dump();
+		const cookie = updatedStore.get(SESSION_COOKIE_NAME);
+
+		expect(cookie).toBeDefined();
+		expect(cookie.value).toBe("");
+		expect(cookie.options.maxAge).toBe(0);
+	});
+
+	it("destroySession clears the session cookie when it exists", async () => {
+		await createSession({
+			userId: "user789",
+			role: "branch",
+			branchId: "NL02",
+		});
+
+		destroySession();
+
+		const store = __cookieStore.dump();
+		const cookie = store.get(SESSION_COOKIE_NAME);
+
+		expect(cookie).toBeDefined();
+		expect(cookie.value).toBe("");
+		expect(cookie.options.maxAge).toBe(0);
+	});
+
+	it("destroySession sets an empty cookie even if none existed before", () => {
+		destroySession();
+
+		const store = __cookieStore.dump();
+		const cookie = store.get(SESSION_COOKIE_NAME);
+
+		expect(cookie).toBeDefined();
+		expect(cookie.value).toBe("");
+		expect(cookie.options.maxAge).toBe(0);
+	});
+});