usage-doc-auth-state.test.tsx 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /**
  2. * @vitest-environment happy-dom
  3. */
  4. import fs from "node:fs";
  5. import path from "node:path";
  6. import type { ReactNode } from "react";
  7. import { act } from "react";
  8. import { createRoot } from "react-dom/client";
  9. import { NextIntlClientProvider } from "next-intl";
  10. import { describe, expect, test, vi } from "vitest";
  11. import { UsageDocAuthProvider } from "@/app/[locale]/usage-doc/_components/usage-doc-auth-context";
  12. import { QuickLinks } from "@/app/[locale]/usage-doc/_components/quick-links";
  13. vi.mock("@/i18n/routing", () => ({
  14. Link: ({
  15. href,
  16. children,
  17. ...rest
  18. }: {
  19. href: string;
  20. children: ReactNode;
  21. className?: string;
  22. }) => (
  23. <a href={href} {...rest}>
  24. {children}
  25. </a>
  26. ),
  27. }));
  28. function loadUsageMessages() {
  29. return JSON.parse(
  30. fs.readFileSync(path.join(process.cwd(), "messages", "en", "usage.json"), "utf8")
  31. );
  32. }
  33. function renderWithAuth(node: ReactNode) {
  34. const container = document.createElement("div");
  35. document.body.appendChild(container);
  36. const root = createRoot(container);
  37. const usageMessages = loadUsageMessages();
  38. act(() => {
  39. root.render(
  40. <NextIntlClientProvider locale="en" messages={{ usage: usageMessages }} timeZone="UTC">
  41. {node}
  42. </NextIntlClientProvider>
  43. );
  44. });
  45. return {
  46. container,
  47. unmount: () => {
  48. act(() => root.unmount());
  49. container.remove();
  50. },
  51. };
  52. }
  53. describe("usage-doc auth state - HttpOnly cookie alignment", () => {
  54. test("logged-in: QuickLinks renders dashboard link when isLoggedIn=true", () => {
  55. Object.defineProperty(window, "scrollTo", { value: vi.fn(), writable: true });
  56. const { container, unmount } = renderWithAuth(
  57. <UsageDocAuthProvider isLoggedIn={true}>
  58. <QuickLinks isLoggedIn={true} />
  59. </UsageDocAuthProvider>
  60. );
  61. const dashboardLink = container.querySelector('a[href="/dashboard"]');
  62. expect(dashboardLink).not.toBeNull();
  63. unmount();
  64. });
  65. test("logged-out: QuickLinks does NOT render dashboard link when isLoggedIn=false", () => {
  66. Object.defineProperty(window, "scrollTo", { value: vi.fn(), writable: true });
  67. const { container, unmount } = renderWithAuth(
  68. <UsageDocAuthProvider isLoggedIn={false}>
  69. <QuickLinks isLoggedIn={false} />
  70. </UsageDocAuthProvider>
  71. );
  72. const dashboardLink = container.querySelector('a[href="/dashboard"]');
  73. expect(dashboardLink).toBeNull();
  74. unmount();
  75. });
  76. test("default context value is isLoggedIn=false (no provider ancestor)", () => {
  77. Object.defineProperty(window, "scrollTo", { value: vi.fn(), writable: true });
  78. const { container, unmount } = renderWithAuth(<QuickLinks isLoggedIn={false} />);
  79. const dashboardLink = container.querySelector('a[href="/dashboard"]');
  80. expect(dashboardLink).toBeNull();
  81. unmount();
  82. });
  83. test("page.tsx no longer reads document.cookie for auth state", async () => {
  84. const srcContent = fs.readFileSync(
  85. path.join(process.cwd(), "src", "app", "[locale]", "usage-doc", "page.tsx"),
  86. "utf8"
  87. );
  88. expect(srcContent).not.toContain("document.cookie");
  89. });
  90. test("page.tsx uses useUsageDocAuth hook for session state", async () => {
  91. const srcContent = fs.readFileSync(
  92. path.join(process.cwd(), "src", "app", "[locale]", "usage-doc", "page.tsx"),
  93. "utf8"
  94. );
  95. expect(srcContent).toContain("useUsageDocAuth");
  96. });
  97. test("layout.tsx wraps children with UsageDocAuthProvider", async () => {
  98. const srcContent = fs.readFileSync(
  99. path.join(process.cwd(), "src", "app", "[locale]", "usage-doc", "layout.tsx"),
  100. "utf8"
  101. );
  102. expect(srcContent).toContain("UsageDocAuthProvider");
  103. expect(srcContent).toContain("isLoggedIn={!!session}");
  104. });
  105. });