var Vue = require('src')
describe('Events API', function () {
var vm, spy
beforeEach(function () {
vm = new Vue()
spy = jasmine.createSpy('emitter')
})
it('$on', function () {
vm.$on('test', function () {
// expect correct context
expect(this).toBe(vm)
spy.apply(this, arguments)
})
vm.$emit('test', 1, 2, 3, 4)
expect(spy.calls.count()).toBe(1)
expect(spy).toHaveBeenCalledWith(1, 2, 3, 4)
})
it('$once', function () {
vm.$once('test', spy)
vm.$emit('test', 1, 2, 3)
vm.$emit('test', 2, 3, 4)
expect(spy.calls.count()).toBe(1)
expect(spy).toHaveBeenCalledWith(1, 2, 3)
})
it('$off', function () {
vm.$on('test1', spy)
vm.$on('test2', spy)
vm.$off()
vm.$emit('test1')
vm.$emit('test2')
expect(spy).not.toHaveBeenCalled()
})
it('$off event', function () {
vm.$on('test1', spy)
vm.$on('test2', spy)
vm.$off('test1')
vm.$off('test1') // test off something that's already off
vm.$emit('test1', 1)
vm.$emit('test2', 2)
expect(spy.calls.count()).toBe(1)
expect(spy).toHaveBeenCalledWith(2)
})
it('$off event + fn', function () {
var spy2 = jasmine.createSpy('emitter')
vm.$on('test', spy)
vm.$on('test', spy2)
vm.$off('test', spy)
vm.$emit('test', 1, 2, 3)
expect(spy).not.toHaveBeenCalled()
expect(spy2.calls.count()).toBe(1)
expect(spy2).toHaveBeenCalledWith(1, 2, 3)
})
it('$broadcast', function () {
var child1 = new Vue({ parent: vm })
var child2 = new Vue({ parent: vm })
var child3 = new Vue({ parent: child1 })
child1.$on('test', spy)
child2.$on('test', spy)
child3.$on('test', spy)
vm.$broadcast('test')
expect(spy.calls.count()).toBe(2) // should not propagate by default
})
it('$broadcast with propagation', function () {
var child1 = new Vue({ parent: vm })
var child2 = new Vue({ parent: vm })
var child3 = new Vue({ parent: child1 })
child1.$on('test', function () {
spy()
return true
})
child2.$on('test', spy)
child3.$on('test', spy)
vm.$broadcast('test')
expect(spy.calls.count()).toBe(3)
})
it('$broadcast optimization', function () {
var child = new Vue({ parent: vm })
var child2 = new Vue({ parent: child })
// hooks should not incurr the bookkeeping cost
child.$on('hook:created', function () {})
expect(vm._eventsCount['hook:created']).toBeUndefined()
function handler () {
spy()
return true
}
child.$on('test', handler)
expect(vm._eventsCount['test']).toBe(1)
// child2's $emit & $broadcast
// shouldn't get called if no child listens to the event
child2.$emit = spy
child2.$broadcast = spy
vm.$broadcast('test')
expect(spy.calls.count()).toBe(1)
// check $off bookkeeping
child.$off('test', handler)
expect(vm._eventsCount['test']).toBe(0)
function noop () {}
child.$on('test', noop)
child2.$on('test', noop)
expect(vm._eventsCount['test']).toBe(2)
child.$off('test')
expect(vm._eventsCount['test']).toBe(1)
child.$on('test', noop)
child2.$on('test', noop)
expect(vm._eventsCount['test']).toBe(3)
child.$off()
child2.$off()
expect(vm._eventsCount['test']).toBe(0)
})
it('$broadcast cancel', function () {
var child = new Vue({ parent: vm })
var child2 = new Vue({ parent: child })
child.$on('test', function () {
return false
})
child2.$on('test', spy)
vm.$broadcast('test')
expect(spy).not.toHaveBeenCalled()
})
it('$dispatch', function () {
var child = new Vue({ parent: vm })
var child2 = new Vue({ parent: child })
child2.$on('test', spy)
child.$on('test', spy)
vm.$on('test', spy)
child2.$dispatch('test')
expect(spy.calls.count()).toBe(2) // should trigger on self, but not propagate to root
})
it('$dispatch with propagation', function () {
var child = new Vue({ parent: vm })
var child2 = new Vue({ parent: child })
var child3 = new Vue({ parent: child2 })
child.$on('test', function () {
spy()
return true
})
vm.$on('test', spy)
child3.$dispatch('test')
expect(spy.calls.count()).toBe(2)
})
it('handle $dispatch by v-on inline-statement', function () {
var parent = new Vue({
el: document.createElement('div'),
template: '',
methods: {
onTest: function () {
spy()
}
},
components: {
child1: {
template: '',
methods: {
onTest: function () {
spy()
}
},
components: {
child2: {
template: '',
methods: {
onTest: function () {
spy()
return true
}
},
components: {
child3: {
template: '',
methods: {
onTest: function () {
spy()
return true
}
},
components: {
child4: {}
}
}
}
}
}
}
}
})
parent
.$refs.child // child1
.$refs.child // child2
.$refs.child // child3
.$refs.child // child4
.$dispatch('test')
expect(spy.calls.count()).toBe(3)
})
it('$dispatch forward on immediate inline component handler', function () {
var shouldPropagate = true
var parent = new Vue({
el: document.createElement('div'),
template: '',
events: {
test: spy
},
methods: {
onTest: function () {
spy()
return shouldPropagate
}
},
components: {
child: {}
}
})
parent.$refs.child.$dispatch('test')
expect(spy.calls.count()).toBe(2)
shouldPropagate = false
parent.$refs.child.$dispatch('test')
expect(spy.calls.count()).toBe(3)
})
})