session.test.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. import { describe, it, expect, vi, beforeEach } from "vitest";
  2. // Mock next/headers to provide a simple in-memory cookie store
  3. vi.mock("next/headers", () => {
  4. let store = new Map();
  5. return {
  6. cookies() {
  7. return {
  8. get(name) {
  9. const entry = store.get(name);
  10. if (!entry) return undefined;
  11. return { name, value: entry.value };
  12. },
  13. set(name, value, options) {
  14. store.set(name, { value, options });
  15. },
  16. };
  17. },
  18. __cookieStore: {
  19. clear() {
  20. store = new Map();
  21. },
  22. dump() {
  23. return store;
  24. },
  25. },
  26. };
  27. });
  28. // Import after the mock so the module under test uses the mocked cookies()
  29. import {
  30. createSession,
  31. getSession,
  32. destroySession,
  33. SESSION_COOKIE_NAME,
  34. SESSION_MAX_AGE_SECONDS,
  35. } from "./session";
  36. import { __cookieStore } from "next/headers";
  37. describe("auth session utilities", () => {
  38. beforeEach(() => {
  39. __cookieStore.clear();
  40. // Align tests with env policy: strong secret (>= 32 chars)
  41. process.env.SESSION_SECRET = "x".repeat(64);
  42. process.env.NODE_ENV = "test";
  43. });
  44. it("creates a session cookie with a signed JWT", async () => {
  45. const jwt = await createSession({
  46. userId: "user123",
  47. role: "branch",
  48. branchId: "NL01",
  49. });
  50. expect(typeof jwt).toBe("string");
  51. expect(jwt.length).toBeGreaterThan(10);
  52. const store = __cookieStore.dump();
  53. const cookie = store.get(SESSION_COOKIE_NAME);
  54. expect(cookie).toBeDefined();
  55. expect(cookie.value).toBe(jwt);
  56. expect(cookie.options).toMatchObject({
  57. httpOnly: true,
  58. secure: false, // NODE_ENV = "test"
  59. sameSite: "lax",
  60. path: "/",
  61. maxAge: SESSION_MAX_AGE_SECONDS,
  62. });
  63. });
  64. it("reads a valid session from cookie", async () => {
  65. await createSession({
  66. userId: "user456",
  67. role: "admin",
  68. branchId: null,
  69. });
  70. const session = await getSession();
  71. expect(session).toEqual({
  72. userId: "user456",
  73. role: "admin",
  74. branchId: null,
  75. });
  76. });
  77. it("returns null when no session cookie is present", async () => {
  78. const session = await getSession();
  79. expect(session).toBeNull();
  80. });
  81. it("returns null and clears cookie when token is invalid", async () => {
  82. // Manually set an invalid JWT value
  83. const store = __cookieStore.dump();
  84. store.set(SESSION_COOKIE_NAME, {
  85. value: "not-a-valid-jwt",
  86. options: {
  87. httpOnly: true,
  88. secure: false,
  89. sameSite: "lax",
  90. path: "/",
  91. maxAge: SESSION_MAX_AGE_SECONDS,
  92. },
  93. });
  94. const session = await getSession();
  95. expect(session).toBeNull();
  96. const updatedStore = __cookieStore.dump();
  97. const cookie = updatedStore.get(SESSION_COOKIE_NAME);
  98. expect(cookie).toBeDefined();
  99. expect(cookie.value).toBe("");
  100. expect(cookie.options.maxAge).toBe(0);
  101. });
  102. it("destroySession clears the session cookie when it exists", async () => {
  103. await createSession({
  104. userId: "user789",
  105. role: "branch",
  106. branchId: "NL02",
  107. });
  108. destroySession();
  109. const store = __cookieStore.dump();
  110. const cookie = store.get(SESSION_COOKIE_NAME);
  111. expect(cookie).toBeDefined();
  112. expect(cookie.value).toBe("");
  113. expect(cookie.options.maxAge).toBe(0);
  114. });
  115. it("destroySession sets an empty cookie even if none existed before", () => {
  116. destroySession();
  117. const store = __cookieStore.dump();
  118. const cookie = store.get(SESSION_COOKIE_NAME);
  119. expect(cookie).toBeDefined();
  120. expect(cookie.value).toBe("");
  121. expect(cookie.options.maxAge).toBe(0);
  122. });
  123. });