todomvc.js 11 KB

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