testcafe-workshop/test/ControllerSpec.js
2016-04-04 21:30:38 -06:00

405 lines
10 KiB
JavaScript
Executable File

import Controller from '../js/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()
})
})
})