post_list_test.tsx 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. import { assertEquals, cleanup, fireEvent, render, screen } from "./setup.ts";
  2. import PostList from "../../islands/PostList.tsx";
  3. const mockPosts = [
  4. {
  5. id: "1",
  6. title: "First Post",
  7. content: "Hello world",
  8. shared: false,
  9. hasPassword: false,
  10. },
  11. {
  12. id: "2",
  13. title: "Second Post",
  14. content: "Another post",
  15. shared: true,
  16. hasPassword: false,
  17. },
  18. { id: "3", title: "", content: "", shared: false, hasPassword: false },
  19. ];
  20. const mockPostWithPassword = [
  21. {
  22. id: "4",
  23. title: "Protected Post",
  24. content: "Secret",
  25. shared: true,
  26. hasPassword: true,
  27. },
  28. ];
  29. Deno.test({
  30. name: "PostList - renders correct number of post cards",
  31. fn() {
  32. const { container } = render(<PostList posts={mockPosts} />);
  33. const cards = container.querySelectorAll(".grid > div");
  34. assertEquals(cards.length, 3);
  35. cleanup();
  36. },
  37. sanitizeResources: false,
  38. sanitizeOps: false,
  39. });
  40. Deno.test({
  41. name: "PostList - displays post title",
  42. fn() {
  43. render(<PostList posts={mockPosts} />);
  44. assertEquals(screen.getByText("First Post") !== null, true);
  45. assertEquals(screen.getByText("Second Post") !== null, true);
  46. cleanup();
  47. },
  48. sanitizeResources: false,
  49. sanitizeOps: false,
  50. });
  51. Deno.test({
  52. name: "PostList - shows Untitled for empty title",
  53. fn() {
  54. render(<PostList posts={mockPosts} />);
  55. assertEquals(screen.getByText("Untitled") !== null, true);
  56. cleanup();
  57. },
  58. sanitizeResources: false,
  59. sanitizeOps: false,
  60. });
  61. Deno.test({
  62. name: "PostList - displays post content snippet",
  63. fn() {
  64. render(<PostList posts={mockPosts} />);
  65. assertEquals(screen.getByText("Hello world") !== null, true);
  66. assertEquals(screen.getByText("Another post") !== null, true);
  67. cleanup();
  68. },
  69. sanitizeResources: false,
  70. sanitizeOps: false,
  71. });
  72. Deno.test({
  73. name: "PostList - shows No content for empty content",
  74. fn() {
  75. render(<PostList posts={mockPosts} />);
  76. assertEquals(screen.getByText("No content") !== null, true);
  77. cleanup();
  78. },
  79. sanitizeResources: false,
  80. sanitizeOps: false,
  81. });
  82. Deno.test({
  83. name: "PostList - each card has an Edit button",
  84. fn() {
  85. render(<PostList posts={mockPosts} />);
  86. const editButtons = screen.getAllByText("Edit");
  87. assertEquals(editButtons.length, 3);
  88. cleanup();
  89. },
  90. sanitizeResources: false,
  91. sanitizeOps: false,
  92. });
  93. Deno.test({
  94. name: "PostList - each card has a Delete button",
  95. fn() {
  96. render(<PostList posts={mockPosts} />);
  97. const deleteButtons = screen.getAllByText("Delete");
  98. assertEquals(deleteButtons.length, 3);
  99. cleanup();
  100. },
  101. sanitizeResources: false,
  102. sanitizeOps: false,
  103. });
  104. Deno.test({
  105. name: "PostList - Delete button triggers $modal.show",
  106. fn() {
  107. let modalTitle = "";
  108. let modalContent = "";
  109. globalThis.$modal = {
  110. show: (title: string, content: string | preact.JSX.Element) => {
  111. modalTitle = title;
  112. modalContent = content as string;
  113. },
  114. hide: () => {},
  115. };
  116. render(<PostList posts={[mockPosts[0]]} />);
  117. const deleteButton = screen.getByText("Delete");
  118. fireEvent.click(deleteButton);
  119. assertEquals(modalTitle, "Confirm delete");
  120. assertEquals(modalContent.includes("First Post"), true);
  121. delete globalThis.$modal;
  122. cleanup();
  123. },
  124. sanitizeResources: false,
  125. sanitizeOps: false,
  126. });
  127. Deno.test({
  128. name: "PostList - shows shared icon for shared posts",
  129. fn() {
  130. const { container } = render(<PostList posts={mockPosts} />);
  131. const sharedIcons = container.querySelectorAll(".bi-share-fill");
  132. assertEquals(sharedIcons.length, 1);
  133. cleanup();
  134. },
  135. sanitizeResources: false,
  136. sanitizeOps: false,
  137. });
  138. Deno.test({
  139. name: "PostList - shows lock icon for password-protected posts",
  140. fn() {
  141. const { container } = render(<PostList posts={mockPostWithPassword} />);
  142. const lockIcons = container.querySelectorAll(".bi-lock-fill");
  143. assertEquals(lockIcons.length, 1);
  144. cleanup();
  145. },
  146. sanitizeResources: false,
  147. sanitizeOps: false,
  148. });
  149. Deno.test({
  150. name: "PostList - hides shared icon in readOnly mode",
  151. fn() {
  152. const { container } = render(<PostList posts={mockPosts} readOnly />);
  153. const sharedIcons = container.querySelectorAll(".bi-share-fill");
  154. assertEquals(sharedIcons.length, 0);
  155. cleanup();
  156. },
  157. sanitizeResources: false,
  158. sanitizeOps: false,
  159. });
  160. Deno.test({
  161. name: "PostList - hides Edit and Delete buttons in readOnly mode",
  162. fn() {
  163. render(<PostList posts={mockPosts} readOnly />);
  164. assertEquals(screen.queryByText("Edit"), null);
  165. assertEquals(screen.queryByText("Delete"), null);
  166. cleanup();
  167. },
  168. sanitizeResources: false,
  169. sanitizeOps: false,
  170. });
  171. Deno.test({
  172. name: "PostList - renders empty grid with no posts",
  173. fn() {
  174. const { container } = render(<PostList posts={[]} />);
  175. const cards = container.querySelectorAll(".grid > div");
  176. assertEquals(cards.length, 0);
  177. cleanup();
  178. },
  179. sanitizeResources: false,
  180. sanitizeOps: false,
  181. });