import Vue from 'vue'
import { createComponent } from 'core/vdom/create-component'
import { setCurrentRenderingInstance } from 'core/instance/render'
describe('create-component', () => {
let vm
beforeEach(() => {
vm = new Vue({
template: '<p>{{msg}}</p>',
data() {
return { msg: 'hello, my children' }
}
}).$mount()
return new Promise(r => Vue.nextTick(r))
})
it('create a component basically', () => {
const child = {
name: 'child',
props: ['msg'],
render() {}
}
const data = {
props: { msg: 'hello world' },
attrs: { id: 1 },
staticAttrs: { class: 'foo' },
on: { notify: 'onNotify' }
}
const vnode = createComponent(child, data, vm, vm)
expect(vnode.tag).toMatch(/vue-component-[0-9]+-child/)
expect(vnode.data.attrs).toEqual({ id: 1 })
expect(vnode.data.staticAttrs).toEqual({ class: 'foo' })
expect(vnode.componentOptions.propsData).toEqual({ msg: 'hello world' })
expect(vnode.componentOptions.listeners).toEqual({ notify: 'onNotify' })
expect(vnode.children).toBeUndefined()
expect(vnode.text).toBeUndefined()
expect(vnode.elm).toBeUndefined()
expect(vnode.ns).toBeUndefined()
expect(vnode.context).toEqual(vm)
})
it('create a component when resolved with async loading', done => {
let vnode = null
const data = {
props: {},
staticAttrs: { class: 'foo' }
}
vi.spyOn(vm, '$forceUpdate')
function async(resolve, reject) {
setTimeout(() => {
resolve({
name: 'child',
props: ['msg']
})
Vue.nextTick(loaded)
}, 0)
}
function go() {
setCurrentRenderingInstance(vm)
vnode = createComponent(async, data, vm, vm)
setCurrentRenderingInstance(null)
expect(vnode.isComment).toBe(true)
expect(vnode.asyncFactory).toBe(async)
expect(vnode.asyncFactory.owners.length).toEqual(1)
}
function loaded() {
setCurrentRenderingInstance(vm)
vnode = createComponent(async, data, vm, vm)
setCurrentRenderingInstance(null)
expect(vnode.tag).toMatch(/vue-component-[0-9]+-child/)
expect(vnode.data.staticAttrs).toEqual({ class: 'foo' })
expect(vnode.children).toBeUndefined()
expect(vnode.text).toBeUndefined()
expect(vnode.elm).toBeUndefined()
expect(vnode.ns).toBeUndefined()
expect(vnode.context).toEqual(vm)
expect(vnode.asyncFactory.owners.length).toEqual(0)
expect(vm.$forceUpdate).toHaveBeenCalled()
done()
}
go()
})
it('create a component when resolved with synchronous async loading', done => {
const data = {
props: {},
staticAttrs: { class: 'bar' }
}
vi.spyOn(vm, '$forceUpdate')
function async(resolve, reject) {
resolve({
name: 'child',
props: ['msg']
})
}
setCurrentRenderingInstance(vm)
const vnode = createComponent(async, data, vm, vm)
setCurrentRenderingInstance(null)
expect(vnode.asyncFactory).toBe(async)
expect(vnode.asyncFactory.owners.length).toEqual(0)
expect(vnode.tag).toMatch(/vue-component-[0-9]+-child/)
expect(vnode.data.staticAttrs).toEqual({ class: 'bar' })
expect(vnode.children).toBeUndefined()
expect(vnode.text).toBeUndefined()
expect(vnode.elm).toBeUndefined()
expect(vnode.ns).toBeUndefined()
expect(vnode.context).toEqual(vm)
expect(vm.$forceUpdate).not.toHaveBeenCalled()
done()
})
it('not create a component when rejected with async loading', done => {
let vnode = null
const data = {
props: { msg: 'hello world' },
attrs: { id: 1 }
}
const reason = 'failed!!'
function async(resolve, reject) {
setTimeout(() => {
reject(reason)
Vue.nextTick(failed)
}, 0)
}
function go() {
setCurrentRenderingInstance(vm)
vnode = createComponent(async, data, vm, vm)
setCurrentRenderingInstance(null)
expect(vnode.isComment).toBe(true)
}
function failed() {
setCurrentRenderingInstance(vm)
vnode = createComponent(async, data, vm, vm)
setCurrentRenderingInstance(null)
expect(vnode.isComment).toBe(true)
expect(
`Failed to resolve async component: ${async}\nReason: ${reason}`
).toHaveBeenWarned()
done()
}
go()
})
it('not create a component when specified with falsy', () => {
const vnode = createComponent(null, {}, vm, vm)
expect(vnode).toBeUndefined()
})
it('warn component definition type', () => {
const Ctor = 'child'
const vnode = createComponent(Ctor, {}, vm, vm)
expect(vnode).toBeUndefined()
expect(`Invalid Component definition: ${Ctor}`).toHaveBeenWarned()
})
})