search.spec.ts 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. import { expect, test } from '@playwright/test';
  2. test('Search page with "q" param is successfully loaded', async ({ page }) => {
  3. // Navigate to the search page with query parameters
  4. await page.goto('/_search?q=alerts');
  5. // Confirm search result elements are visible
  6. await expect(page.getByTestId('search-result-base')).toBeVisible();
  7. await expect(page.getByTestId('search-result-list')).toBeVisible();
  8. await expect(page.getByTestId('search-result-content')).toBeVisible();
  9. await expect(page.locator('.wiki')).toBeVisible();
  10. });
  11. test('checkboxes behaviors', async ({ page }) => {
  12. // Navigate to the search page with query parameters
  13. await page.goto('/_search?q=alerts');
  14. // Confirm search result elements are visible
  15. await expect(page.getByTestId('search-result-base')).toBeVisible();
  16. await expect(page.getByTestId('search-result-list')).toBeVisible();
  17. await expect(page.getByTestId('search-result-content')).toBeVisible();
  18. await expect(page.locator('.wiki')).toBeVisible();
  19. // Click the first checkbox
  20. await page.getByTestId('cb-select').first().click({ force: true });
  21. // Unclick the first checkbox
  22. await page.getByTestId('cb-select').first().click({ force: true });
  23. // Click the select all checkbox
  24. await page.getByTestId('cb-select-all').click({ force: true });
  25. // Unclick the first checkbox after selecting all
  26. await page.getByTestId('cb-select').first().click({ force: true });
  27. // Click the first checkbox again
  28. await page.getByTestId('cb-select').first().click({ force: true });
  29. // Unclick the select all checkbox
  30. await page.getByTestId('cb-select').first().click({ force: true });
  31. });
  32. test('successfully loads /_private-legacy-pages', async ({ page }) => {
  33. await page.goto('/_private-legacy-pages');
  34. // Confirm search result elements are visible
  35. await expect(
  36. page.locator('[data-testid="search-result-base"]'),
  37. ).toBeVisible();
  38. await expect(
  39. page.locator('[data-testid="search-result-private-legacy-pages"]'),
  40. ).toBeVisible();
  41. });
  42. test('Search all pages by word', async ({ page }) => {
  43. await page.goto('/');
  44. await page.getByTestId('open-search-modal-button').click();
  45. await expect(page.getByTestId('search-modal')).toBeVisible();
  46. await page.locator('.form-control').fill('sand');
  47. await expect(page.locator('.search-menu-item').first()).toBeVisible();
  48. });
  49. test.describe
  50. .serial('Search all pages', () => {
  51. const tag = 'help';
  52. const searchText = `tag:${tag}`;
  53. test('Successfully created tags', async ({ page }) => {
  54. await page.goto('/');
  55. // open Edit Tags Modal to add tag
  56. await page.locator('.grw-side-contents-sticky-container').isVisible();
  57. await page.locator('#edit-tags-btn-wrapper-for-tooltip').click();
  58. await expect(page.locator('#edit-tag-modal')).toBeVisible();
  59. // Use pressSequentially to fire per-character input events that the
  60. // AsyncTypeahead listens to; fill() can be too fast to trigger the
  61. // debounced onSearch reliably on CI.
  62. await page.locator('.rbt-input-main').pressSequentially(tag);
  63. const typeaheadItem = page.locator(
  64. '#tag-typeahead-asynctypeahead-item-0',
  65. );
  66. await expect(typeaheadItem).toBeVisible({ timeout: 15000 });
  67. await typeaheadItem.click();
  68. await page.getByTestId('tag-edit-done-btn').click();
  69. });
  70. test('Search all pages by tag is successfully loaded', async ({ page }) => {
  71. await page.goto('/');
  72. // Search
  73. await page.getByTestId('open-search-modal-button').click();
  74. await expect(page.getByTestId('search-modal')).toBeVisible();
  75. await page.locator('.form-control').fill(searchText);
  76. await page.getByTestId('search-all-menu-item').click();
  77. // Confirm search result elements are visible
  78. const searchResultList = page.getByTestId('search-result-list');
  79. await expect(searchResultList).toBeVisible();
  80. await expect(searchResultList.locator('li')).toHaveCount(1);
  81. });
  82. test('Successfully order page search results by tag', async ({ page }) => {
  83. await page.goto('/');
  84. await page.locator('.grw-tag-simple-bar').locator('button').click();
  85. await expect(page.getByTestId('search-result-base')).toBeVisible();
  86. await expect(page.getByTestId('search-result-list')).toBeVisible();
  87. await expect(page.getByTestId('search-result-content')).toBeVisible();
  88. });
  89. });
  90. test.describe('Sort with dropdown', () => {
  91. test.beforeEach(async ({ page }) => {
  92. await page.goto('/_search?q=sand');
  93. await expect(page.getByTestId('search-result-base')).toBeVisible();
  94. await expect(page.getByTestId('search-result-list')).toBeVisible();
  95. await expect(page.getByTestId('search-result-content')).toBeVisible();
  96. // open sort dropdown
  97. await page.locator('.search-control').locator('button').first().click();
  98. });
  99. test('Open sort dropdown', async ({ page }) => {
  100. await expect(
  101. page.locator('.search-control .dropdown-menu.show'),
  102. ).toBeVisible();
  103. });
  104. test('Sort by relevance', async ({ page }) => {
  105. const dropdownMenu = page.locator('.search-control .dropdown-menu.show');
  106. await expect(dropdownMenu).toBeVisible();
  107. await dropdownMenu.locator('.dropdown-item').nth(0).click();
  108. await expect(page.getByTestId('search-result-base')).toBeVisible();
  109. await expect(page.getByTestId('search-result-list')).toBeVisible();
  110. await expect(page.getByTestId('search-result-content')).toBeVisible();
  111. });
  112. test('Sort by creation date', async ({ page }) => {
  113. const dropdownMenu = page.locator('.search-control .dropdown-menu.show');
  114. await expect(dropdownMenu).toBeVisible();
  115. await dropdownMenu.locator('.dropdown-item').nth(1).click();
  116. await expect(page.getByTestId('search-result-base')).toBeVisible();
  117. await expect(page.getByTestId('search-result-list')).toBeVisible();
  118. await expect(page.getByTestId('search-result-content')).toBeVisible();
  119. });
  120. test('Sort by last update date', async ({ page }) => {
  121. const dropdownMenu = page.locator('.search-control .dropdown-menu.show');
  122. await expect(dropdownMenu).toBeVisible();
  123. await dropdownMenu.locator('.dropdown-item').nth(2).click();
  124. await expect(page.getByTestId('search-result-base')).toBeVisible();
  125. await expect(page.getByTestId('search-result-list')).toBeVisible();
  126. await expect(page.getByTestId('search-result-content')).toBeVisible();
  127. });
  128. });
  129. test.describe('Search and use', () => {
  130. test.beforeEach(async ({ page }) => {
  131. await page.goto('/_search?q=alerts');
  132. await expect(page.getByTestId('search-result-base')).toBeVisible();
  133. await expect(page.getByTestId('search-result-list')).toBeVisible();
  134. await expect(page.getByTestId('search-result-content')).toBeVisible();
  135. await page
  136. .getByTestId('page-list-item-L')
  137. .first()
  138. .getByTestId('open-page-item-control-btn')
  139. .click();
  140. await expect(page.locator('.dropdown-menu.show')).toBeVisible();
  141. });
  142. test('Successfully the dropdown is opened', async ({ page }) => {
  143. await expect(page.locator('.dropdown-menu.show')).toBeVisible();
  144. });
  145. test('Successfully add bookmark', async ({ page }) => {
  146. const dropdonwMenu = page.locator('.dropdown-menu.show');
  147. await expect(dropdonwMenu).toBeVisible();
  148. // Add bookmark
  149. await dropdonwMenu.getByTestId('add-bookmark-btn').click();
  150. await expect(
  151. page
  152. .getByTestId('search-result-content')
  153. .locator('.btn-bookmark.active')
  154. .first(),
  155. ).toBeVisible();
  156. });
  157. test('Successfully open duplicate modal', async ({ page }) => {
  158. const dropdonwMenu = page.locator('.dropdown-menu.show');
  159. await expect(dropdonwMenu).toBeVisible();
  160. await dropdonwMenu.getByTestId('open-page-duplicate-modal-btn').click();
  161. await expect(page.getByTestId('page-duplicate-modal')).toBeVisible();
  162. });
  163. test('Successfully open move/rename modal', async ({ page }) => {
  164. const dropdonwMenu = page.locator('.dropdown-menu.show');
  165. await expect(dropdonwMenu).toBeVisible();
  166. await dropdonwMenu.getByTestId('rename-page-btn').click();
  167. await expect(page.getByTestId('page-rename-modal')).toBeVisible();
  168. });
  169. test('Successfully open delete modal', async ({ page }) => {
  170. const dropdonwMenu = page.locator('.dropdown-menu.show');
  171. await expect(dropdonwMenu).toBeVisible();
  172. await dropdonwMenu.getByTestId('open-page-delete-modal-btn').click();
  173. await expect(page.getByTestId('page-delete-modal')).toBeVisible();
  174. });
  175. });
  176. test('Search current tree by word is successfully loaded', async ({ page }) => {
  177. await page.goto('/');
  178. const searchText = 'GROWI';
  179. await page.getByTestId('open-search-modal-button').click();
  180. await expect(page.getByTestId('search-modal')).toBeVisible();
  181. await page.locator('.form-control').fill(searchText);
  182. await page.getByTestId('search-prefix-menu-item').click();
  183. await expect(page.getByTestId('search-result-base')).toBeVisible();
  184. await expect(page.getByTestId('search-result-list')).toBeVisible();
  185. await expect(page.getByTestId('search-result-content')).toBeVisible();
  186. });
  187. test.describe('Search result navigation and repeated search', () => {
  188. test('Repeated search works', async ({ page }) => {
  189. // Step 1: Start from the home page and reload to clear any state
  190. await page.goto('/');
  191. await page.reload();
  192. // Step 2: Open search modal and search for "sandbox"
  193. await page.getByTestId('open-search-modal-button').click();
  194. await expect(page.getByTestId('search-modal')).toBeVisible();
  195. await page.locator('.form-control').fill('sandbox');
  196. // Step 3: Submit the search by clicking on "search in all" menu item
  197. await expect(page.getByTestId('search-all-menu-item')).toBeVisible();
  198. await page.getByTestId('search-all-menu-item').click();
  199. // Step 4: Verify that the search page is displayed with results
  200. await expect(page.getByTestId('search-result-base')).toBeVisible();
  201. await expect(page.getByTestId('search-result-list')).toBeVisible();
  202. await expect(page.getByTestId('search-result-content')).toBeVisible();
  203. await expect(page).toHaveURL(/\/_search\?q=sandbox/);
  204. // Step 5: Click on the first search result to navigate to a page
  205. const sandboxPageLink = page
  206. .getByTestId('search-result-list')
  207. .getByRole('link', { name: 'Sandbox' })
  208. .first();
  209. await sandboxPageLink.click();
  210. await expect(page).toHaveTitle(/Sandbox/);
  211. // Step 6: Wait for leaving search results and verify page content is displayed
  212. await expect(page.getByTestId('search-result-base')).not.toBeVisible();
  213. // Verify page body is rendered (not empty due to stale atom data)
  214. await expect(page.locator('.wiki')).toBeVisible();
  215. await expect(page.locator('.wiki')).not.toBeEmpty();
  216. // Step 7: From the navigated page, open search modal again
  217. await page.getByTestId('open-search-modal-button').click();
  218. await expect(page.getByTestId('search-modal')).toBeVisible();
  219. // Step 8: Search for the same keyword ("sandbox")
  220. await page.locator('.form-control').fill('sandbox');
  221. // Step 9: Submit the search by clicking on "search in all" menu item
  222. await expect(page.getByTestId('search-all-menu-item')).toBeVisible();
  223. await page.getByTestId('search-all-menu-item').click();
  224. // Step 10: Verify that the search page is displayed with results
  225. await expect(page.getByTestId('search-result-base')).toBeVisible();
  226. await expect(page.getByTestId('search-result-list')).toBeVisible();
  227. await expect(page.getByTestId('search-result-content')).toBeVisible();
  228. await expect(page).toHaveURL(/\/_search\?q=sandbox/);
  229. // Step 11: Click on the second search result to navigate to a page
  230. const mathPageLink = page
  231. .getByTestId('search-result-list')
  232. .getByRole('link', { name: 'Math' })
  233. .first();
  234. await mathPageLink.click();
  235. // and verify the page that is not Sandbox is loaded
  236. await expect(page).not.toHaveTitle(/Sandbox/);
  237. // Step 12: Verify page body is rendered (not empty due to stale atom data)
  238. await expect(page.locator('.wiki')).toBeVisible();
  239. await expect(page.locator('.wiki')).not.toBeEmpty();
  240. });
  241. });