forked from boranton/testcafe-workshop
setup prelesson
This commit is contained in:
parent
4cbbea66e5
commit
b772e81bf8
9
.babelrc
9
.babelrc
@ -1,10 +1,3 @@
|
|||||||
{
|
{
|
||||||
"presets": ["es2015-webpack", "stage-2"],
|
"presets": ["es2015-webpack", "stage-2"]
|
||||||
"env": {
|
|
||||||
"test": {
|
|
||||||
"plugins": [
|
|
||||||
["__coverage__", {"ignore": "*.test.*"}]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,12 +10,5 @@
|
|||||||
"valid-jsdoc": 0,
|
"valid-jsdoc": 0,
|
||||||
"vars-on-top": 0,
|
"vars-on-top": 0,
|
||||||
"complexity": [2, 6],
|
"complexity": [2, 6],
|
||||||
},
|
|
||||||
"globals": {
|
|
||||||
"jasmine": false,
|
|
||||||
"describe": false,
|
|
||||||
"it": false,
|
|
||||||
"beforeEach": false,
|
|
||||||
"expect": false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,30 +0,0 @@
|
|||||||
const webpackConfig = require('./webpack.config')({test: true})
|
|
||||||
process.env.BABEL_ENV = 'test' // so we load the correct babel plugins
|
|
||||||
require('babel-register')
|
|
||||||
|
|
||||||
module.exports = function setKarmaConfig(config) {
|
|
||||||
config.set({
|
|
||||||
basePath: '',
|
|
||||||
frameworks: ['jasmine'],
|
|
||||||
files: ['src/**/*.test.js'],
|
|
||||||
exclude: [],
|
|
||||||
preprocessors: {
|
|
||||||
'src/**/*.test.js': ['webpack'],
|
|
||||||
},
|
|
||||||
webpack: webpackConfig,
|
|
||||||
webpackMiddleware: {noInfo: true},
|
|
||||||
reporters: ['progress', 'coverage'],
|
|
||||||
coverageReporter: {
|
|
||||||
reporters: [
|
|
||||||
{type: 'lcov', dir: 'coverage/', subdir: '.'},
|
|
||||||
{type: 'json', dir: 'coverage/', subdir: '.'},
|
|
||||||
{type: 'text-summary'},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
port: 9876,
|
|
||||||
colors: true,
|
|
||||||
logLevel: config.LOG_INFO,
|
|
||||||
browsers: ['Firefox'],
|
|
||||||
singleRun: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
12
package.json
12
package.json
@ -9,7 +9,6 @@
|
|||||||
"babel-core": "6.8.0",
|
"babel-core": "6.8.0",
|
||||||
"babel-eslint": "6.0.4",
|
"babel-eslint": "6.0.4",
|
||||||
"babel-loader": "6.2.4",
|
"babel-loader": "6.2.4",
|
||||||
"babel-plugin-__coverage__": "0.111111.11",
|
|
||||||
"babel-preset-es2015-webpack": "6.4.1",
|
"babel-preset-es2015-webpack": "6.4.1",
|
||||||
"babel-preset-stage-2": "6.5.0",
|
"babel-preset-stage-2": "6.5.0",
|
||||||
"cpy-cli": "1.0.0",
|
"cpy-cli": "1.0.0",
|
||||||
@ -18,13 +17,6 @@
|
|||||||
"eslint-config-kentcdodds": "6.2.1",
|
"eslint-config-kentcdodds": "6.2.1",
|
||||||
"eslint-loader": "1.3.0",
|
"eslint-loader": "1.3.0",
|
||||||
"ghooks": "1.2.1",
|
"ghooks": "1.2.1",
|
||||||
"jasmine-core": "2.4.1",
|
|
||||||
"karma": "0.13.22",
|
|
||||||
"karma-chrome-launcher": "1.0.1",
|
|
||||||
"karma-coverage": "1.0.0",
|
|
||||||
"karma-firefox-launcher": "1.0.0",
|
|
||||||
"karma-jasmine": "1.0.2",
|
|
||||||
"karma-webpack": "1.7.0",
|
|
||||||
"npm-run-all": "1.8.0",
|
"npm-run-all": "1.8.0",
|
||||||
"opt-cli": "1.4.2",
|
"opt-cli": "1.4.2",
|
||||||
"rimraf": "2.5.2",
|
"rimraf": "2.5.2",
|
||||||
@ -39,9 +31,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "karma start",
|
"validate": "npm-run-all --parallel validate-webpack:* lint",
|
||||||
"watch:test": "karma start --auto-watch --no-single-run",
|
|
||||||
"validate": "npm-run-all --parallel validate-webpack:* lint test",
|
|
||||||
"validate-webpack:dev": "webpack-validator webpack.config.js --env.dev",
|
"validate-webpack:dev": "webpack-validator webpack.config.js --env.dev",
|
||||||
"validate-webpack:prod": "webpack-validator webpack.config.js --env.prod",
|
"validate-webpack:prod": "webpack-validator webpack.config.js --env.prod",
|
||||||
"clean-dist": "rimraf dist",
|
"clean-dist": "rimraf dist",
|
||||||
|
|||||||
@ -1,404 +0,0 @@
|
|||||||
import Controller from './controller'
|
|
||||||
|
|
||||||
describe('controller', () => {
|
|
||||||
var subject, model, view
|
|
||||||
|
|
||||||
var setUpModel = function(todos) {
|
|
||||||
model.read.and.callFake(function(query, callback) {
|
|
||||||
callback = callback || query
|
|
||||||
callback(todos)
|
|
||||||
})
|
|
||||||
|
|
||||||
model.getCount.and.callFake(function(callback) {
|
|
||||||
|
|
||||||
var todoCounts = {
|
|
||||||
active: todos.filter(function(todo) {
|
|
||||||
return !todo.completed
|
|
||||||
}).length,
|
|
||||||
completed: todos.filter(function(todo) {
|
|
||||||
return !!todo.completed
|
|
||||||
}).length,
|
|
||||||
total: todos.length
|
|
||||||
}
|
|
||||||
|
|
||||||
callback(todoCounts)
|
|
||||||
})
|
|
||||||
|
|
||||||
model.remove.and.callFake(function(id, callback) {
|
|
||||||
callback()
|
|
||||||
})
|
|
||||||
|
|
||||||
model.create.and.callFake(function(title, callback) {
|
|
||||||
callback()
|
|
||||||
})
|
|
||||||
|
|
||||||
model.update.and.callFake(function(id, updateData, callback) {
|
|
||||||
callback()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var createViewStub = () => {
|
|
||||||
var eventRegistry = {}
|
|
||||||
return {
|
|
||||||
render: jasmine.createSpy('render'),
|
|
||||||
bind: function(event, handler) {
|
|
||||||
eventRegistry[event] = handler
|
|
||||||
},
|
|
||||||
trigger: function(event, parameter) {
|
|
||||||
eventRegistry[event](parameter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
model = jasmine.createSpyObj('model', ['read', 'getCount', 'remove', 'create', 'update'])
|
|
||||||
view = createViewStub()
|
|
||||||
subject = new Controller(model, view)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should show entries on start-up', () => {
|
|
||||||
setUpModel([])
|
|
||||||
|
|
||||||
subject.setView('')
|
|
||||||
|
|
||||||
expect(view.render).toHaveBeenCalledWith('showEntries', [])
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('routing', () => {
|
|
||||||
|
|
||||||
it('should show all entries without a route', () => {
|
|
||||||
var todo = {title: 'my todo'}
|
|
||||||
setUpModel([todo])
|
|
||||||
|
|
||||||
subject.setView('')
|
|
||||||
|
|
||||||
expect(view.render).toHaveBeenCalledWith('showEntries', [todo])
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should show all entries without "all" route', () => {
|
|
||||||
var todo = {title: 'my todo'}
|
|
||||||
setUpModel([todo])
|
|
||||||
|
|
||||||
subject.setView('#/')
|
|
||||||
|
|
||||||
expect(view.render).toHaveBeenCalledWith('showEntries', [todo])
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should show active entries', () => {
|
|
||||||
var todo = {title: 'my todo', completed: false}
|
|
||||||
setUpModel([todo])
|
|
||||||
|
|
||||||
subject.setView('#/active')
|
|
||||||
|
|
||||||
expect(model.read).toHaveBeenCalledWith({completed: false}, jasmine.any(Function))
|
|
||||||
expect(view.render).toHaveBeenCalledWith('showEntries', [todo])
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should show completed entries', () => {
|
|
||||||
var todo = {title: 'my todo', completed: true}
|
|
||||||
setUpModel([todo])
|
|
||||||
|
|
||||||
subject.setView('#/completed')
|
|
||||||
|
|
||||||
expect(model.read).toHaveBeenCalledWith({completed: true}, jasmine.any(Function))
|
|
||||||
expect(view.render).toHaveBeenCalledWith('showEntries', [todo])
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should show the content block when todos exists', () => {
|
|
||||||
setUpModel([{title: 'my todo', completed: true}])
|
|
||||||
|
|
||||||
subject.setView('')
|
|
||||||
|
|
||||||
expect(view.render).toHaveBeenCalledWith('contentBlockVisibility', {
|
|
||||||
visible: true
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should hide the content block when no todos exists', () => {
|
|
||||||
setUpModel([])
|
|
||||||
|
|
||||||
subject.setView('')
|
|
||||||
|
|
||||||
expect(view.render).toHaveBeenCalledWith('contentBlockVisibility', {
|
|
||||||
visible: false
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should check the toggle all button, if all todos are completed', () => {
|
|
||||||
setUpModel([{title: 'my todo', completed: true}])
|
|
||||||
|
|
||||||
subject.setView('')
|
|
||||||
|
|
||||||
expect(view.render).toHaveBeenCalledWith('toggleAll', {
|
|
||||||
checked: true
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should set the "clear completed" button', () => {
|
|
||||||
var todo = {id: 42, title: 'my todo', completed: true}
|
|
||||||
setUpModel([todo])
|
|
||||||
|
|
||||||
subject.setView('')
|
|
||||||
|
|
||||||
expect(view.render).toHaveBeenCalledWith('clearCompletedButton', {
|
|
||||||
completed: 1,
|
|
||||||
visible: true
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should highlight "All" filter by default', () => {
|
|
||||||
setUpModel([])
|
|
||||||
|
|
||||||
subject.setView('')
|
|
||||||
|
|
||||||
expect(view.render).toHaveBeenCalledWith('setFilter', '')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should highlight "Active" filter when switching to active view', () => {
|
|
||||||
setUpModel([])
|
|
||||||
|
|
||||||
subject.setView('#/active')
|
|
||||||
|
|
||||||
expect(view.render).toHaveBeenCalledWith('setFilter', 'active')
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('toggle all', () => {
|
|
||||||
it('should toggle all todos to completed', () => {
|
|
||||||
var todos = [{
|
|
||||||
id: 42,
|
|
||||||
title: 'my todo',
|
|
||||||
completed: false
|
|
||||||
}, {
|
|
||||||
id: 21,
|
|
||||||
title: 'another todo',
|
|
||||||
completed: false
|
|
||||||
}]
|
|
||||||
|
|
||||||
setUpModel(todos)
|
|
||||||
subject.setView('')
|
|
||||||
|
|
||||||
view.trigger('toggleAll', {completed: true})
|
|
||||||
|
|
||||||
expect(model.update).toHaveBeenCalledWith(42, {completed: true}, jasmine.any(Function))
|
|
||||||
expect(model.update).toHaveBeenCalledWith(21, {completed: true}, jasmine.any(Function))
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should update the view', () => {
|
|
||||||
var todos = [{
|
|
||||||
id: 42,
|
|
||||||
title: 'my todo',
|
|
||||||
completed: true
|
|
||||||
}]
|
|
||||||
|
|
||||||
setUpModel(todos)
|
|
||||||
subject.setView('')
|
|
||||||
|
|
||||||
view.trigger('toggleAll', {completed: false})
|
|
||||||
|
|
||||||
expect(view.render).toHaveBeenCalledWith('elementComplete', {id: 42, completed: false})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('new todo', () => {
|
|
||||||
it('should add a new todo to the model', () => {
|
|
||||||
setUpModel([])
|
|
||||||
|
|
||||||
subject.setView('')
|
|
||||||
|
|
||||||
view.trigger('newTodo', 'a new todo')
|
|
||||||
|
|
||||||
expect(model.create).toHaveBeenCalledWith('a new todo', jasmine.any(Function))
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should add a new todo to the view', () => {
|
|
||||||
setUpModel([])
|
|
||||||
|
|
||||||
subject.setView('')
|
|
||||||
|
|
||||||
view.render.calls.reset()
|
|
||||||
model.read.calls.reset()
|
|
||||||
model.read.and.callFake(function(callback) {
|
|
||||||
callback([{
|
|
||||||
title: 'a new todo',
|
|
||||||
completed: false
|
|
||||||
}])
|
|
||||||
})
|
|
||||||
|
|
||||||
view.trigger('newTodo', 'a new todo')
|
|
||||||
|
|
||||||
expect(model.read).toHaveBeenCalled()
|
|
||||||
|
|
||||||
expect(view.render).toHaveBeenCalledWith('showEntries', [{
|
|
||||||
title: 'a new todo',
|
|
||||||
completed: false
|
|
||||||
}])
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should clear the input field when a new todo is added', () => {
|
|
||||||
setUpModel([])
|
|
||||||
|
|
||||||
subject.setView('')
|
|
||||||
|
|
||||||
view.trigger('newTodo', 'a new todo')
|
|
||||||
|
|
||||||
expect(view.render).toHaveBeenCalledWith('clearNewTodo')
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('element removal', () => {
|
|
||||||
it('should remove an entry from the model', () => {
|
|
||||||
var todo = {id: 42, title: 'my todo', completed: true}
|
|
||||||
setUpModel([todo])
|
|
||||||
|
|
||||||
subject.setView('')
|
|
||||||
view.trigger('itemRemove', {id: 42})
|
|
||||||
|
|
||||||
expect(model.remove).toHaveBeenCalledWith(42, jasmine.any(Function))
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should remove an entry from the view', () => {
|
|
||||||
var todo = {id: 42, title: 'my todo', completed: true}
|
|
||||||
setUpModel([todo])
|
|
||||||
|
|
||||||
subject.setView('')
|
|
||||||
view.trigger('itemRemove', {id: 42})
|
|
||||||
|
|
||||||
expect(view.render).toHaveBeenCalledWith('removeItem', 42)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should update the element count', () => {
|
|
||||||
var todo = {id: 42, title: 'my todo', completed: true}
|
|
||||||
setUpModel([todo])
|
|
||||||
|
|
||||||
subject.setView('')
|
|
||||||
view.trigger('itemRemove', {id: 42})
|
|
||||||
|
|
||||||
expect(view.render).toHaveBeenCalledWith('updateElementCount', 0)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('remove completed', () => {
|
|
||||||
it('should remove a completed entry from the model', () => {
|
|
||||||
var todo = {id: 42, title: 'my todo', completed: true}
|
|
||||||
setUpModel([todo])
|
|
||||||
|
|
||||||
subject.setView('')
|
|
||||||
view.trigger('removeCompleted')
|
|
||||||
|
|
||||||
expect(model.read).toHaveBeenCalledWith({completed: true}, jasmine.any(Function))
|
|
||||||
expect(model.remove).toHaveBeenCalledWith(42, jasmine.any(Function))
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should remove a completed entry from the view', () => {
|
|
||||||
var todo = {id: 42, title: 'my todo', completed: true}
|
|
||||||
setUpModel([todo])
|
|
||||||
|
|
||||||
subject.setView('')
|
|
||||||
view.trigger('removeCompleted')
|
|
||||||
|
|
||||||
expect(view.render).toHaveBeenCalledWith('removeItem', 42)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('element complete toggle', () => {
|
|
||||||
it('should update the model', () => {
|
|
||||||
var todo = {id: 21, title: 'my todo', completed: false}
|
|
||||||
setUpModel([todo])
|
|
||||||
subject.setView('')
|
|
||||||
|
|
||||||
view.trigger('itemToggle', {id: 21, completed: true})
|
|
||||||
|
|
||||||
expect(model.update).toHaveBeenCalledWith(21, {completed: true}, jasmine.any(Function))
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should update the view', () => {
|
|
||||||
var todo = {id: 42, title: 'my todo', completed: true}
|
|
||||||
setUpModel([todo])
|
|
||||||
subject.setView('')
|
|
||||||
|
|
||||||
view.trigger('itemToggle', {id: 42, completed: false})
|
|
||||||
|
|
||||||
expect(view.render).toHaveBeenCalledWith('elementComplete', {id: 42, completed: false})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('edit item', () => {
|
|
||||||
it('should switch to edit mode', () => {
|
|
||||||
var todo = {id: 21, title: 'my todo', completed: false}
|
|
||||||
setUpModel([todo])
|
|
||||||
|
|
||||||
subject.setView('')
|
|
||||||
|
|
||||||
view.trigger('itemEdit', {id: 21})
|
|
||||||
|
|
||||||
expect(view.render).toHaveBeenCalledWith('editItem', {id: 21, title: 'my todo'})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should leave edit mode on done', () => {
|
|
||||||
var todo = {id: 21, title: 'my todo', completed: false}
|
|
||||||
setUpModel([todo])
|
|
||||||
|
|
||||||
subject.setView('')
|
|
||||||
|
|
||||||
view.trigger('itemEditDone', {id: 21, title: 'new title'})
|
|
||||||
|
|
||||||
expect(view.render).toHaveBeenCalledWith('editItemDone', {id: 21, title: 'new title'})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should persist the changes on done', () => {
|
|
||||||
var todo = {id: 21, title: 'my todo', completed: false}
|
|
||||||
setUpModel([todo])
|
|
||||||
|
|
||||||
subject.setView('')
|
|
||||||
|
|
||||||
view.trigger('itemEditDone', {id: 21, title: 'new title'})
|
|
||||||
|
|
||||||
expect(model.update).toHaveBeenCalledWith(21, {title: 'new title'}, jasmine.any(Function))
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should remove the element from the model when persisting an empty title', () => {
|
|
||||||
var todo = {id: 21, title: 'my todo', completed: false}
|
|
||||||
setUpModel([todo])
|
|
||||||
|
|
||||||
subject.setView('')
|
|
||||||
|
|
||||||
view.trigger('itemEditDone', {id: 21, title: ''})
|
|
||||||
|
|
||||||
expect(model.remove).toHaveBeenCalledWith(21, jasmine.any(Function))
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should remove the element from the view when persisting an empty title', () => {
|
|
||||||
var todo = {id: 21, title: 'my todo', completed: false}
|
|
||||||
setUpModel([todo])
|
|
||||||
|
|
||||||
subject.setView('')
|
|
||||||
|
|
||||||
view.trigger('itemEditDone', {id: 21, title: ''})
|
|
||||||
|
|
||||||
expect(view.render).toHaveBeenCalledWith('removeItem', 21)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should leave edit mode on cancel', () => {
|
|
||||||
var todo = {id: 21, title: 'my todo', completed: false}
|
|
||||||
setUpModel([todo])
|
|
||||||
|
|
||||||
subject.setView('')
|
|
||||||
|
|
||||||
view.trigger('itemEditCancel', {id: 21})
|
|
||||||
|
|
||||||
expect(view.render).toHaveBeenCalledWith('editItemDone', {id: 21, title: 'my todo'})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should not persist the changes on cancel', () => {
|
|
||||||
var todo = {id: 21, title: 'my todo', completed: false}
|
|
||||||
setUpModel([todo])
|
|
||||||
|
|
||||||
subject.setView('')
|
|
||||||
|
|
||||||
view.trigger('itemEditCancel', {id: 21})
|
|
||||||
|
|
||||||
expect(model.update).not.toHaveBeenCalled()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
Loading…
x
Reference in New Issue
Block a user