blob: 761c913da00bb0d981ece4a1ee054adc749250ac [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'
import { init as resetTaskHandler } from '../../../../../runtime/bridge/TaskCenter'
import Differ from '../../../../../runtime/frameworks/legacy/app/differ'
const oriCallNative = global.callNative
describe('generate virtual dom for a single vm', () => {
const spy = sinon.spy()
const spy1 = sinon.spy()
let doc
let customComponentMap
let differ
beforeEach(() => {
differ = new Differ('test')
doc = new Document('test', '', function (actions) {
actions.forEach((action) => {
spy.apply(null, ['test', action.method].concat(action.args))
})
})
customComponentMap = {}
})
afterEach(() => {
spy.reset()
spy1.reset()
doc.destroy()
})
it('$watch', () => {
const data = {
a: {
b: 1
}
}
customComponentMap.foo = {
template: {
type: 'container'
},
data: data
}
const app = { doc, customComponentMap, differ }
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
expect(vm._app).equal(app)
expect(doc.body).is.an.object
vm.$watch(function () {
return this.a.b
}, (value) => {
expect(value).eql(2)
})
data.a.b = 2
})
it('vm.data is not a object', () => {
const data = 'hello'
customComponentMap.foo = {
template: {
type: 'container'
},
data: data
}
const app = { doc, customComponentMap, differ }
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
expect(vm._app).equal(app)
expect(doc.body).is.an.object
})
it('no param parentVm', () => {
customComponentMap.foo = {
template: {
type: 'container'
}
}
const vm = new Vm('foo', customComponentMap.foo, null)
expect(vm._app).is.an.object
expect(doc.body).is.an.object
})
it('no param options', () => {
const app = {}
const vm = new Vm('foo', null, { _app: app })
expect(vm._app).is.an.object
expect(doc.body).is.an.object
})
it('old method.ready', () => {
customComponentMap.foo = {
template: {
type: 'container'
},
methods: {
ready: spy1
}
}
const app = { doc, customComponentMap, differ }
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
expect(vm._app).equal(app)
expect(doc.body).is.an.object
expect(doc.body.type).eql('container')
expect(spy1).callCount(1)
})
it('generate an static element ', () => {
customComponentMap.foo = {
template: {
type: 'container',
attr: {
a: 1,
b: 2,
static: ''
},
style: {
c: 3,
d: 4
}
}
}
const app = { doc, customComponentMap, differ }
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
expect(vm._app).equal(app)
expect(vm._static).eql(true)
expect(doc.body).is.an.object
expect(doc.body.type).eql('container')
expect(doc.body.attr).eql({ a: 1, b: 2, static: '' })
expect(doc.body.style).eql({ c: 3, d: 4 })
expect(doc.body.children).is.an.array
expect(doc.body.children.length).eql(0)
})
it('generate an single element', () => {
customComponentMap.foo = {
template: {
type: 'container',
attr: {
a: 1,
b: 2
},
style: {
c: 3,
d: 4
}
}
}
const app = { doc, customComponentMap, differ }
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
expect(vm._app).equal(app)
expect(doc.body).is.an.object
expect(doc.body.type).eql('container')
expect(doc.body.attr).eql({ a: 1, b: 2 })
expect(doc.body.style).eql({ c: 3, d: 4 })
expect(doc.body.children).is.an.array
expect(doc.body.children.length).eql(0)
})
it('generate an element tree', () => {
customComponentMap.foo = {
template: {
type: 'container', attr: { a: 1, b: 2 }, style: { c: 3, d: 4 },
children: [
{ type: 'image', attr: { src: '<some image url>' }},
{ type: 'text', attr: { value: '<some text content>' }}
]
}
}
const app = { doc, customComponentMap, differ }
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
expect(vm._app).equal(app)
const el = doc.body
expect(el.type).eql('container')
expect(el.attr).eql({ a: 1, b: 2 })
expect(el.style).eql({ c: 3, d: 4 })
expect(el.children).is.an.array
expect(el.children.length).eql(2)
const image = el.children[0]
const text = el.children[1]
expect(image.type).eql('image')
expect(image.attr).eql({ src: '<some image url>' })
expect(text.type).eql('text')
expect(text.attr).eql({ value: '<some text content>' })
})
it('generate an element tree with component options', () => {
customComponentMap.foo = {
template: {
type: 'cell',
children: [
{ type: 'text', attr: { value: '<some text content>' }}
]
}
}
const app = { doc, customComponentMap, differ }
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
expect(spy.firstCall.args[0]).to.be.equal('test')
expect(spy.firstCall.args[1]).to.be.equal('createBody')
expect(spy.firstCall.args[2]).to.deep.equal({
ref: '_root',
type: 'cell',
attr: {
append: 'tree'
},
children: [{
ref: spy.firstCall.args[2].children[0].ref,
type: 'text',
attr: {
value: '<some text content>'
},
style: {}
}],
style: {}
})
expect(vm._app).equal(app)
const el = doc.body
expect(el.type).eql('cell')
expect(el.children).is.an.array
expect(el.children.length).eql(1)
const text = el.children[0]
expect(text.type).eql('text')
expect(text.attr).eql({ value: '<some text content>' })
})
it('generate an element tree with data binding', () => {
customComponentMap.foo = {
template: {
type: 'container', attr: { a: 1, b: 2 }, style: { c: 3, d: 4 },
children: [
{ type: 'image', attr: { src: function () { return this.x } }},
{ type: 'text', attr: { value: function () { return this.n } }},
{ type: 'text', attr: { value: function () { return this.m } }}
]
},
data: {
x: '<some image url>', y: '<some text content>'
},
computed: {
n: function () {
return this.y.toUpperCase()
},
m: {
get: function () {
return this.y.toUpperCase()
},
set: function (v) {
this.y = v
}
}
}
}
const app = { doc, customComponentMap, differ }
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
expect(vm._app).equal(app)
expect(vm.x).eql('<some image url>')
expect(vm.y).eql('<some text content>')
expect(vm.n).eql('<SOME TEXT CONTENT>')
expect(vm.m).eql('<SOME TEXT CONTENT>')
const el = doc.body
expect(el.type).eql('container')
expect(el.attr).eql({ a: 1, b: 2 })
expect(el.style).eql({ c: 3, d: 4 })
expect(el.children).is.an.array
expect(el.children.length).eql(3)
const image = el.children[0]
const text = el.children[1]
const text2 = el.children[2]
expect(image.type).eql('image')
expect(image.attr).eql({ src: '<some image url>' })
expect(text.type).eql('text')
expect(text.attr).eql({ value: '<SOME TEXT CONTENT>' })
expect(text2.type).eql('text')
expect(text2.attr).eql({ value: '<SOME TEXT CONTENT>' })
vm.x = '<some image url>'
differ.flush()
expect(el).equal(doc.body)
expect(image).equal(el.children[0])
expect(text).equal(el.children[1])
expect(text2).equal(el.children[2])
vm.x = 'other string value'
differ.flush()
expect(el).equal(doc.body)
expect(image).equal(el.children[0])
expect(image.attr).eql({ src: 'other string value' })
vm.y = 'other string value'
differ.flush()
expect(el).equal(doc.body)
expect(text).equal(el.children[1])
expect(text.attr).eql({ value: 'OTHER STRING VALUE' })
expect(text2).equal(el.children[2])
expect(text2.attr).eql({ value: 'OTHER STRING VALUE' })
vm.m = 'third string value'
differ.flush()
expect(vm.x).eql('other string value')
expect(vm.y).eql('third string value')
expect(vm.n).eql('THIRD STRING VALUE')
expect(vm.m).eql('THIRD STRING VALUE')
expect(el).equal(doc.body)
expect(text).equal(el.children[1])
expect(text.attr).eql({ value: 'THIRD STRING VALUE' })
expect(text2).equal(el.children[2])
expect(text2.attr).eql({ value: 'THIRD STRING VALUE' })
})
it('generate an element tree with shown', () => {
customComponentMap.foo = {
template: {
type: 'container',
children: [
{ type: 'prev' },
{
shown: function () { return this.y },
type: 'image', attr: { src: function () { return this.x } }
},
{ type: 'next' }
]
},
data: {
x: '<some image url>', y: true
}
}
const app = { doc, customComponentMap, differ }
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
expect(vm._app).equal(app)
expect(vm.x).eql('<some image url>')
expect(vm.y).eql(true)
const el = doc.body
expect(el.type).eql('container')
expect(el.children).is.an.array
expect(el.children.length).eql(5)
const prev = el.children[0]
const starter = el.children[1]
const image = el.children[2]
const ender = el.children[3]
const next = el.children[4]
expect(prev.type).eql('prev')
expect(starter.type).eql('comment')
expect(ender.type).eql('comment')
expect(next.type).eql('next')
expect(image.type).eql('image')
expect(image.attr).eql({ src: '<some image url>' })
vm.y = false
differ.flush()
expect(el).equal(doc.body)
expect(el.children).is.an.array
expect(el.children.length).eql(4)
expect(prev).equal(el.children[0])
expect(starter).equal(el.children[1])
expect(ender).equal(el.children[2])
expect(next).equal(el.children[3])
vm.y = true
differ.flush()
expect(el).equal(doc.body)
expect(el.children).is.an.array
expect(el.children.length).eql(5)
expect(prev).equal(el.children[0])
expect(starter).equal(el.children[1])
const image2 = el.children[2]
expect(image2.type).eql('image')
expect(image2.attr).eql({ src: '<some image url>' })
expect(ender).equal(el.children[3])
expect(next).equal(el.children[4])
})
it('generate an element tree with repeat', () => {
customComponentMap.foo = {
template: {
type: 'container',
children: [
{ type: 'prev' },
{
repeat: function () { return this.list },
type: 'image', attr: { src: function () { return this.x } }
},
{ type: 'next' }
]
},
data: {
x: '<some image url>',
list: [
{ uid: 1, x: 1 }, { uid: 2, x: 2 }, { uid: 3 }
]
}
}
const app = { doc, customComponentMap, differ }
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
expect(vm._app).equal(app)
expect(vm.x).eql('<some image url>')
expect(vm.list).eql([
{ uid: 1, x: 1, $index: 0 },
{ uid: 2, x: 2, $index: 1 },
{ uid: 3, $index: 2 }])
const el = doc.body
expect(el.type).eql('container')
expect(el.children).is.an.array
expect(el.children.length).eql(7)
const prev = el.children[0]
const starter = el.children[1]
const ender = el.children[5]
const next = el.children[6]
expect(prev.type).eql('prev')
expect(starter.type).eql('comment')
expect(ender.type).eql('comment')
expect(next.type).eql('next')
expect(el.children[2].type).eql('image')
expect(el.children[2].attr).eql({ src: 1 })
expect(el.children[3].type).eql('image')
expect(el.children[3].attr).eql({ src: 2 })
expect(el.children[4].type).eql('image')
expect(el.children[4].attr).eql({ src: '<some image url>' })
vm.list[1].x = 3
differ.flush()
expect(el.children.length).eql(7)
expect(el.children[2].attr).eql({ src: 1 })
expect(el.children[3].attr).eql({ src: 3 })
expect(el.children[4].attr).eql({ src: '<some image url>' })
vm.x = 'other string value'
differ.flush()
expect(el.children.length).eql(7)
expect(el.children[2].attr).eql({ src: 1 })
expect(el.children[3].attr).eql({ src: 3 })
expect(el.children[4].attr).eql({ src: 'other string value' })
vm.list.push({ uid: 4, x: 4 })
vm.list.push({ uid: 5 }, { uid: 6, x: 6 })
differ.flush()
expect(el.children.length).eql(10)
expect(el.children[2].attr).eql({ src: 1 })
expect(el.children[3].attr).eql({ src: 3 })
expect(el.children[4].attr).eql({ src: 'other string value' })
expect(el.children[5].attr).eql({ src: 4 })
expect(el.children[6].attr).eql({ src: 'other string value' })
expect(el.children[7].attr).eql({ src: 6 })
vm.list.splice(1, 2, { uid: 7, x: 7 })
differ.flush()
expect(el.children.length).eql(9)
expect(el.children[2].attr).eql({ src: 1 })
expect(el.children[3].attr).eql({ src: 7 })
expect(el.children[4].attr).eql({ src: 4 })
expect(el.children[5].attr).eql({ src: 'other string value' })
expect(el.children[6].attr).eql({ src: 6 })
vm.list.$set(0, { uid: 321, x: 32 })
vm.list.$set(10, { uid: 8889, x: 8888 })
differ.flush()
expect(el.children.length).eql(10)
expect(el.children[2].attr).eql({ src: 32 })
expect(el.children[7].attr).eql({ src: 8888 })
vm.list.unshift({ uid: 12345, x: 123456 })
differ.flush()
expect(el.children.length).eql(11)
expect(el.children[2].attr).eql({ src: 123456 })
})
it('generate an static element tree with shown and repeat', () => {
customComponentMap.foo = {
template: {
type: 'container',
attr: {
static: ''
},
children: [
{ type: 'prev' },
{
shown: function () { return this.x % 2 === 0 },
repeat: function () { return this.list },
type: 'image', attr: { src: function () { return this.x } }
},
{ type: 'next' }
]
},
data: {
x: '<some image url>',
list: [
{ uid: 1, x: 1 }, { uid: 2, x: 2 }, { uid: 3 }
]
}
}
const app = { doc, customComponentMap, differ }
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
expect(vm._app).equal(app)
expect(vm._static).equal(true)
expect(vm.x).eql('<some image url>')
expect(vm.list).eql([
{ uid: 1, x: 1, $index: 0 },
{ uid: 2, x: 2, $index: 1 },
{ uid: 3, $index: 2 }])
const el = doc.body
expect(el.type).eql('container')
expect(el.children).is.an.array
expect(el.children.length).eql(11)
const prev = el.children[0]
const next = el.children[10]
expect(prev.type).eql('prev')
expect(el.children[1].type).eql('comment')
expect(el.children[1].value).eql('start')
expect(el.children[9].type).eql('comment')
expect(el.children[9].value).eql('end')
expect(el.children[2].type).eql('comment')
expect(el.children[2].value).eql('start')
expect(el.children[3].type).eql('comment')
expect(el.children[3].value).eql('end')
expect(el.children[4].type).eql('comment')
expect(el.children[4].value).eql('start')
expect(el.children[5].type).eql('image')
expect(el.children[5].attr).eql({ src: 2 })
expect(el.children[6].type).eql('comment')
expect(el.children[6].value).eql('end')
expect(el.children[7].type).eql('comment')
expect(el.children[7].value).eql('start')
expect(el.children[8].type).eql('comment')
expect(el.children[8].value).eql('end')
expect(next.type).eql('next')
vm.list[0].x = 4
differ.flush()
expect(el.children.length).eql(11)
expect(el.children[5].type).eql('image')
expect(el.children[5].attr).eql({ src: 2 })
})
it('generate an element tree which root element with shown', () => {
customComponentMap.foo = {
template: {
type: 'container',
shown: function () { return this.x % 2 === 0 }
},
data: {
x: 2
}
}
const app = { doc, customComponentMap, differ }
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
expect(vm._app).equal(app)
expect(vm.x).eql(2)
})
it('append tree', () => {
customComponentMap.foo = {
template: {
type: 'container',
attr: {
append: 'tree'
},
children: [
{ type: 'a' },
{ repeat: {}}
]
}
}
const app = { doc, customComponentMap, differ }
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
expect(vm._app).equal(app)
})
it('repeat is not a function', () => {
customComponentMap.foo = {
template: {
type: 'container',
children: [
{ type: 'a' },
{ repeat: {}}
]
}
}
const app = { doc, customComponentMap, differ }
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
expect(vm._app).equal(app)
})
it('repeat oldStyle with item which not a object', () => {
customComponentMap.foo = {
template: {
type: 'container',
children: [
{ type: 'a' },
{ repeat: function () { return [1, 2, 3] } }
]
}
}
const app = { doc, customComponentMap, differ }
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
expect(vm._app).equal(app)
})
it('classList length is zero', () => {
customComponentMap.foo = {
template: {
type: 'container',
classList: []
}
}
const app = { doc, customComponentMap, differ }
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
expect(vm._app).equal(app)
})
it('classList is a function', () => {
customComponentMap.foo = {
template: {
type: 'container',
classList: function () { return [] }
}
}
const app = { doc, customComponentMap, differ }
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
expect(vm._app).equal(app)
})
it('generate an element tree which root element with repeat', () => {
customComponentMap.foo = {
template: {
type: 'container',
repeat: function () { return this.list }
},
data: {
list: [
{ uid: 1, x: 1 }, { uid: 2, x: 2 }, { uid: 3 }
]
}
}
const app = { doc, customComponentMap, differ }
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
expect(vm._app).equal(app)
expect(vm.list).eql([
{ uid: 1, x: 1 },
{ uid: 2, x: 2 },
{ uid: 3 }
])
})
it('generate an element tree with shown and repeat', () => {
customComponentMap.foo = {
template: {
type: 'container',
children: [
{ type: 'prev' },
{
shown: function () { return this.x % 2 === 0 },
repeat: function () { return this.list },
type: 'image', attr: { src: function () { return this.x } }
},
{ type: 'next' }
]
},
data: {
x: '<some image url>',
list: [
{ uid: 1, x: 1 }, { uid: 2, x: 2 }, { uid: 3 }
]
}
}
const app = { doc, customComponentMap, differ }
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
expect(vm._app).equal(app)
expect(vm.x).eql('<some image url>')
expect(vm.list).eql([
{ uid: 1, x: 1, $index: 0 },
{ uid: 2, x: 2, $index: 1 },
{ uid: 3, $index: 2 }])
const el = doc.body
expect(el.type).eql('container')
expect(el.children).is.an.array
expect(el.children.length).eql(11)
const prev = el.children[0]
const next = el.children[10]
expect(prev.type).eql('prev')
expect(el.children[1].type).eql('comment')
expect(el.children[1].value).eql('start')
expect(el.children[9].type).eql('comment')
expect(el.children[9].value).eql('end')
expect(el.children[2].type).eql('comment')
expect(el.children[2].value).eql('start')
expect(el.children[3].type).eql('comment')
expect(el.children[3].value).eql('end')
expect(el.children[4].type).eql('comment')
expect(el.children[4].value).eql('start')
expect(el.children[5].type).eql('image')
expect(el.children[5].attr).eql({ src: 2 })
expect(el.children[6].type).eql('comment')
expect(el.children[6].value).eql('end')
expect(el.children[7].type).eql('comment')
expect(el.children[7].value).eql('start')
expect(el.children[8].type).eql('comment')
expect(el.children[8].value).eql('end')
expect(next.type).eql('next')
vm.list[0].x = 4
differ.flush()
expect(el.children.length).eql(12)
expect(el.children[3].type).eql('image')
expect(el.children[3].attr).eql({ src: 4 })
expect(el.children[6].type).eql('image')
expect(el.children[6].attr).eql({ src: 2 })
})
it('generate more than one group of elements with the same repeat data', () => {
customComponentMap.foo = {
template: {
type: 'container',
children: [
{ type: 'begin' },
{
repeat: {
expression: function () { return this.list },
value: 'v1'
},
type: 'image', attr: { src: function () { return this.v1.x } }
},
{ type: 'middle' },
{
repeat: {
expression: function () { return this.list },
value: 'v2'
},
type: 'text', attr: { value: function () { return this.v2.x } }
},
{ type: 'end' }
]
},
data: {
list: [
{ uid: 1, x: 1 }, { uid: 2, x: 2 }, { uid: 3 }
]
}
}
const app = { doc, customComponentMap, differ }
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
expect(vm._app).equal(app)
expect(vm.list).eql([
{ uid: 1, x: 1 },
{ uid: 2, x: 2 },
{ uid: 3 }])
const el = doc.body
expect(el.type).eql('container')
expect(el.children).is.an.array
// [begin, comment, image x 3, comment, middle, comment, text x 3, comment, end]
expect(el.children.length).eql(13)
expect(el.children[0].type).eql('begin')
expect(el.children[1].type).eql('comment')
expect(el.children[1].value).eql('start')
expect(el.children[2].type).eql('image')
expect(el.children[2].attr).eql({ src: 1 })
expect(el.children[3].type).eql('image')
expect(el.children[3].attr).eql({ src: 2 })
expect(el.children[4].type).eql('image')
expect(el.children[4].attr).eql({})
expect(el.children[5].type).eql('comment')
expect(el.children[5].value).eql('end')
expect(el.children[6].type).eql('middle')
expect(el.children[7].type).eql('comment')
expect(el.children[7].value).eql('start')
expect(el.children[8].type).eql('text')
expect(el.children[8].attr).eql({ value: 1 })
expect(el.children[9].type).eql('text')
expect(el.children[9].attr).eql({ value: 2 })
expect(el.children[10].type).eql('text')
expect(el.children[10].attr).eql({})
expect(el.children[11].type).eql('comment')
expect(el.children[11].value).eql('end')
expect(el.children[12].type).eql('end')
vm.list[0].x = 4
differ.flush()
expect(el.children.length).eql(13)
expect(el.children[2].attr).eql({ src: 4 })
expect(el.children[8].attr).eql({ value: 4 })
// [begin, comment, image x 4, comment, middle, comment, text x 4, comment, end]
vm.list.push({ uid: 10, x: 10 })
differ.flush()
expect(el.children.length).eql(15)
expect(el.children[5].attr).eql({ src: 10 })
expect(el.children[12].attr).eql({ value: 10 })
// [begin, comment, image x 2, comment, middle, comment, text x 2, comment, end]
vm.list = [
{ uid: 100, x: 100 }, { uid: 1, x: 1 }
]
differ.flush()
expect(el.children.length).eql(11)
expect(el.children[2].attr).eql({ src: 100 })
expect(el.children[3].attr).eql({ src: 1 })
expect(el.children[7].attr).eql({ value: 100 })
expect(el.children[8].attr).eql({ value: 1 })
vm.list[0].x = 4
differ.flush()
expect(el.children.length).eql(11)
expect(el.children[2].attr).eql({ src: 4 })
expect(el.children[3].attr).eql({ src: 1 })
expect(el.children[7].attr).eql({ value: 4 })
expect(el.children[8].attr).eql({ value: 1 })
vm.list[1].x = 5
differ.flush()
expect(el.children.length).eql(11)
expect(el.children[2].attr).eql({ src: 4 })
expect(el.children[3].attr).eql({ src: 5 })
expect(el.children[7].attr).eql({ value: 4 })
expect(el.children[8].attr).eql({ value: 5 })
})
it('generate an element with external data', () => {
customComponentMap.foo = {
data: () => {
return { a: 10, b: 20 }
},
template: {
type: 'container',
attr: {
x: function () { return this.a },
y: function () { return this.b }
}
}
}
const app = { doc, customComponentMap, differ }
const vm = new Vm('foo', customComponentMap.foo, { _app: app }, null, { a: 1000 })
expect(vm._app).equal(app)
const el = doc.body
expect(el.type).eql('container')
expect(el.attr).eql({ x: 1000, y: 20 })
vm.a = 100
vm.b = 200
differ.flush()
expect(el).equal(doc.body)
expect(el.attr).eql({ x: 100, y: 200 })
})
})
describe('generate virtual dom for sub vm', () => {
let doc
let customComponentMap
let differ
beforeEach(() => {
global.callNative = function () {}
resetTaskHandler()
doc = new Document('test', null, null)
customComponentMap = {}
differ = new Differ('test')
})
afterEach(() => {
doc.destroy()
global.callNative = oriCallNative
})
it('generate sub elements', () => {
customComponentMap.foo = {
data: function () {
return {
showbar1: false,
showbar2: false,
bar2list: [{
id: 'bar2-1'
}, {
id: 'bar2-2'
}]
}
},
template: {
type: 'div',
children: [
{ type: 'bar', id: 'bar', component: true,
events: { click: 'handleClick' }
},
{ type: 'bar1',
shown: function () { return this.showbar1 },
id: 'bar1', component: true
},
{ type: 'bar2',
shown: function () { return this.showbar2 },
repeat: function () { return this.bar2list },
id: function () { return this.id },
component: true
}
]
},
methods: {
handleClick: sinon.spy()
}
}
customComponentMap.bar = {
template: {
type: 'container',
children: [{ type: 'aaa' }, { type: 'bbb' }]
}
}
customComponentMap.bar1 = {
template: {
type: 'container',
children: [{ type: 'aaaa' }, { type: 'bbbb' }]
}
}
const app = { doc, customComponentMap, differ }
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
expect(vm._app).equal(app)
expect(vm._rootEl).to.deep.equal(vm._parentEl.children[0])
expect(vm._childrenVms.length).to.be.equal(1)
expect(vm._childrenVms[0]).to.deep.equal(vm._ids['bar'].vm)
expect(vm._childrenVms[0]._rootEl).to.deep.equal(vm._ids['bar'].el)
const el = doc.body
expect(el.type).eql('div')
expect(el.pureChildren).is.an.array
expect(el.pureChildren.length).eql(1)
const sub = el.children[0]
expect(sub.type).eql('container')
expect(sub.children).is.an.array
expect(sub.children.length).eql(2)
expect(sub.children[0].type).eql('aaa')
expect(sub.children[1].type).eql('bbb')
expect(sub.event.click).is.a.function
const spy = customComponentMap.foo.methods.handleClick
sub.event.click.handler(1, 2, 3)
expect(spy.args.length).eql(1)
expect(spy.args[0]).eql([1, 2, 3])
vm.showbar1 = true
differ.flush()
expect(vm._childrenVms.length).to.be.equal(2)
expect(vm._childrenVms[1]).to.deep.equal(vm._ids['bar1'].vm)
expect(vm._childrenVms[1]._rootEl).to.deep.equal(vm._ids['bar1'].el)
vm.showbar2 = true
differ.flush()
expect(vm._ids['bar2-1'].vm).to.be.not.undefined
expect(vm._ids['bar2-1'].el).to.be.not.undefined
expect(vm._ids['bar2-2'].vm).to.be.not.undefined
expect(vm._ids['bar2-2'].el).to.be.not.undefined
})
it('generate sub element with static', () => {
customComponentMap.foo = {
template: {
type: 'container',
attr: {
static: ''
},
children: [{ type: 'bar', component: true }]
}
}
customComponentMap.bar = {
replace: true,
template: {
type: 'container',
children: [{ type: 'aaa' }]
}
}
const app = { doc, customComponentMap, differ }
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
expect(vm._app).equal(app)
expect(vm._static).eql(true)
const el = doc.body
expect(el.type).eql('container')
expect(el.children).is.an.array
expect(el.children.length).eql(1)
const aaa = el.children[0]
expect(aaa.type).eql('aaa')
expect(vm._childrenVms.length).to.be.equal(1)
expect(vm._childrenVms[0]._static).eql(true)
})
it('generate replaced sub element', () => {
customComponentMap.foo = {
template: {
type: 'container',
children: [{ type: 'bar', component: true }]
}
}
customComponentMap.bar = {
replace: true,
template: {
type: 'container',
children: [{ type: 'aaa' }]
}
}
const app = { doc, customComponentMap, differ }
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
expect(vm._app).equal(app)
const el = doc.body
expect(el.type).eql('container')
expect(el.children).is.an.array
expect(el.children.length).eql(1)
const aaa = el.children[0]
expect(aaa.type).eql('aaa')
})
it('generate replaced sub elements', () => {
customComponentMap.foo = {
template: {
type: 'container',
children: [{ type: 'bar', component: true }]
}
}
customComponentMap.bar = {
replace: true,
template: {
type: 'container',
children: [{ type: 'aaa' }, { type: 'bbb' }]
}
}
const app = { doc, customComponentMap, differ }
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
expect(vm._app).equal(app)
const el = doc.body
expect(el.type).eql('container')
expect(el.children).is.an.array
expect(el.children.length).eql(4)
expect(el.children[0].type).eql('comment')
const aaa = el.children[1]
expect(aaa.type).eql('aaa')
const bbb = el.children[2]
expect(bbb.type).eql('bbb')
expect(el.children[3].type).eql('comment')
})
it('generate sub elements with no props', () => {
customComponentMap.foo = {
template: {
type: 'container',
children: [{ type: 'bar', component: true, attr: { x: 10, y: 20 }}]
}
}
customComponentMap.bar = {
data: () => {
return { x: 1, y: 2 }
},
template: {
type: 'container',
children: [
{ type: 'aaa', attr: { a: function () { return this.x } }},
{ type: 'bbb', attr: { b: function () { return this.y } }}
]
}
}
const app = { doc, customComponentMap, differ }
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
expect(vm._app).equal(app)
const el = doc.body
expect(el.type).eql('container')
expect(el.children).is.an.array
expect(el.children.length).eql(1)
const sub = el.children[0]
const aaa = sub.children[0]
expect(aaa.type).eql('aaa')
expect(aaa.attr).eql({ a: 10 })
const bbb = sub.children[1]
expect(bbb.type).eql('bbb')
expect(bbb.attr).eql({ b: 20 })
})
it('generate sub elements with array props', () => {
customComponentMap.foo = {
template: {
type: 'container',
children: [{ type: 'bar', component: true, attr: { x: 10, y: 20 }}]
}
}
customComponentMap.bar = {
props: ['x'],
data: () => {
return { x: 1, y: 2 }
},
template: {
type: 'container',
children: [
{ type: 'aaa', attr: { a: function () { return this.x } }},
{ type: 'bbb', attr: { b: function () { return this.y } }}
]
}
}
const app = { doc, customComponentMap, differ }
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
expect(vm._app).equal(app)
const el = doc.body
expect(el.type).eql('container')
expect(el.children).is.an.array
expect(el.children.length).eql(1)
const sub = el.children[0]
const aaa = sub.children[0]
expect(aaa.type).eql('aaa')
expect(aaa.attr).eql({ a: 10 })
const bbb = sub.children[1]
expect(bbb.type).eql('bbb')
expect(bbb.attr).eql({ b: 2 })
})
it('generate sub elements with props', () => {
customComponentMap.foo = {
template: {
type: 'container',
children: [{ type: 'bar', component: true, attr: { x: 10, y: 20 }}]
}
}
customComponentMap.bar = {
props: { x: Number },
data: () => {
return { x: 1, y: 2 }
},
template: {
type: 'container',
children: [
{ type: 'aaa', attr: { a: function () { return this.x } }},
{ type: 'bbb', attr: { b: function () { return this.y } }}
]
}
}
const app = { doc, customComponentMap, differ }
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
expect(vm._app).equal(app)
const el = doc.body
expect(el.type).eql('container')
expect(el.children).is.an.array
expect(el.children.length).eql(1)
const sub = el.children[0]
const aaa = sub.children[0]
expect(aaa.type).eql('aaa')
expect(aaa.attr).eql({ a: 10 })
const bbb = sub.children[1]
expect(bbb.type).eql('bbb')
expect(bbb.attr).eql({ b: 2 })
})
it('generate sub elements with data', () => {
customComponentMap.foo = {
data: () => {
return { a: 10, b: 20 }
},
template: {
type: 'container',
children: [{ type: 'bar', component: true, attr: {
x: function () { return this.a },
y: function () { return this.b }
}}]
}
}
customComponentMap.bar = {
props: { x: Number },
data: () => {
return { x: 1, y: 2 }
},
template: {
type: 'container',
children: [
{ type: 'aaa', attr: { a: function () { return this.x } }},
{ type: 'bbb', attr: { b: function () { return this.y } }}
]
}
}
const app = { doc, customComponentMap, differ }
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
expect(vm._app).equal(app)
const el = doc.body
expect(el.type).eql('container')
expect(el.children).is.an.array
expect(el.children.length).eql(1)
const sub = el.children[0]
const aaa = sub.children[0]
expect(aaa.type).eql('aaa')
expect(aaa.attr).eql({ a: 10 })
const bbb = sub.children[1]
expect(bbb.type).eql('bbb')
expect(bbb.attr).eql({ b: 2 })
vm.a = 100
vm.b = 200
differ.flush()
expect(el).equal(doc.body)
expect(sub).equal(el.children[0])
expect(aaa).equal(sub.children[0])
expect(aaa.attr).eql({ a: 100 })
expect(bbb).equal(sub.children[1])
expect(bbb.attr).eql({ b: 2 })
})
it('generate sub elements with shown data', () => {
customComponentMap.foo = {
data: () => {
return { a: 10, b: 20 }
},
template: {
type: 'container',
children: [{ type: 'bar', component: true, attr: {
x: function () { return this.a },
y: function () { return this.b }
}, shown: function () { return this.a < 15 } }]
}
}
customComponentMap.bar = {
props: { x: Number },
data: () => {
return { x: 1, y: 2 }
},
template: {
type: 'container',
children: [
{ type: 'aaa', attr: { a: function () { return this.x } }},
{ type: 'bbb', attr: { b: function () { return this.y } }}
]
}
}
const app = { doc, customComponentMap, differ }
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
expect(vm._app).equal(app)
const el = doc.body
expect(el.type).eql('container')
expect(el.children).is.an.array
expect(el.children.length).eql(3)
const sub = el.children[1]
const aaa = sub.children[0]
expect(aaa.type).eql('aaa')
expect(aaa.attr).eql({ a: 10 })
const bbb = sub.children[1]
expect(bbb.type).eql('bbb')
expect(bbb.attr).eql({ b: 2 })
vm.a = 20
differ.flush()
expect(el).equal(doc.body)
expect(el.children).is.an.array
expect(el.children.length).eql(2)
})
it('generate sub elements with repeat data', () => {
customComponentMap.foo = {
data: () => {
return { list: [{ uid: 1, a: 1 }, { uid: 2, a: 2 }, { uid: 3, a: 3 }] }
},
template: {
type: 'container',
children: [{ type: 'bar', component: true, attr: {
x: function () { return this.a },
y: function () { return this.b }
}, repeat: function () { return this.list } }]
}
}
customComponentMap.bar = {
props: { x: Number },
data: () => {
return { x: 1, y: 2 }
},
template: {
type: 'container',
children: [
{ type: 'aaa', attr: { a: function () { return this.x } }},
{ type: 'bbb', attr: { b: function () { return this.y } }}
]
}
}
const app = { doc, customComponentMap, differ }
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
expect(vm._app).equal(app)
const el = doc.body
expect(el.type).eql('container')
expect(el.children).is.an.array
expect(el.children.length).eql(5)
const sub1 = el.children[1]
const aaa1 = sub1.children[0]
expect(aaa1.type).eql('aaa')
expect(aaa1.attr).eql({ a: 1 })
const bbb1 = sub1.children[1]
expect(bbb1.type).eql('bbb')
expect(bbb1.attr).eql({ b: 2 })
const sub2 = el.children[2]
const aaa2 = sub2.children[0]
expect(aaa2.type).eql('aaa')
expect(aaa2.attr).eql({ a: 2 })
const bbb2 = sub2.children[1]
expect(bbb2.type).eql('bbb')
expect(bbb2.attr).eql({ b: 2 })
const sub3 = el.children[3]
const aaa3 = sub3.children[0]
expect(aaa3.type).eql('aaa')
expect(aaa3.attr).eql({ a: 3 })
const bbb3 = sub3.children[1]
expect(bbb3.type).eql('bbb')
expect(bbb3.attr).eql({ b: 2 })
})
it('generate sub elements with content', () => {
customComponentMap.foo = {
template: {
type: 'container',
children: [{ type: 'bar', component: true, children: [
{ type: 'a' }, { type: 'b', attr: { bbb: function () { return this.x } }}
] }]
},
data: () => {
return {
x: 1, y: 2
}
}
}
customComponentMap.bar = {
replace: true,
template: {
type: 'container',
children: [{ type: 'aaa' }, { type: 'content' }, { type: 'bbb' }]
}
}
const app = { doc, customComponentMap, differ }
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
const el = doc.body
expect(el.type).eql('container')
// [comment, aaa, comment, a, b, comment, bbb, comment]
expect(el.children.length).eql(8)
expect(el.children[0].type).eql('comment')
expect(el.children[2].type).eql('comment')
expect(el.children[5].type).eql('comment')
expect(el.children[7].type).eql('comment')
expect(el.pureChildren.length).eql(4)
expect(el.pureChildren[0].type).eql('aaa')
expect(el.pureChildren[1].type).eql('a')
expect(el.pureChildren[2].type).eql('b')
expect(el.pureChildren[2].attr).eql({ bbb: 1 })
expect(el.pureChildren[3].type).eql('bbb')
vm.x = 10
differ.flush()
expect(el.pureChildren[2].attr).eql({ bbb: 10 })
})
it('generate sub elements with dynamic types', (done) => {
customComponentMap.foo = {
data: {
x: 'bar',
y: 'hello'
},
template: {
type: 'div',
children: [{
type: function () { return this.x },
attr: { value: function () { return this.y } }
}]
}
}
customComponentMap.bar = {
template: {
type: 'text',
attr: { value: 'bar' }
}
}
customComponentMap.baz = {
data: function () {
return {
value: ''
}
},
template: {
type: 'text',
attr: { value: function () { return this.value + ' baz' } }
}
}
const app = { doc, customComponentMap, differ }
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
expect(doc.body.pureChildren[0].type).eql('text')
expect(doc.body.pureChildren[0].attr).eql({ value: 'bar' })
vm.x = 'baz'
expect(doc.body.pureChildren[0].type).eql('text')
expect(doc.body.pureChildren[0].attr).eql({ value: 'hello baz' })
vm.y = 'bye'
setTimeout(() => {
expect(doc.body.pureChildren[0].type).eql('text')
expect(doc.body.pureChildren[0].attr).eql({ value: 'bye baz' })
vm.x = 'text'
expect(doc.body.pureChildren[0].type).eql('text')
expect(doc.body.pureChildren[0].attr).eql({ value: 'bye' })
done()
})
})
it('generate sub elements with repeat dynamic types', (done) => {
customComponentMap.foo = {
data: {
list: [
{ uid: 1, type: 'bar' },
{ uid: 2, type: 'baz' },
{ uid: 3, type: 'bar' },
{ uid: 4, type: 'baz' }
]
},
template: {
type: 'div',
children: [{
type: function () { return this.v.type },
repeat: {
expression: function () { return this.list },
trackBy: 'uid',
value: 'v'
}
}]
}
}
customComponentMap.bar = {
template: {
type: 'text',
attr: { value: 'bar' }
}
}
customComponentMap.baz = {
template: {
type: 'text',
attr: { value: 'baz' }
}
}
const app = { doc, customComponentMap, differ }
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
expect(doc.body.pureChildren.length).eql(4)
expect(doc.body.pureChildren.map(el => el.attr.value)).eql(['bar', 'baz', 'bar', 'baz'])
vm.list.splice(2, 0, { uid: 5, type: 'baz' })
setTimeout(() => {
expect(doc.body.pureChildren.length).eql(5)
expect(doc.body.pureChildren.map(el => el.attr.value)).eql(['bar', 'baz', 'baz', 'bar', 'baz'])
done()
})
})
})
describe('generate dom actions', () => {
let doc, app, spy, customComponentMap, differ
beforeEach(() => {
spy = sinon.spy()
doc = new Document('foo', '', function (actions) {
actions.forEach((action) => {
spy.apply(null, ['bar', action.method].concat(action.args))
})
})
differ = new Differ('foo')
customComponentMap = {}
app = { doc, customComponentMap, differ }
})
afterEach(() => {
customComponentMap = {}
doc.destroy()
app = doc = spy = null
})
it('received create body and add element actions', () => {
const handler = sinon.spy()
customComponentMap.foo = {
template: {
type: 'container',
attr: {
a: 1,
b: 2
},
style: {
c: 3,
d: 4
},
classList: ['classA'],
events: { click: 'handleClick' }
},
style: {
classA: { d: 5, e: 6 }
},
methods: {
handleClick: handler
}
}
new Vm('foo', customComponentMap.foo, { _app: app })
const el = {
ref: '_root',
type: 'container',
attr: { a: 1, b: 2 }, style: { c: 3, d: 4, e: 6 },
event: ['click']
}
expect(spy.args.length).eql(1)
expect(spy.args[0]).eql(['bar', 'createBody', el])
expect(doc.body.event.click).is.a.function
expect(handler.args.length).eql(0)
doc.body.fireEvent('click')
expect(handler.args.length).eql(0)
})
it('received actions for a template with if & repeat', () => {
customComponentMap.foo = {
template: {
type: 'container',
children: [
{ type: 'prev' },
{
shown: function () { return this.x % 2 === 0 },
repeat: function () { return this.list },
trackBy: 'uid',
type: 'image', attr: { src: function () { return this.x } }
},
{ type: 'next' }
]
},
data: {
x: '<some image url>',
list: [
{ uid: 1, x: 1 }, { uid: 2, x: 2 }, { uid: 3 }
]
}
}
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
const pureChildren = doc.body.pureChildren
const el = { ref: '_root', type: 'container', attr: {}, style: {}}
const prev = {
ref: pureChildren[0].ref,
type: 'prev', attr: {}, style: {}
}
const img = {
ref: pureChildren[1].ref,
type: 'image', attr: { src: 2 }, style: {}
}
const next = {
ref: pureChildren[2].ref,
type: 'next', attr: {}, style: {}
}
expect(spy.args.length).eql(4)
expect(spy.args[0]).eql(['bar', 'createBody', el])
expect(spy.args[1]).eql(['bar', 'addElement', '_root', prev, -1])
expect(spy.args[2]).eql(['bar', 'addElement', '_root', img, 1])
expect(spy.args[3]).eql(['bar', 'addElement', '_root', next, -1])
vm.list[1].x = 3
differ.flush()
// [1, 3, undefined]
expect(spy.args.length).eql(5)
expect(spy.args[4]).eql(['bar', 'removeElement', img.ref])
vm.list[1].x = 12
differ.flush()
// [1, !12, undefined]
expect(spy.args.length).eql(6)
img.ref = pureChildren[1].ref
img.attr.src = 12
expect(spy.args[5]).eql(['bar', 'addElement', '_root', img, 1])
vm.x = 'other string value'
differ.flush()
expect(spy.args.length).eql(6)
vm.list.push({ uid: 4, x: 4 })
vm.list.push({ uid: 5 }, { uid: 6, x: 6 })
differ.flush()
// [1, !12, undefined, !4, undefined, !6]
const img2 = {
ref: pureChildren[2].ref,
type: 'image', attr: { src: 4 }, style: {}
}
const img3 = {
ref: pureChildren[3].ref,
type: 'image', attr: { src: 6 }, style: {}
}
expect(spy.args.length).eql(8)
expect(spy.args[6]).eql(['bar', 'addElement', '_root', img2, 2])
expect(spy.args[7]).eql(['bar', 'addElement', '_root', img3, 3])
const temp1 = vm.list[1] // 12
const temp2 = vm.list[5] // 6
// vm.list.splice(0, 6, temp2, {uid: 7, x: 7}, temp1)
vm.list = []
vm.list.push(temp2, { uid: 7, x: 7 }, temp1)
differ.flush()
// [!6, 7, !12]
expect(spy.args.length).eql(10)
expect(spy.args[8]).eql(['bar', 'removeElement', img2.ref])
expect(spy.args[9]).eql(['bar', 'moveElement', img3.ref, '_root', 1])
})
it('received actions for element updates', () => {
customComponentMap.foo = {
template: {
type: 'container', attr: { a: 1, b: 2 }, style: { c: 3, d: 4 },
children: [
{ type: 'image', attr: { src: function () { return this.x } }},
{ type: 'text', attr: { value: function () { return this.y } }}
]
},
data: {
x: '<some image url>', y: '<some text content>'
}
}
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
const pureChildren = doc.body.pureChildren
const length = spy.args.length
vm.x = '<some image url>'
differ.flush()
expect(spy.args.length - length).eql(0)
vm.x = 'other string value'
differ.flush()
const change = [
'bar', 'updateAttrs',
pureChildren[0].ref,
{ src: 'other string value' }
]
expect(spy.args.length - length).eql(1)
expect(spy.args[length]).eql(change)
})
it('received no action when no virtual dom different', () => {
customComponentMap.foo = {
template: {
type: 'container', children: [
{
type: 'text',
shown: function () { return this.name.length > 3 },
attr: {
value: function () { return this.name.toUpperCase() }
}
}
]
},
data: {
name: 'Mike'
}
}
const vm = new Vm('foo', customComponentMap.foo, { _app: app })
expect(doc.body.pureChildren.length).eql(1)
const text = doc.body.pureChildren[0]
expect(text.attr.value).eql('MIKE')
const initCalls = spy.args.length
vm.name = 'MiKe'
differ.flush()
expect(spy.args.length).eql(initCalls)
text.setAttr('value', 'MIKE')
differ.flush()
expect(spy.args.length).eql(initCalls)
text.setAttr('value', 'STEVE')
differ.flush()
expect(spy.args.length).eql(initCalls + 1)
expect(spy.args[initCalls]).eql([
'bar', 'updateAttrs', text.ref, { value: 'STEVE' }])
vm.name = 'Steve'
differ.flush()
expect(spy.args.length).eql(initCalls + 1)
})
it('received actions for components', () => {
customComponentMap.foo = {
template: {
type: 'container',
children: [{ type: 'bar', component: true }]
}
}
customComponentMap.bar = {
template: {
type: 'container',
children: [{ type: 'aaa' }, { type: 'bbb' }]
}
}
new Vm('foo', customComponentMap.foo, { _app: app })
const pureChildren = doc.body.pureChildren
const first = pureChildren[0]
const second = first.pureChildren[0]
const third = first.pureChildren[1]
expect(spy.args.length).eql(4)
let el = { ref: '_root', type: 'container', attr: {}, style: {}}
expect(spy.args[0]).eql(['bar', 'createBody', el])
el = { ref: first.ref, type: 'container', attr: {}, style: {}}
expect(spy.args[1]).eql(['bar', 'addElement', '_root', el, -1])
el = { ref: second.ref, type: 'aaa', attr: {}, style: {}}
expect(spy.args[2]).eql(['bar', 'addElement', first.ref, el, -1])
el = { ref: third.ref, type: 'bbb', attr: {}, style: {}}
expect(spy.args[3]).eql(['bar', 'addElement', first.ref, el, -1])
})
it('received actions for complicated components', () => {
customComponentMap.foo = {
data: () => {
return { list: [{ uid: 1, a: 1 }, { uid: 2, a: 2 }, { uid: 3, a: 3 }] }
},
template: {
type: 'container',
children: [{ type: 'bar', component: true, attr: {
x: function () { return this.a },
y: function () { return this.b }
}, repeat: function () { return this.list } }]
}
}
customComponentMap.bar = {
props: { x: Number },
data: () => {
return { x: 1, y: 2 }
},
template: {
type: 'container',
children: [
{ type: 'aaa', attr: { a: function () { return this.x } }},
{ type: 'bbb', attr: { b: function () { return this.y } }}
]
}
}
new Vm('foo', customComponentMap.foo, { _app: app })
const pureChildren = doc.body.pureChildren
const first = pureChildren[0]
const second = pureChildren[1]
const third = pureChildren[2]
/* eslint-disable indent */
// expect(spy.args[0]).eql([ 'bar', 'createBody', 'container' ])
expect(spy.args[0]).eql(['bar', 'createBody', { ref: '_root', type: 'container', attr: {}, style: {}}])
expect(spy.args[1]).eql(['bar', 'addElement', '_root', { ref: first.ref, type: 'container', attr: {}, style: {}}, 0])
expect(spy.args[2]).eql(['bar', 'addElement', first.ref, { ref: first.pureChildren[0].ref, type: 'aaa', attr: { a: 1 }, style: {}}, -1])
expect(spy.args[3]).eql(['bar', 'addElement', first.ref, { ref: first.pureChildren[1].ref, type: 'bbb', attr: { b: 2 }, style: {}}, -1])
expect(spy.args[4]).eql(['bar', 'addElement', '_root', { ref: second.ref, type: 'container', attr: {}, style: {}}, 1])
expect(spy.args[5]).eql(['bar', 'addElement', second.ref, { ref: second.pureChildren[0].ref, type: 'aaa', attr: { a: 2 }, style: {}}, -1])
expect(spy.args[6]).eql(['bar', 'addElement', second.ref, { ref: second.pureChildren[1].ref, type: 'bbb', attr: { b: 2 }, style: {}}, -1])
expect(spy.args[7]).eql(['bar', 'addElement', '_root', { ref: third.ref, type: 'container', attr: {}, style: {}}, 2])
expect(spy.args[8]).eql(['bar', 'addElement', third.ref, { ref: third.pureChildren[0].ref, type: 'aaa', attr: { a: 3 }, style: {}}, -1])
expect(spy.args[9]).eql(['bar', 'addElement', third.ref, { ref: third.pureChildren[1].ref, type: 'bbb', attr: { b: 2 }, style: {}}, -1])
/* eslint-enable indent */
})
it('received actions for add a tree element', () => {
customComponentMap.foo = {
template: {
type: 'r',
children: [
{ type: 'a' }, { type: 'b', children: [
{ type: 'd' }, { type: 'e', append: 'tree', children: [
{ type: 'g' }, { type: 'h' }, { type: 'i' }
] }, { type: 'f' }
] }, { type: 'c' }
]
}
}
new Vm('foo', customComponentMap.foo, { _app: app })
const pureChildren = doc.body.pureChildren
expect(spy.args.length).eql(7)
// body, r, r.a, r.b, r.b.d, r.b.e(tree), r.b.f, r.c
expect(spy.args[0][2].ref).eql('_root')
expect(spy.args[0][2].type).eql('r')
expect(spy.args[1][3].ref).eql(pureChildren[0].ref)
expect(spy.args[1][3].type).eql('a')
expect(spy.args[1][2]).eql('_root')
expect(spy.args[1][4]).eql(-1)
expect(spy.args[2][3].ref).eql(pureChildren[1].ref)
expect(spy.args[2][3].type).eql('b')
expect(spy.args[2][2]).eql('_root')
expect(spy.args[2][4]).eql(-1)
expect(spy.args[3][3].ref).eql(pureChildren[1].pureChildren[0].ref)
expect(spy.args[3][3].type).eql('d')
expect(spy.args[3][2]).eql(pureChildren[1].ref)
expect(spy.args[3][4]).eql(-1)
const tree = pureChildren[1].pureChildren[1]
expect(spy.args[4][3].ref).eql(tree.ref)
expect(spy.args[4][3].type).eql('e')
expect(spy.args[4][2]).eql(pureChildren[1].ref)
expect(spy.args[4][4]).eql(-1)
expect(spy.args[4][3].children).eql([
{ ref: tree.pureChildren[0].ref, type: 'g', attr: {}, style: {}},
{ ref: tree.pureChildren[1].ref, type: 'h', attr: {}, style: {}},
{ ref: tree.pureChildren[2].ref, type: 'i', attr: {}, style: {}}])
expect(spy.args[5][3].ref).eql(pureChildren[1].pureChildren[2].ref)
expect(spy.args[5][3].type).eql('f')
expect(spy.args[5][2]).eql(pureChildren[1].ref)
expect(spy.args[5][4]).eql(-1)
expect(spy.args[6][3].ref).eql(pureChildren[2].ref)
expect(spy.args[6][3].type).eql('c')
expect(spy.args[6][2]).eql('_root')
expect(spy.args[6][4]).eql(-1)
})
})