todomvc.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. casper.test.begin('todomvc', 57, function (test) {
  2. casper
  3. .start('examples/todomvc/index.html')
  4. .then(function () {
  5. this.viewport(1000, 1000) // for appearing destroy button by mouse hover
  6. test.assertNotVisible('.main', '.main should be hidden')
  7. test.assertNotVisible('.footer', '.footer should be hidden')
  8. test.assertElementCount('.filters .selected', 1, 'should have one filter selected')
  9. test.assertSelectorHasText('.filters .selected', 'All', 'default filter should be "All"')
  10. })
  11. // let's add a new item -----------------------------------------------
  12. .then(function () {
  13. casper.sendKeys('.new-todo', 'test')
  14. })
  15. .then(function () {
  16. // wait before hitting enter
  17. // so v-model unlocks
  18. createNewItem()
  19. })
  20. .then(function () {
  21. test.assertElementCount('.todo', 1, 'new item should be created')
  22. test.assertNotVisible('.todo .edit', 'new item edit box should be hidden')
  23. test.assertSelectorHasText('.todo label', 'test', 'new item should have correct label text')
  24. test.assertSelectorHasText('.todo-count strong', '1', 'remaining count should be 1')
  25. test.assertEvalEquals(function () {
  26. return __utils__.findOne('.todo .toggle').checked
  27. }, false, 'new item toggle should not be checked')
  28. test.assertVisible('.main', '.main should now be visible')
  29. test.assertVisible('.footer', '.footer should now be visible')
  30. test.assertNotVisible('.clear-completed', '.clear-completed should be hidden')
  31. test.assertField({ type: 'css', path: '.new-todo' }, '', 'new todo input should be reset')
  32. })
  33. // add another item ---------------------------------------------------
  34. .then(function () {
  35. createNewItem('test2')
  36. })
  37. .then(function () {
  38. test.assertElementCount('.todo', 2, 'should have 2 items now')
  39. test.assertSelectorHasText('.todo:nth-child(2) label', 'test2', 'new item should have correct label text')
  40. test.assertSelectorHasText('.todo-count strong', '2', 'remaining count should be 2')
  41. })
  42. // mark one item as completed -----------------------------------------
  43. .thenClick('.todo .toggle', function () {
  44. test.assertElementCount('.todo.completed', 1, 'should have 1 item completed')
  45. test.assertEval(function () {
  46. return __utils__.findOne('.todo').classList.contains('completed')
  47. }, 'it should be the first one')
  48. test.assertSelectorHasText('.todo-count strong', '1', 'remaining count should be 1')
  49. test.assertVisible('.clear-completed', '.clear-completed should now be visible')
  50. })
  51. // add yet another item -----------------------------------------------
  52. .then(function () {
  53. createNewItem('test3')
  54. })
  55. .then(function () {
  56. test.assertElementCount('.todo', 3, 'should have 3 items now')
  57. test.assertSelectorHasText('.todo:nth-child(3) label', 'test3', 'new item should have correct label text')
  58. test.assertSelectorHasText('.todo-count strong', '2', 'remaining count should be 2')
  59. })
  60. // add moreeee, now we assume they all work properly ------------------
  61. .then(function () {
  62. createNewItem('test4')
  63. createNewItem('test5')
  64. })
  65. .then(function () {
  66. test.assertElementCount('.todo', 5, 'should have 5 items now')
  67. test.assertSelectorHasText('.todo-count strong', '4', 'remaining count should be 4')
  68. })
  69. // check more as completed --------------------------------------------
  70. .then(function () {
  71. this.click('.todo:nth-child(4) .toggle')
  72. this.click('.todo:nth-child(5) .toggle')
  73. })
  74. .then(function () {
  75. test.assertElementCount('.todo.completed', 3, 'should have 3 item completed')
  76. test.assertSelectorHasText('.todo-count strong', '2', 'remaining count should be 2')
  77. })
  78. // remove a completed item --------------------------------------------
  79. .then(function () {
  80. this.mouse.move('.todo:nth-child(1)')
  81. })
  82. .thenClick('.todo:nth-child(1) .destroy', function () {
  83. test.assertElementCount('.todo', 4, 'should have 4 items now')
  84. test.assertElementCount('.todo.completed', 2, 'should have 2 item completed')
  85. test.assertSelectorHasText('.todo-count strong', '2', 'remaining count should be 2')
  86. })
  87. // remove a incompleted item ------------------------------------------
  88. .then(function () {
  89. this.mouse.move('.todo:nth-child(2)')
  90. })
  91. .thenClick('.todo:nth-child(2) .destroy', function () {
  92. test.assertElementCount('.todo', 3, 'should have 3 items now')
  93. test.assertElementCount('.todo.completed', 2, 'should have 2 item completed')
  94. test.assertSelectorHasText('.todo-count strong', '1', 'remaining count should be 1')
  95. })
  96. // remove all completed ------------------------------------------------
  97. .thenClick('.clear-completed', function () {
  98. test.assertElementCount('.todo', 1, 'should have 1 item now')
  99. test.assertSelectorHasText('.todo label', 'test2', 'the remaining one should be the second one')
  100. test.assertElementCount('.todo.completed', 0, 'should have no completed items now')
  101. test.assertSelectorHasText('.todo-count strong', '1', 'remaining count should be 1')
  102. test.assertNotVisible('.clear-completed', '.clear-completed should be hidden')
  103. })
  104. // prepare to test filters ------------------------------------------------
  105. .then(function () {
  106. createNewItem('test')
  107. createNewItem('test')
  108. })
  109. .then(function () {
  110. this.click('.todo:nth-child(2) .toggle')
  111. this.click('.todo:nth-child(3) .toggle')
  112. })
  113. // active filter ----------------------------------------------------------
  114. .thenClick('.filters li:nth-child(2) a', function () {
  115. test.assertElementCount('.todo', 1, 'filter active should have 1 item')
  116. test.assertElementCount('.todo.completed', 0, 'visible items should be incomplete')
  117. })
  118. // add item with filter active --------------------------------------------
  119. // mostly make sure v-repeat works well with v-if
  120. .then(function () {
  121. createNewItem('test')
  122. })
  123. .then(function () {
  124. test.assertElementCount('.todo', 2, 'should be able to create new item when fitler active')
  125. })
  126. // completed filter -------------------------------------------------------
  127. .thenClick('.filters li:nth-child(3) a', function () {
  128. test.assertElementCount('.todo', 2, 'filter completed should have 2 items')
  129. test.assertElementCount('.todo.completed', 2, 'visible items should be completed')
  130. })
  131. // toggling todos when filter is active -----------------------------------
  132. .thenClick('.todo .toggle', function () {
  133. test.assertElementCount('.todo', 1, 'should have only 1 item left')
  134. })
  135. .thenClick('.filters li:nth-child(2) a', function () {
  136. test.assertElementCount('.todo', 3, 'should have only 3 items now')
  137. })
  138. .thenClick('.todo .toggle', function () {
  139. test.assertElementCount('.todo', 2, 'should have only 2 items now')
  140. })
  141. // test editing triggered by blur ------------------------------------------
  142. .thenClick('.filters li:nth-child(1) a')
  143. .then(function () {
  144. doubleClick('.todo:nth-child(1) label')
  145. })
  146. .then(function () {
  147. test.assertElementCount('.todo.editing', 1, 'should have one item being edited')
  148. test.assertEval(function () {
  149. var input = document.querySelector('.todo:nth-child(1) .edit')
  150. return input === document.activeElement
  151. }, 'edit input should be focused')
  152. })
  153. .then(function () {
  154. resetField()
  155. this.sendKeys('.todo:nth-child(1) .edit', 'edited!') // doneEdit triggered by blur
  156. })
  157. .then(function () {
  158. test.assertElementCount('.todo.editing', 0, 'item should no longer be edited')
  159. test.assertSelectorHasText('.todo:nth-child(1) label', 'edited!', 'item should have updated text')
  160. })
  161. // test editing triggered by enter ----------------------------------------
  162. .then(function () {
  163. doubleClick('.todo label')
  164. })
  165. .then(function () {
  166. resetField()
  167. this.sendKeys('.todo:nth-child(1) .edit', 'edited again!', { keepFocus: true })
  168. keyUp(13) // Enter
  169. })
  170. .then(function () {
  171. test.assertElementCount('.todo.editing', 0, 'item should no longer be edited')
  172. test.assertSelectorHasText('.todo:nth-child(1) label', 'edited again!', 'item should have updated text')
  173. })
  174. // test cancel ------------------------------------------------------------
  175. .then(function () {
  176. doubleClick('.todo label')
  177. })
  178. .then(function () {
  179. resetField()
  180. this.sendKeys('.todo:nth-child(1) .edit', 'cancel test', { keepFocus: true })
  181. keyUp(27) // ESC
  182. })
  183. .then(function () {
  184. test.assertElementCount('.todo.editing', 0, 'item should no longer be edited')
  185. test.assertSelectorHasText('.todo label', 'edited again!', 'item should not have updated text')
  186. })
  187. // test empty input remove ------------------------------------------------
  188. .then(function () {
  189. doubleClick('.todo label')
  190. })
  191. .then(function () {
  192. resetField()
  193. this.sendKeys('.todo:nth-child(1) .edit', ' ')
  194. })
  195. .then(function () {
  196. test.assertElementCount('.todo', 3, 'item should have been deleted')
  197. })
  198. // test toggle all
  199. .thenClick('.toggle-all', function () {
  200. test.assertElementCount('.todo.completed', 3, 'should toggle all items to completed')
  201. })
  202. .thenClick('.toggle-all', function () {
  203. test.assertElementCount('.todo:not(.completed)', 3, 'should toggle all items to active')
  204. })
  205. // run
  206. .run(function () {
  207. test.done()
  208. })
  209. // helper ===============
  210. function createNewItem (text) {
  211. if (text) {
  212. casper.sendKeys('.new-todo', text)
  213. }
  214. casper.evaluate(function () {
  215. // casper.mouseEvent can't set keyCode
  216. var field = document.querySelector('.new-todo')
  217. var e = document.createEvent('HTMLEvents')
  218. e.initEvent('keyup', true, true)
  219. e.keyCode = 13
  220. field.dispatchEvent(e)
  221. })
  222. }
  223. function doubleClick (selector) {
  224. casper.evaluate(function (selector) {
  225. var el = document.querySelector(selector)
  226. var e = document.createEvent('MouseEvents')
  227. e.initMouseEvent('dblclick', true, true, null, 1, 0, 0, 0, 0, false, false, false, false, 0, null)
  228. el.dispatchEvent(e)
  229. }, selector)
  230. }
  231. function keyUp (code) {
  232. casper.evaluate(function (code) {
  233. var input = document.querySelector('.todo:nth-child(1) .edit')
  234. var e = document.createEvent('HTMLEvents')
  235. e.initEvent('keyup', true, true)
  236. e.keyCode = code
  237. input.dispatchEvent(e)
  238. }, code)
  239. }
  240. function resetField () {
  241. // somehow casper.sendKey() option reset:true doesn't work
  242. casper.evaluate(function () {
  243. document.querySelector('.todo:nth-child(1) .edit').value = ''
  244. })
  245. }
  246. })