todomvc.spec.ts 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. import path from 'node:path'
  2. import { E2E_TIMEOUT, setupPuppeteer } from './e2eUtils'
  3. describe('e2e: todomvc', () => {
  4. const {
  5. page,
  6. click,
  7. isVisible,
  8. count,
  9. text,
  10. value,
  11. isChecked,
  12. isFocused,
  13. classList,
  14. enterValue,
  15. clearValue,
  16. timeout,
  17. } = setupPuppeteer()
  18. async function removeItemAt(n: number) {
  19. const item = (await page().$('.todo:nth-child(' + n + ')'))!
  20. const itemBBox = (await item.boundingBox())!
  21. await page().mouse.move(itemBBox.x + 10, itemBBox.y + 10)
  22. await click('.todo:nth-child(' + n + ') .destroy')
  23. }
  24. async function testTodomvc(apiType: 'classic' | 'composition') {
  25. const baseUrl = `file://${path.resolve(
  26. __dirname,
  27. `../../examples/${apiType}/todomvc.html`,
  28. )}`
  29. await page().goto(baseUrl)
  30. expect(await isVisible('.main')).toBe(false)
  31. expect(await isVisible('.footer')).toBe(false)
  32. expect(await count('.filters .selected')).toBe(1)
  33. expect(await text('.filters .selected')).toBe('All')
  34. expect(await count('.todo')).toBe(0)
  35. await enterValue('.new-todo', 'test')
  36. expect(await count('.todo')).toBe(1)
  37. expect(await isVisible('.todo .edit')).toBe(false)
  38. expect(await text('.todo label')).toBe('test')
  39. expect(await text('.todo-count strong')).toBe('1')
  40. expect(await isChecked('.todo .toggle')).toBe(false)
  41. expect(await isVisible('.main')).toBe(true)
  42. expect(await isVisible('.footer')).toBe(true)
  43. expect(await isVisible('.clear-completed')).toBe(false)
  44. expect(await value('.new-todo')).toBe('')
  45. await enterValue('.new-todo', 'test2')
  46. expect(await count('.todo')).toBe(2)
  47. expect(await text('.todo:nth-child(2) label')).toBe('test2')
  48. expect(await text('.todo-count strong')).toBe('2')
  49. // toggle
  50. await click('.todo .toggle')
  51. expect(await count('.todo.completed')).toBe(1)
  52. expect(await classList('.todo:nth-child(1)')).toContain('completed')
  53. expect(await text('.todo-count strong')).toBe('1')
  54. expect(await isVisible('.clear-completed')).toBe(true)
  55. await enterValue('.new-todo', 'test3')
  56. expect(await count('.todo')).toBe(3)
  57. expect(await text('.todo:nth-child(3) label')).toBe('test3')
  58. expect(await text('.todo-count strong')).toBe('2')
  59. await enterValue('.new-todo', 'test4')
  60. await enterValue('.new-todo', 'test5')
  61. expect(await count('.todo')).toBe(5)
  62. expect(await text('.todo-count strong')).toBe('4')
  63. // toggle more
  64. await click('.todo:nth-child(4) .toggle')
  65. await click('.todo:nth-child(5) .toggle')
  66. expect(await count('.todo.completed')).toBe(3)
  67. expect(await text('.todo-count strong')).toBe('2')
  68. // remove
  69. await removeItemAt(1)
  70. expect(await count('.todo')).toBe(4)
  71. expect(await count('.todo.completed')).toBe(2)
  72. expect(await text('.todo-count strong')).toBe('2')
  73. await removeItemAt(2)
  74. expect(await count('.todo')).toBe(3)
  75. expect(await count('.todo.completed')).toBe(2)
  76. expect(await text('.todo-count strong')).toBe('1')
  77. // remove all
  78. await click('.clear-completed')
  79. expect(await count('.todo')).toBe(1)
  80. expect(await text('.todo label')).toBe('test2')
  81. expect(await count('.todo.completed')).toBe(0)
  82. expect(await text('.todo-count strong')).toBe('1')
  83. expect(await isVisible('.clear-completed')).toBe(false)
  84. // prepare to test filters
  85. await enterValue('.new-todo', 'test')
  86. await enterValue('.new-todo', 'test')
  87. await click('.todo:nth-child(2) .toggle')
  88. await click('.todo:nth-child(3) .toggle')
  89. // active filter
  90. await click('.filters li:nth-child(2) a')
  91. await timeout(1)
  92. expect(await count('.todo')).toBe(1)
  93. expect(await count('.todo.completed')).toBe(0)
  94. // add item with filter active
  95. await enterValue('.new-todo', 'test')
  96. expect(await count('.todo')).toBe(2)
  97. // completed filter
  98. await click('.filters li:nth-child(3) a')
  99. await timeout(1)
  100. expect(await count('.todo')).toBe(2)
  101. expect(await count('.todo.completed')).toBe(2)
  102. // filter on page load
  103. await page().goto(`${baseUrl}#active`)
  104. expect(await count('.todo')).toBe(2)
  105. expect(await count('.todo.completed')).toBe(0)
  106. expect(await text('.todo-count strong')).toBe('2')
  107. // completed on page load
  108. await page().goto(`${baseUrl}#completed`)
  109. expect(await count('.todo')).toBe(2)
  110. expect(await count('.todo.completed')).toBe(2)
  111. expect(await text('.todo-count strong')).toBe('2')
  112. // toggling with filter active
  113. await click('.todo .toggle')
  114. expect(await count('.todo')).toBe(1)
  115. await click('.filters li:nth-child(2) a')
  116. await timeout(1)
  117. expect(await count('.todo')).toBe(3)
  118. await click('.todo .toggle')
  119. expect(await count('.todo')).toBe(2)
  120. // editing triggered by blur
  121. await click('.filters li:nth-child(1) a')
  122. await timeout(1)
  123. await click('.todo:nth-child(1) label', { clickCount: 2 })
  124. expect(await count('.todo.editing')).toBe(1)
  125. expect(await isFocused('.todo:nth-child(1) .edit')).toBe(true)
  126. await clearValue('.todo:nth-child(1) .edit')
  127. await page().type('.todo:nth-child(1) .edit', 'edited!')
  128. await click('.new-todo') // blur
  129. expect(await count('.todo.editing')).toBe(0)
  130. expect(await text('.todo:nth-child(1) label')).toBe('edited!')
  131. // editing triggered by enter
  132. await click('.todo label', { clickCount: 2 })
  133. await enterValue('.todo:nth-child(1) .edit', 'edited again!')
  134. expect(await count('.todo.editing')).toBe(0)
  135. expect(await text('.todo:nth-child(1) label')).toBe('edited again!')
  136. // cancel
  137. await click('.todo label', { clickCount: 2 })
  138. await clearValue('.todo:nth-child(1) .edit')
  139. await page().type('.todo:nth-child(1) .edit', 'edited!')
  140. await page().keyboard.press('Escape')
  141. expect(await count('.todo.editing')).toBe(0)
  142. expect(await text('.todo:nth-child(1) label')).toBe('edited again!')
  143. // empty value should remove
  144. await click('.todo label', { clickCount: 2 })
  145. await enterValue('.todo:nth-child(1) .edit', ' ')
  146. expect(await count('.todo')).toBe(3)
  147. // toggle all
  148. await click('.toggle-all+label')
  149. expect(await count('.todo.completed')).toBe(3)
  150. await click('.toggle-all+label')
  151. expect(await count('.todo:not(.completed)')).toBe(3)
  152. }
  153. test(
  154. 'classic',
  155. async () => {
  156. await testTodomvc('classic')
  157. },
  158. E2E_TIMEOUT,
  159. )
  160. test(
  161. 'composition',
  162. async () => {
  163. await testTodomvc('composition')
  164. },
  165. E2E_TIMEOUT,
  166. )
  167. })