basic.spec.ts 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. import { expect } from '@playwright/test'
  2. import fs from 'fs/promises'
  3. import path from 'path'
  4. import { test, graphDir } from './fixtures'
  5. import { randomString, createRandomPage, newBlock } from './utils'
  6. test('render app', async ({ page }) => {
  7. // NOTE: part of app startup tests is moved to `fixtures.ts`.
  8. await page.waitForFunction('window.document.title != "Loading"')
  9. expect(await page.title()).toMatch(/^Logseq.*?/)
  10. })
  11. test('toggle sidebar', async ({ page }) => {
  12. let sidebar = page.locator('#left-sidebar')
  13. // Left sidebar is toggled by `is-open` class
  14. if (/is-open/.test(await sidebar.getAttribute('class'))) {
  15. await page.click('#left-menu.button')
  16. expect(await sidebar.getAttribute('class')).not.toMatch(/is-open/)
  17. } else {
  18. await page.click('#left-menu.button')
  19. expect(await sidebar.getAttribute('class')).toMatch(/is-open/)
  20. await page.click('#left-menu.button')
  21. expect(await sidebar.getAttribute('class')).not.toMatch(/is-open/)
  22. }
  23. await page.click('#left-menu.button')
  24. expect(await sidebar.getAttribute('class')).toMatch(/is-open/)
  25. await page.waitForSelector('#left-sidebar .left-sidebar-inner', { state: 'visible' })
  26. await page.waitForSelector('#left-sidebar a:has-text("New page")', { state: 'visible' })
  27. })
  28. test('search', async ({ page }) => {
  29. await page.click('#search-button')
  30. await page.waitForSelector('[placeholder="Search or create page"]')
  31. await page.fill('[placeholder="Search or create page"]', 'welcome')
  32. await page.waitForTimeout(500)
  33. const results = await page.$$('#ui__ac-inner .block')
  34. expect(results.length).toBeGreaterThanOrEqual(1)
  35. })
  36. test('create page and blocks', async ({ page }) => {
  37. const pageTitle = await createRandomPage(page)
  38. // do editing
  39. await page.fill(':nth-match(textarea, 1)', 'this is my first bullet')
  40. await page.press(':nth-match(textarea, 1)', 'Enter')
  41. // first block
  42. expect(await page.$$('.block-content')).toHaveLength(1)
  43. await page.fill(':nth-match(textarea, 1)', 'this is my second bullet')
  44. await page.press(':nth-match(textarea, 1)', 'Enter')
  45. await page.fill(':nth-match(textarea, 1)', 'this is my third bullet')
  46. await page.press(':nth-match(textarea, 1)', 'Tab')
  47. await page.press(':nth-match(textarea, 1)', 'Enter')
  48. await page.keyboard.type('continue editing test')
  49. await page.keyboard.press('Shift+Enter')
  50. await page.keyboard.type('continue')
  51. await page.keyboard.press('Enter')
  52. await page.keyboard.press('Shift+Tab')
  53. await page.keyboard.press('Shift+Tab')
  54. await page.keyboard.type('test ok')
  55. await page.keyboard.press('Escape')
  56. const blocks = await page.$$('.ls-block')
  57. expect(blocks).toHaveLength(5)
  58. // active edit
  59. await page.click('.ls-block >> nth=-1')
  60. await page.press('textarea >> nth=0', 'Enter')
  61. await page.fill('textarea >> nth=0', 'test')
  62. for (let i = 0; i < 5; i++) {
  63. await page.keyboard.press('Backspace')
  64. }
  65. await page.keyboard.press('Escape')
  66. await page.waitForTimeout(500)
  67. expect(await page.$$('.ls-block')).toHaveLength(5)
  68. await page.waitForTimeout(1000)
  69. const contentOnDisk = await fs.readFile(
  70. path.join(graphDir, `pages/${pageTitle}.md`),
  71. 'utf8'
  72. )
  73. expect(contentOnDisk.trim()).toEqual(`
  74. - this is my first bullet
  75. - this is my second bullet
  76. - this is my third bullet
  77. - continue editing test
  78. continue
  79. - test ok`.trim())
  80. })
  81. test('delete and backspace', async ({ page }) => {
  82. await createRandomPage(page)
  83. await page.fill(':nth-match(textarea, 1)', 'test')
  84. expect(await page.inputValue(':nth-match(textarea, 1)')).toBe('test')
  85. // backspace
  86. await page.keyboard.press('Backspace')
  87. await page.keyboard.press('Backspace')
  88. expect(await page.inputValue(':nth-match(textarea, 1)')).toBe('te')
  89. // refill
  90. await page.fill(':nth-match(textarea, 1)', 'test')
  91. await page.keyboard.press('ArrowLeft')
  92. await page.keyboard.press('ArrowLeft')
  93. // delete
  94. await page.keyboard.press('Delete')
  95. expect(await page.inputValue(':nth-match(textarea, 1)')).toBe('tet')
  96. await page.keyboard.press('Delete')
  97. expect(await page.inputValue(':nth-match(textarea, 1)')).toBe('te')
  98. await page.keyboard.press('Delete')
  99. expect(await page.inputValue(':nth-match(textarea, 1)')).toBe('te')
  100. // TODO: test delete & backspace across blocks
  101. })
  102. test('selection', async ({ page }) => {
  103. await createRandomPage(page)
  104. await page.fill(':nth-match(textarea, 1)', 'line 1')
  105. await page.press(':nth-match(textarea, 1)', 'Enter')
  106. await page.fill(':nth-match(textarea, 1)', 'line 2')
  107. await page.press(':nth-match(textarea, 1)', 'Enter')
  108. await page.press(':nth-match(textarea, 1)', 'Tab')
  109. await page.fill(':nth-match(textarea, 1)', 'line 3')
  110. await page.press(':nth-match(textarea, 1)', 'Enter')
  111. await page.fill(':nth-match(textarea, 1)', 'line 4')
  112. await page.press(':nth-match(textarea, 1)', 'Tab')
  113. await page.press(':nth-match(textarea, 1)', 'Enter')
  114. await page.fill(':nth-match(textarea, 1)', 'line 5')
  115. await page.keyboard.down('Shift')
  116. await page.keyboard.press('ArrowUp')
  117. await page.keyboard.press('ArrowUp')
  118. await page.keyboard.press('ArrowUp')
  119. await page.keyboard.up('Shift')
  120. await page.waitForTimeout(500)
  121. await page.keyboard.press('Backspace')
  122. expect(await page.$$('.ls-block')).toHaveLength(2)
  123. })
  124. test('template', async ({ page }) => {
  125. const randomTemplate = randomString(10)
  126. await createRandomPage(page)
  127. await page.fill(':nth-match(textarea, 1)', 'template')
  128. await page.press(':nth-match(textarea, 1)', 'Shift+Enter')
  129. await page.type(':nth-match(textarea, 1)', 'template:: ' + randomTemplate)
  130. await page.press(':nth-match(textarea, 1)', 'Enter')
  131. await page.press(':nth-match(textarea, 1)', 'Enter')
  132. await page.press(':nth-match(textarea, 1)', 'Tab')
  133. await page.fill(':nth-match(textarea, 1)', 'line1')
  134. await page.press(':nth-match(textarea, 1)', 'Enter')
  135. await page.fill(':nth-match(textarea, 1)', 'line2')
  136. await page.press(':nth-match(textarea, 1)', 'Enter')
  137. await page.press(':nth-match(textarea, 1)', 'Tab')
  138. await page.fill(':nth-match(textarea, 1)', 'line3')
  139. await page.press(':nth-match(textarea, 1)', 'Enter')
  140. await page.press(':nth-match(textarea, 1)', 'Enter')
  141. await page.press(':nth-match(textarea, 1)', 'Enter')
  142. expect(await page.$$('.ls-block')).toHaveLength(5)
  143. await page.type(':nth-match(textarea, 1)', '/template')
  144. await page.click('[title="Insert a created template here"]')
  145. // type to search template name
  146. await page.keyboard.type(randomTemplate.substring(0, 3))
  147. await page.click('.absolute >> text=' + randomTemplate)
  148. await page.waitForTimeout(500)
  149. expect(await page.$$('.ls-block')).toHaveLength(8)
  150. })
  151. test('auto completion square brackets', async ({ page }) => {
  152. await createRandomPage(page)
  153. await page.fill(':nth-match(textarea, 1)', 'Auto-completion test')
  154. await page.press(':nth-match(textarea, 1)', 'Enter')
  155. // [[]]
  156. await page.type(':nth-match(textarea, 1)', 'This is a [')
  157. await page.inputValue(':nth-match(textarea, 1)').then(text => {
  158. expect(text).toBe('This is a []')
  159. })
  160. await page.type(':nth-match(textarea, 1)', '[')
  161. // wait for search popup
  162. await page.waitForSelector('text="Search for a page"')
  163. expect(await page.inputValue(':nth-match(textarea, 1)')).toBe('This is a [[]]')
  164. // re-enter edit mode
  165. await page.press(':nth-match(textarea, 1)', 'Escape')
  166. await page.click('.ls-block >> nth=-1')
  167. await page.waitForSelector(':nth-match(textarea, 1)', { state: 'visible' })
  168. // #3253
  169. await page.press(':nth-match(textarea, 1)', 'ArrowLeft')
  170. await page.press(':nth-match(textarea, 1)', 'ArrowLeft')
  171. await page.press(':nth-match(textarea, 1)', 'Enter')
  172. await page.waitForSelector('text="Search for a page"', { state: 'visible' })
  173. // type more `]`s
  174. await page.type(':nth-match(textarea, 1)', ']')
  175. expect(await page.inputValue(':nth-match(textarea, 1)')).toBe('This is a [[]]')
  176. await page.type(':nth-match(textarea, 1)', ']')
  177. expect(await page.inputValue(':nth-match(textarea, 1)')).toBe('This is a [[]]')
  178. await page.type(':nth-match(textarea, 1)', ']')
  179. expect(await page.inputValue(':nth-match(textarea, 1)')).toBe('This is a [[]]]')
  180. })
  181. test('auto completion and auto pair', async ({ page }) => {
  182. await createRandomPage(page)
  183. await page.fill(':nth-match(textarea, 1)', 'Auto-completion test')
  184. await page.press(':nth-match(textarea, 1)', 'Enter')
  185. // {{
  186. await page.type(':nth-match(textarea, 1)', 'type {{')
  187. expect(await page.inputValue(':nth-match(textarea, 1)')).toBe('type {{}}')
  188. // ((
  189. await newBlock(page)
  190. await page.type(':nth-match(textarea, 1)', 'type (')
  191. expect(await page.inputValue(':nth-match(textarea, 1)')).toBe('type ()')
  192. await page.type(':nth-match(textarea, 1)', '(')
  193. expect(await page.inputValue(':nth-match(textarea, 1)')).toBe('type (())')
  194. // 99 #3444
  195. // TODO: Test under different keyboard layout when Playwright supports it
  196. // await newBlock(page)
  197. // await page.type(':nth-match(textarea, 1)', 'type 9')
  198. // expect(await page.inputValue(':nth-match(textarea, 1)')).toBe('type 9')
  199. // await page.type(':nth-match(textarea, 1)', '9')
  200. // expect(await page.inputValue(':nth-match(textarea, 1)')).toBe('type 99')
  201. // [[ #3251
  202. await newBlock(page)
  203. await page.type(':nth-match(textarea, 1)', 'type [')
  204. expect(await page.inputValue(':nth-match(textarea, 1)')).toBe('type []')
  205. await page.type(':nth-match(textarea, 1)', '[')
  206. expect(await page.inputValue(':nth-match(textarea, 1)')).toBe('type [[]]')
  207. // ``
  208. await newBlock(page)
  209. await page.type(':nth-match(textarea, 1)', 'type `')
  210. expect(await page.inputValue(':nth-match(textarea, 1)')).toBe('type ``')
  211. await page.type(':nth-match(textarea, 1)', 'code here')
  212. expect(await page.inputValue(':nth-match(textarea, 1)')).toBe('type `code here`')
  213. })
  214. // FIXME: Electron with filechooser is not working
  215. test.skip('open directory', async ({ page }) => {
  216. await page.click('#left-sidebar >> text=Journals')
  217. await page.waitForSelector('h1:has-text("Open a local directory")')
  218. await page.click('h1:has-text("Open a local directory")')
  219. // await page.waitForEvent('filechooser')
  220. await page.keyboard.press('Escape')
  221. await page.click('#left-sidebar >> text=Journals')
  222. })
  223. test('invalid page props #3944', async ({ page }) => {
  224. await createRandomPage(page)
  225. await page.fill(':nth-match(textarea, 1)', 'public:: true\nsize:: 65535')
  226. await page.press(':nth-match(textarea, 1)', 'Enter')
  227. await page.press(':nth-match(textarea, 1)', 'Enter')
  228. await page.waitForTimeout(1000)
  229. })