Skip to content

Commit 19b4aab

Browse files
committed
todomvc e2e tests
1 parent 6d66b29 commit 19b4aab

File tree

5 files changed

+282
-2
lines changed

5 files changed

+282
-2
lines changed

build/bind.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// shim phantomjs for testing
2+
Function.prototype.bind = require('function-bind')

examples/todomvc/vuex/store.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,18 @@ Vue.use(Vuex)
66

77
export const STORAGE_KEY = 'todos-vuejs'
88

9+
// for testing
10+
if (navigator.userAgent.indexOf('PhantomJS') > -1) {
11+
localStorage.clear()
12+
}
13+
914
const state = {
1015
todos: JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]')
1116
}
1217

1318
const mutations = {
1419
ADD_TODO (state, text) {
15-
state.todos.unshift({
20+
state.todos.push({
1621
text: text,
1722
done: false
1823
})

examples/webpack.build-all.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ var examples = [
88

99
var entry = {}
1010
examples.forEach(function (name) {
11-
entry[name] = './examples/' + name + '/main.js'
11+
entry[name] = ['./build/bind.js', './examples/' + name + '/main.js']
1212
})
1313

1414
module.exports = {

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
"eslint-config-standard": "^5.1.0",
5050
"eslint-plugin-promise": "^1.0.8",
5151
"eslint-plugin-standard": "^1.3.2",
52+
"function-bind": "^1.1.0",
5253
"mocha": "^2.3.4",
5354
"rollup": "^0.25.4",
5455
"rollup-plugin-babel": "^2.4.0",

test/e2e/todomvc.js

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

0 commit comments

Comments
 (0)