login_frame_test.tsx 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. import { cleanup, assertEquals, render, screen, fireEvent, act } from "./setup.ts";
  2. import LoginFrame from "../../islands/LoginFrame.tsx";
  3. // Mock fetch to prevent actual network calls
  4. const originalFetch = globalThis.fetch;
  5. function mockFetch(response = { success: false }) {
  6. globalThis.fetch = () =>
  7. Promise.resolve(new Response(JSON.stringify(response), {
  8. headers: { "Content-Type": "application/json" },
  9. }));
  10. }
  11. function restoreFetch() {
  12. globalThis.fetch = originalFetch;
  13. }
  14. // Mock $loading to prevent errors
  15. function mockLoading() {
  16. globalThis.$loading = { show: () => {}, hide: () => {} };
  17. }
  18. function restoreLoading() {
  19. delete globalThis.$loading;
  20. }
  21. Deno.test({
  22. name: "LoginFrame - login mode renders email and password inputs",
  23. async fn() {
  24. mockFetch();
  25. const { container } = render(<LoginFrame mode="login" />);
  26. // Wait for useEffect to settle
  27. await act(async () => {});
  28. assertEquals(screen.getByPlaceholderText("Your email") !== null, true);
  29. assertEquals(screen.getByPlaceholderText("Your password") !== null, true);
  30. cleanup();
  31. restoreFetch();
  32. },
  33. sanitizeResources: false,
  34. sanitizeOps: false,
  35. });
  36. Deno.test({
  37. name: "LoginFrame - login mode renders Sign in button",
  38. async fn() {
  39. mockFetch();
  40. const { container } = render(<LoginFrame mode="login" />);
  41. await act(async () => {});
  42. assertEquals(screen.getByText("Sign in").tagName, "BUTTON");
  43. cleanup();
  44. restoreFetch();
  45. },
  46. sanitizeResources: false,
  47. sanitizeOps: false,
  48. });
  49. Deno.test({
  50. name: "LoginFrame - login mode renders Go Register button",
  51. async fn() {
  52. mockFetch();
  53. render(<LoginFrame mode="login" />);
  54. await act(async () => {});
  55. assertEquals(screen.getByText("Go Register").tagName, "BUTTON");
  56. cleanup();
  57. restoreFetch();
  58. },
  59. sanitizeResources: false,
  60. sanitizeOps: false,
  61. });
  62. Deno.test({
  63. name: "LoginFrame - login mode does not render confirm password",
  64. async fn() {
  65. mockFetch();
  66. render(<LoginFrame mode="login" />);
  67. await act(async () => {});
  68. const confirmInput = screen.queryByPlaceholderText("Confirm your password");
  69. assertEquals(confirmInput, null);
  70. cleanup();
  71. restoreFetch();
  72. },
  73. sanitizeResources: false,
  74. sanitizeOps: false,
  75. });
  76. Deno.test({
  77. name: "LoginFrame - register mode renders confirm password input",
  78. fn() {
  79. mockFetch();
  80. render(<LoginFrame mode="register" />);
  81. assertEquals(screen.getByPlaceholderText("Confirm your password") !== null, true);
  82. cleanup();
  83. restoreFetch();
  84. },
  85. sanitizeResources: false,
  86. sanitizeOps: false,
  87. });
  88. Deno.test({
  89. name: "LoginFrame - register mode renders Register button",
  90. fn() {
  91. mockFetch();
  92. render(<LoginFrame mode="register" />);
  93. assertEquals(screen.getByText("Register").tagName, "BUTTON");
  94. cleanup();
  95. restoreFetch();
  96. },
  97. sanitizeResources: false,
  98. sanitizeOps: false,
  99. });
  100. Deno.test({
  101. name: "LoginFrame - register mode renders Go Login button",
  102. fn() {
  103. mockFetch();
  104. render(<LoginFrame mode="register" />);
  105. assertEquals(screen.getByText("Go Login").tagName, "BUTTON");
  106. cleanup();
  107. restoreFetch();
  108. },
  109. sanitizeResources: false,
  110. sanitizeOps: false,
  111. });
  112. Deno.test({
  113. name: "LoginFrame - submit with empty fields sets error state",
  114. async fn() {
  115. mockFetch();
  116. mockLoading();
  117. render(<LoginFrame mode="login" />);
  118. await act(async () => {});
  119. const submitBtn = screen.getByText("Sign in");
  120. await act(async () => {
  121. fireEvent.click(submitBtn);
  122. });
  123. // Check that error borders appear on empty inputs
  124. const emailInput = screen.getByPlaceholderText("Your email");
  125. const passwordInput = screen.getByPlaceholderText("Your password");
  126. assertEquals(emailInput.className.includes("border-red-600"), true);
  127. assertEquals(passwordInput.className.includes("border-red-600"), true);
  128. cleanup();
  129. restoreFetch();
  130. restoreLoading();
  131. },
  132. sanitizeResources: false,
  133. sanitizeOps: false,
  134. });
  135. Deno.test({
  136. name: "LoginFrame - typing clears error state",
  137. async fn() {
  138. mockFetch();
  139. mockLoading();
  140. render(<LoginFrame mode="login" />);
  141. await act(async () => {});
  142. // Trigger error
  143. await act(async () => {
  144. fireEvent.click(screen.getByText("Sign in"));
  145. });
  146. const emailInput = screen.getByPlaceholderText("Your email");
  147. assertEquals(emailInput.className.includes("border-red-600"), true);
  148. // Type into the email input to clear error
  149. await act(async () => {
  150. fireEvent.input(emailInput, { target: { value: "test@email.com" } });
  151. });
  152. assertEquals(emailInput.className.includes("border-red-600"), false);
  153. cleanup();
  154. restoreFetch();
  155. restoreLoading();
  156. },
  157. sanitizeResources: false,
  158. sanitizeOps: false,
  159. });