vue3-yuanma/packages/runtime-core/__tests__/apiApp.spec.ts

437 lines
9.6 KiB
TypeScript
Raw Normal View History

2019-09-04 06:11:04 +08:00
import {
createApp,
h,
nodeOps,
serializeInner,
mockWarn,
provide,
inject,
resolveComponent,
resolveDirective,
withDirectives,
2019-09-04 06:11:04 +08:00
Plugin,
2019-09-06 08:59:45 +08:00
ref,
getCurrentInstance
2019-09-04 06:11:04 +08:00
} from '@vue/runtime-test'
describe('api: createApp', () => {
mockWarn()
test('mount', () => {
const Comp = {
props: {
count: {
default: 0
}
},
setup(props: { count: number }) {
return () => props.count
2019-09-04 06:11:04 +08:00
}
}
const root1 = nodeOps.createElement('div')
createApp().mount(Comp, root1)
expect(serializeInner(root1)).toBe(`0`)
// mount with props
const root2 = nodeOps.createElement('div')
const app2 = createApp()
app2.mount(Comp, root2, { count: 1 })
expect(serializeInner(root2)).toBe(`1`)
// remount warning
const root3 = nodeOps.createElement('div')
app2.mount(Comp, root3)
expect(serializeInner(root3)).toBe(``)
expect(`already been mounted`).toHaveBeenWarned()
})
test('provide', () => {
const app = createApp()
app.provide('foo', 1)
app.provide('bar', 2)
const Root = {
setup() {
// test override
provide('foo', 3)
return () => h(Child)
}
}
const Child = {
setup() {
const foo = inject('foo')
const bar = inject('bar')
return () => `${foo},${bar}`
}
}
const root = nodeOps.createElement('div')
app.mount(Root, root)
expect(serializeInner(root)).toBe(`3,2`)
})
test('component', () => {
const app = createApp()
2019-09-04 06:30:52 +08:00
const FooBar = () => 'foobar!'
app.component('FooBar', FooBar)
expect(app.component('FooBar')).toBe(FooBar)
2019-09-04 06:11:04 +08:00
app.component('BarBaz', () => 'barbaz!')
2019-10-29 04:22:03 +08:00
app.component('BarBaz', () => 'barbaz!')
expect(
'Component "BarBaz" has already been registered in target app.'
).toHaveBeenWarnedTimes(1)
2019-09-04 06:11:04 +08:00
const Root = {
// local override
components: {
BarBaz: () => 'barbaz-local!'
},
setup() {
// resolve in setup
const FooBar = resolveComponent('foo-bar') as any
return () => {
// resolve in render
const BarBaz = resolveComponent('bar-baz') as any
return h('div', [h(FooBar), h(BarBaz)])
}
}
}
const root = nodeOps.createElement('div')
app.mount(Root, root)
expect(serializeInner(root)).toBe(`<div>foobar!barbaz-local!</div>`)
})
test('directive', () => {
const app = createApp()
const spy1 = jest.fn()
const spy2 = jest.fn()
const spy3 = jest.fn()
2019-09-04 06:30:52 +08:00
const FooBar = { mounted: spy1 }
app.directive('FooBar', FooBar)
expect(app.directive('FooBar')).toBe(FooBar)
2019-09-04 06:11:04 +08:00
app.directive('BarBaz', {
mounted: spy2
})
2019-10-29 04:22:03 +08:00
app.directive('BarBaz', {
mounted: spy2
})
expect(
'Directive "BarBaz" has already been registered in target app.'
).toHaveBeenWarnedTimes(1)
2019-09-04 06:11:04 +08:00
const Root = {
// local override
directives: {
BarBaz: { mounted: spy3 }
},
setup() {
// resolve in setup
const FooBar = resolveDirective('foo-bar')!
2019-09-04 06:11:04 +08:00
return () => {
// resolve in render
const BarBaz = resolveDirective('bar-baz')!
return withDirectives(h('div'), [[FooBar], [BarBaz]])
2019-09-04 06:11:04 +08:00
}
}
}
const root = nodeOps.createElement('div')
app.mount(Root, root)
expect(spy1).toHaveBeenCalled()
expect(spy2).not.toHaveBeenCalled()
expect(spy3).toHaveBeenCalled()
app.directive('bind', FooBar)
expect(
`Do not use built-in directive ids as custom directive id: bind`
).toHaveBeenWarned()
2019-09-04 06:11:04 +08:00
})
2019-09-06 08:59:45 +08:00
test('mixin', () => {
const calls: string[] = []
const mixinA = {
data() {
return {
a: 1
}
},
created(this: any) {
calls.push('mixinA created')
expect(this.a).toBe(1)
expect(this.b).toBe(2)
expect(this.c).toBe(3)
},
mounted() {
calls.push('mixinA mounted')
}
}
const mixinB = {
2019-10-29 04:22:03 +08:00
name: 'mixinB',
2019-09-06 08:59:45 +08:00
data() {
return {
b: 2
}
},
created(this: any) {
calls.push('mixinB created')
expect(this.a).toBe(1)
expect(this.b).toBe(2)
expect(this.c).toBe(3)
},
mounted() {
calls.push('mixinB mounted')
}
}
const Comp = {
data() {
return {
c: 3
}
},
created(this: any) {
calls.push('comp created')
expect(this.a).toBe(1)
expect(this.b).toBe(2)
expect(this.c).toBe(3)
},
mounted() {
calls.push('comp mounted')
},
render(this: any) {
return `${this.a}${this.b}${this.c}`
}
}
const app = createApp()
app.mixin(mixinA)
app.mixin(mixinB)
2019-10-29 04:22:03 +08:00
app.mixin(mixinA)
app.mixin(mixinB)
expect(
'Mixin has already been applied to target app'
).toHaveBeenWarnedTimes(2)
expect(
'Mixin has already been applied to target app: mixinB'
).toHaveBeenWarnedTimes(1)
2019-09-06 08:59:45 +08:00
const root = nodeOps.createElement('div')
app.mount(Comp, root)
expect(serializeInner(root)).toBe(`123`)
expect(calls).toEqual([
'mixinA created',
'mixinB created',
'comp created',
'mixinA mounted',
'mixinB mounted',
'comp mounted'
])
})
2019-09-04 06:11:04 +08:00
test('use', () => {
const PluginA: Plugin = app => app.provide('foo', 1)
const PluginB: Plugin = {
install: (app, arg1, arg2) => app.provide('bar', arg1 + arg2)
2019-09-04 06:11:04 +08:00
}
const PluginC: any = undefined
2019-09-04 06:11:04 +08:00
const app = createApp()
app.use(PluginA)
app.use(PluginB, 1, 1)
2019-09-04 06:11:04 +08:00
const Root = {
setup() {
const foo = inject('foo')
const bar = inject('bar')
return () => `${foo},${bar}`
}
}
const root = nodeOps.createElement('div')
app.mount(Root, root)
expect(serializeInner(root)).toBe(`1,2`)
app.use(PluginA)
expect(
`Plugin has already been applied to target app`
).toHaveBeenWarnedTimes(1)
app.use(PluginC)
expect(
`A plugin must either be a function or an object with an "install" ` +
`function.`
).toHaveBeenWarnedTimes(1)
2019-09-04 06:11:04 +08:00
})
test('config.errorHandler', () => {
const app = createApp()
const error = new Error()
const count = ref(0)
const handler = (app.config.errorHandler = jest.fn(
(err, instance, info) => {
expect(err).toBe(error)
expect((instance as any).count).toBe(count.value)
expect(info).toBe(`render function`)
}
))
const Root = {
setup() {
const count = ref(0)
return {
count
}
},
render() {
throw error
}
}
app.mount(Root, nodeOps.createElement('div'))
expect(handler).toHaveBeenCalled()
})
test('config.warnHandler', () => {
const app = createApp()
2019-09-06 08:59:45 +08:00
let ctx: any
2019-09-04 06:11:04 +08:00
const handler = (app.config.warnHandler = jest.fn(
2019-09-06 08:59:45 +08:00
(msg, instance, trace) => {
expect(msg).toMatch(`Component is missing template or render function`)
expect(instance).toBe(ctx.proxy)
2019-09-06 08:59:45 +08:00
expect(trace).toMatch(`Hello`)
}
2019-09-04 06:11:04 +08:00
))
const Root = {
2019-09-06 08:59:45 +08:00
name: 'Hello',
setup() {
ctx = getCurrentInstance()
}
2019-09-04 06:11:04 +08:00
}
app.mount(Root, nodeOps.createElement('div'))
2019-09-06 08:59:45 +08:00
expect(handler).toHaveBeenCalledTimes(1)
2019-09-04 06:11:04 +08:00
})
describe('config.isNativeTag', () => {
const isNativeTag = jest.fn(tag => tag === 'div')
test('Component.name', () => {
const app = createApp()
Object.defineProperty(app.config, 'isNativeTag', {
value: isNativeTag,
writable: false
})
const Root = {
name: 'div',
setup() {
return {
count: ref(0)
}
},
render() {
return null
}
}
app.mount(Root, nodeOps.createElement('div'))
expect(
`Do not use built-in or reserved HTML elements as component id: div`
).toHaveBeenWarned()
})
test('Component.components', () => {
const app = createApp()
Object.defineProperty(app.config, 'isNativeTag', {
value: isNativeTag,
writable: false
})
const Root = {
components: {
div: () => 'div'
},
setup() {
return {
count: ref(0)
}
},
render() {
return null
}
}
app.mount(Root, nodeOps.createElement('div'))
expect(
`Do not use built-in or reserved HTML elements as component id: div`
).toHaveBeenWarned()
})
test('Component.directives', () => {
const app = createApp()
Object.defineProperty(app.config, 'isNativeTag', {
value: isNativeTag,
writable: false
})
const Root = {
directives: {
bind: () => {}
},
setup() {
return {
count: ref(0)
}
},
render() {
return null
}
}
app.mount(Root, nodeOps.createElement('div'))
expect(
`Do not use built-in directive ids as custom directive id: bind`
).toHaveBeenWarned()
})
test('register using app.component', () => {
const app = createApp()
Object.defineProperty(app.config, 'isNativeTag', {
value: isNativeTag,
writable: false
})
const Root = {
setup() {
return {
count: ref(0)
}
},
render() {
return null
}
}
app.component('div', () => 'div')
app.mount(Root, nodeOps.createElement('div'))
expect(
`Do not use built-in or reserved HTML elements as component id: div`
).toHaveBeenWarned()
})
})
2019-09-04 06:11:04 +08:00
})