blob: b43b016e3036b40251d03a8fd337caf6ba182f37 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import chai from 'chai'
import sinon from 'sinon'
import sinonChai from 'sinon-chai'
const { expect } = chai
chai.use(sinonChai)
import Vm from '../../../../../runtime/frameworks/legacy/vm'
import { Document } from '../../../../../runtime/vdom'
describe('bind and fire events', () => {
let doc, customComponentMap, spy
function checkReady (vm, handler) {
/* istanbul ignore else */
if (vm._ready) {
handler()
}
else {
vm.$on('hook:ready', handler)
}
}
beforeEach(() => {
spy = sinon.spy()
doc = new Document('test', '', spy)
customComponentMap = {}
})
afterEach(() => {
doc.destroy()
})
it('bind event and fire in a single dom', (done) => {
customComponentMap.foo = {
template: {
type: 'container',
attr: {
a: function () { return this.x }
},
events: { click: 'handleClick' }
},
data: function () {
return { x: 1 }
},
methods: {
handleClick: function () {
this.x = 2
}
}
}
const app = { doc, customComponentMap }
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
checkReady(vm, function () {
expect(doc.body.event.click.handler).a('function')
const el = doc.body
expect(el.attr.a).eql(1)
expect(spy.args.length).eql(1)
expect(doc.listener.updates.length).eql(0)
el.event.click.handler({ xxx: 1 })
expect(el.attr.a).eql(2)
expect(spy.args.length).eql(2)
expect(spy.args[1][0]).eql([
{ module: 'dom', method: 'updateAttrs', args: [el.ref, { a: 2 }] }
])
done()
})
})
it('emit, broadcast and dispatch vm events', (done) => {
customComponentMap.foo = {
template: {
type: 'aaa',
children: [{ type: 'bar', component: true }]
}
}
customComponentMap.bar = {
template: {
type: 'bbb'
}
}
const app = { doc, customComponentMap }
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
checkReady(vm, function () {
doc.close()
expect(vm._childrenVms.length).eql(1)
const subVm = vm._childrenVms[0]
expect(vm._type).eql('foo')
expect(subVm._type).eql('bar')
const spyA = sinon.spy()
const spyB = sinon.spy()
vm.$on('customTypeA', spyA)
subVm.$on('customTypeA', spyB)
let detail = { aaa: 111 }
vm.$emit('customTypeA', detail)
expect(spyA.args.length).eql(1)
expect(spyB.args.length).eql(0)
detail = { aaa: 111 }
subVm.$emit('customTypeA', detail)
expect(spyA.args.length).eql(1)
expect(spyB.args.length).eql(1)
detail = { aaa: 111 }
vm.$broadcast('customTypeA', detail)
expect(spyA.args.length).eql(2)
expect(spyB.args.length).eql(2)
detail = { aaa: 111 }
subVm.$broadcast('customTypeA', detail)
expect(spyA.args.length).eql(2)
expect(spyB.args.length).eql(3)
detail = { aaa: 111 }
vm.$dispatch('customTypeA', detail)
expect(spyA.args.length).eql(3)
expect(spyB.args.length).eql(3)
detail = { aaa: 111 }
subVm.$dispatch('customTypeA', detail)
expect(spyA.args.length).eql(4)
expect(spyB.args.length).eql(4)
vm.$off('customTypeA', spyA)
subVm.$off('customTypeA')
detail = { aaa: 111 }
vm.$emit('customTypeA', detail)
detail = { aaa: 111 }
subVm.$emit('customTypeA', detail)
detail = { aaa: 111 }
vm.$broadcast('customTypeA', detail)
detail = { aaa: 111 }
subVm.$broadcast('customTypeA', detail)
detail = { aaa: 111 }
vm.$dispatch('customTypeA', detail)
detail = { aaa: 111 }
subVm.$dispatch('customTypeA', detail)
expect(spyA.args.length).eql(4)
expect(spyB.args.length).eql(4)
const spyAA = function (e) {
e.stop()
spyA()
}
const spyBB = function (e) {
e.stop()
spyB()
}
vm.$on('customTypeA', spyAA)
subVm.$on('customTypeA', spyBB)
vm.$off()
vm.$off('unknownTypeA', spyA)
detail = { aaa: 111 }
vm.$emit('customTypeA', detail)
expect(spyA.args.length).eql(5)
expect(spyB.args.length).eql(4)
detail = { aaa: 111 }
subVm.$emit('customTypeA', detail)
expect(spyA.args.length).eql(5)
expect(spyB.args.length).eql(5)
detail = { aaa: 111 }
vm.$broadcast('customTypeA', detail)
expect(spyA.args.length).eql(6)
expect(spyB.args.length).eql(5)
detail = { aaa: 111 }
subVm.$broadcast('customTypeA', detail)
expect(spyA.args.length).eql(6)
expect(spyB.args.length).eql(6)
detail = { aaa: 111 }
vm.$dispatch('customTypeA', detail)
expect(spyA.args.length).eql(7)
expect(spyB.args.length).eql(6)
detail = { aaa: 111 }
subVm.$dispatch('customTypeA', detail)
expect(spyA.args.length).eql(7)
expect(spyB.args.length).eql(7)
done()
})
})
it('broadcast for repeat vms', (done) => {
const vmSpy = sinon.spy()
const subVmSpy = sinon.spy()
customComponentMap.foo = {
data: function () {
return { list: [{ a: 1 }, { a: 2 }, { a: 3 }] }
},
template: {
type: 'container',
children: [{
type: 'bar', component: true,
repeat: function () { return this.list }
}]
},
events: {
customTypeA: function (e) {
vmSpy(this, e)
}
}
}
customComponentMap.bar = {
template: {
type: 'aaa'
},
events: {
customTypeA: function (e) {
subVmSpy(this, e)
}
}
}
const app = { doc, customComponentMap }
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
checkReady(vm, function () {
doc.close()
expect(vm._childrenVms.length).eql(3)
let detail = { aaa: 111 }
vm.$emit('customTypeA', detail)
expect(vmSpy.args.length).eql(1)
expect(subVmSpy.args.length).eql(0)
expect(vmSpy.args[0][0]).equal(vm)
expect(vmSpy.args[0][1]).is.an.object
expect(vmSpy.args[0][1].detail).equal(detail)
detail = { aaa: 111 }
vm.$broadcast('customTypeA', detail)
expect(vmSpy.args.length).eql(2)
expect(subVmSpy.args.length).eql(3)
expect(vmSpy.args[1][0]).equal(vm)
expect(vmSpy.args[1][1]).is.an.object
expect(vmSpy.args[1][1].detail).equal(detail)
expect(subVmSpy.args[1][0]).equal(vm._childrenVms[1])
expect(subVmSpy.args[1][1]).is.an.object
expect(subVmSpy.args[1][1].detail).equal(detail)
done()
})
})
it('dispatch from repeat vms', (done) => {
const vmSpy = sinon.spy()
const subVmSpy = sinon.spy()
customComponentMap.foo = {
data: function () {
return { list: [{ a: 1 }, { a: 2 }, { a: 3 }] }
},
template: {
type: 'container',
children: [{
type: 'bar', component: true,
repeat: function () { return this.list }
}]
},
events: {
customTypeA: function (e) {
vmSpy(this, e)
}
}
}
customComponentMap.bar = {
template: {
type: 'aaa'
},
events: {
customTypeA: function (e) {
subVmSpy(this, e)
}
}
}
const app = { doc, customComponentMap }
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
checkReady(vm, function () {
doc.close()
expect(vm._childrenVms.length).eql(3)
let detail = { aaa: 111 }
const subVm = vm._childrenVms[1]
subVm.$emit('customTypeA', detail)
expect(vmSpy.args.length).eql(0)
expect(subVmSpy.args.length).eql(1)
expect(subVmSpy.args[0][0]).equal(subVm)
expect(subVmSpy.args[0][1]).is.an.object
expect(subVmSpy.args[0][1].detail).equal(detail)
detail = { aaa: 111 }
subVm.$dispatch('customTypeA', detail)
expect(vmSpy.args.length).eql(1)
expect(subVmSpy.args.length).eql(2)
expect(vmSpy.args[0][0]).equal(vm)
expect(vmSpy.args[0][1]).is.an.object
expect(vmSpy.args[0][1].detail).equal(detail)
expect(subVmSpy.args[1][0]).equal(subVm)
expect(subVmSpy.args[1][1]).is.an.object
expect(subVmSpy.args[1][1].detail).equal(detail)
done()
})
})
it('lifecycel events', (done) => {
const vmSpy = sinon.spy()
customComponentMap.foo = {
template: {
type: 'aaa',
children: [{ type: 'bar', component: true }]
},
data: function () {
return {
x: 1
}
},
init: function (e) {
vmSpy(this, e)
expect(this._data).is.not.ok
expect(this.x).is.not.ok
expect(this._parentEl).is.not.ok
},
created: function (e) {
vmSpy(this, e)
expect(this._data).is.ok
expect(this.x).is.ok
expect(this._parentEl).is.not.ok
},
ready: function (e) {
vmSpy(this, e)
expect(this._data).is.ok
expect(this.x).is.ok
expect(this._parentEl).is.ok
expect(this._parentEl.children.length).eql(1)
}
}
customComponentMap.bar = {
template: {
type: 'bbb'
},
created: function (e) {
vmSpy(this, e)
}
}
const app = { doc, customComponentMap }
const evSpy = sinon.spy()
const vm = new Vm('foo', customComponentMap.foo, { _app: app }, null, null,
{
'hook:init': () => evSpy('hook:init'),
'hook:created': () => evSpy('hook:created'),
'hook:ready': () => evSpy('hook:ready')
}
)
checkReady(vm, function () {
doc.close()
expect(vmSpy.args.length).eql(4)
const subVm = vm._childrenVms[0]
const calls = vmSpy.args.map(args => [args[0], args[1].type])
expect(calls).eql([
[vm, 'hook:init'],
[vm, 'hook:created'],
[subVm, 'hook:created'],
[vm, 'hook:ready']
])
expect(evSpy.callCount).to.be.equal(3)
expect(evSpy.args).to.deep.equal([
['hook:init'],
['hook:created'],
['hook:ready']
])
done()
})
})
})