refactor: adjust createApp related API signatures
BREAKING CHANGE: `createApp` API has been adjusted.
- `createApp()` now accepts the root component, and optionally a props
object to pass to the root component.
- `app.mount()` now accepts a single argument (the root container)
- `app.unmount()` no longer requires arguments.
New behavior looks like the following:
``` js
const app = createApp(RootComponent)
app.mount('#app')
app.unmount()
```
This commit is contained in:
@@ -30,18 +30,18 @@ describe('api: createApp', () => {
|
||||
}
|
||||
|
||||
const root1 = nodeOps.createElement('div')
|
||||
createApp().mount(Comp, root1)
|
||||
createApp(Comp).mount(root1)
|
||||
expect(serializeInner(root1)).toBe(`0`)
|
||||
|
||||
// mount with props
|
||||
const root2 = nodeOps.createElement('div')
|
||||
const app2 = createApp()
|
||||
app2.mount(Comp, root2, { count: 1 })
|
||||
const app2 = createApp(Comp, { count: 1 })
|
||||
app2.mount(root2)
|
||||
expect(serializeInner(root2)).toBe(`1`)
|
||||
|
||||
// remount warning
|
||||
const root3 = nodeOps.createElement('div')
|
||||
app2.mount(Comp, root3)
|
||||
app2.mount(root3)
|
||||
expect(serializeInner(root3)).toBe(``)
|
||||
expect(`already been mounted`).toHaveBeenWarned()
|
||||
})
|
||||
@@ -59,18 +59,14 @@ describe('api: createApp', () => {
|
||||
}
|
||||
|
||||
const root = nodeOps.createElement('div')
|
||||
const app = createApp()
|
||||
app.mount(Comp, root)
|
||||
const app = createApp(Comp)
|
||||
app.mount(root)
|
||||
|
||||
app.unmount(root)
|
||||
expect(serializeInner(root)).toBe(``)
|
||||
})
|
||||
|
||||
test('provide', () => {
|
||||
const app = createApp()
|
||||
app.provide('foo', 1)
|
||||
app.provide('bar', 2)
|
||||
|
||||
const Root = {
|
||||
setup() {
|
||||
// test override
|
||||
@@ -87,25 +83,16 @@ describe('api: createApp', () => {
|
||||
}
|
||||
}
|
||||
|
||||
const app = createApp(Root)
|
||||
app.provide('foo', 1)
|
||||
app.provide('bar', 2)
|
||||
|
||||
const root = nodeOps.createElement('div')
|
||||
app.mount(Root, root)
|
||||
app.mount(root)
|
||||
expect(serializeInner(root)).toBe(`3,2`)
|
||||
})
|
||||
|
||||
test('component', () => {
|
||||
const app = createApp()
|
||||
|
||||
const FooBar = () => 'foobar!'
|
||||
app.component('FooBar', FooBar)
|
||||
expect(app.component('FooBar')).toBe(FooBar)
|
||||
|
||||
app.component('BarBaz', () => 'barbaz!')
|
||||
|
||||
app.component('BarBaz', () => 'barbaz!')
|
||||
expect(
|
||||
'Component "BarBaz" has already been registered in target app.'
|
||||
).toHaveBeenWarnedTimes(1)
|
||||
|
||||
const Root = {
|
||||
// local override
|
||||
components: {
|
||||
@@ -122,33 +109,29 @@ describe('api: createApp', () => {
|
||||
}
|
||||
}
|
||||
|
||||
const app = createApp(Root)
|
||||
|
||||
const FooBar = () => 'foobar!'
|
||||
app.component('FooBar', FooBar)
|
||||
expect(app.component('FooBar')).toBe(FooBar)
|
||||
|
||||
app.component('BarBaz', () => 'barbaz!')
|
||||
|
||||
app.component('BarBaz', () => 'barbaz!')
|
||||
expect(
|
||||
'Component "BarBaz" has already been registered in target app.'
|
||||
).toHaveBeenWarnedTimes(1)
|
||||
|
||||
const root = nodeOps.createElement('div')
|
||||
app.mount(Root, root)
|
||||
app.mount(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()
|
||||
|
||||
const FooBar = { mounted: spy1 }
|
||||
app.directive('FooBar', FooBar)
|
||||
expect(app.directive('FooBar')).toBe(FooBar)
|
||||
|
||||
app.directive('BarBaz', {
|
||||
mounted: spy2
|
||||
})
|
||||
|
||||
app.directive('BarBaz', {
|
||||
mounted: spy2
|
||||
})
|
||||
expect(
|
||||
'Directive "BarBaz" has already been registered in target app.'
|
||||
).toHaveBeenWarnedTimes(1)
|
||||
|
||||
const Root = {
|
||||
// local override
|
||||
directives: {
|
||||
@@ -165,8 +148,25 @@ describe('api: createApp', () => {
|
||||
}
|
||||
}
|
||||
|
||||
const app = createApp(Root)
|
||||
|
||||
const FooBar = { mounted: spy1 }
|
||||
app.directive('FooBar', FooBar)
|
||||
expect(app.directive('FooBar')).toBe(FooBar)
|
||||
|
||||
app.directive('BarBaz', {
|
||||
mounted: spy2
|
||||
})
|
||||
|
||||
app.directive('BarBaz', {
|
||||
mounted: spy2
|
||||
})
|
||||
expect(
|
||||
'Directive "BarBaz" has already been registered in target app.'
|
||||
).toHaveBeenWarnedTimes(1)
|
||||
|
||||
const root = nodeOps.createElement('div')
|
||||
app.mount(Root, root)
|
||||
app.mount(root)
|
||||
expect(spy1).toHaveBeenCalled()
|
||||
expect(spy2).not.toHaveBeenCalled()
|
||||
expect(spy3).toHaveBeenCalled()
|
||||
@@ -232,7 +232,7 @@ describe('api: createApp', () => {
|
||||
}
|
||||
}
|
||||
|
||||
const app = createApp()
|
||||
const app = createApp(Comp)
|
||||
app.mixin(mixinA)
|
||||
app.mixin(mixinB)
|
||||
|
||||
@@ -246,7 +246,7 @@ describe('api: createApp', () => {
|
||||
).toHaveBeenWarnedTimes(1)
|
||||
|
||||
const root = nodeOps.createElement('div')
|
||||
app.mount(Comp, root)
|
||||
app.mount(root)
|
||||
|
||||
expect(serializeInner(root)).toBe(`123`)
|
||||
expect(calls).toEqual([
|
||||
@@ -272,11 +272,6 @@ describe('api: createApp', () => {
|
||||
}
|
||||
const PluginD: any = undefined
|
||||
|
||||
const app = createApp()
|
||||
app.use(PluginA)
|
||||
app.use(PluginB, 1, 1)
|
||||
app.use(PluginC)
|
||||
|
||||
const Root = {
|
||||
setup() {
|
||||
const foo = inject('foo')
|
||||
@@ -284,8 +279,14 @@ describe('api: createApp', () => {
|
||||
return () => `${foo},${bar}`
|
||||
}
|
||||
}
|
||||
|
||||
const app = createApp(Root)
|
||||
app.use(PluginA)
|
||||
app.use(PluginB, 1, 1)
|
||||
app.use(PluginC)
|
||||
|
||||
const root = nodeOps.createElement('div')
|
||||
app.mount(Root, root)
|
||||
app.mount(root)
|
||||
expect(serializeInner(root)).toBe(`1,2`)
|
||||
|
||||
app.use(PluginA)
|
||||
@@ -301,18 +302,14 @@ describe('api: createApp', () => {
|
||||
})
|
||||
|
||||
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 handler = 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() {
|
||||
@@ -326,21 +323,19 @@ describe('api: createApp', () => {
|
||||
}
|
||||
}
|
||||
|
||||
app.mount(Root, nodeOps.createElement('div'))
|
||||
const app = createApp(Root)
|
||||
app.config.errorHandler = handler
|
||||
app.mount(nodeOps.createElement('div'))
|
||||
expect(handler).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
test('config.warnHandler', () => {
|
||||
const app = createApp()
|
||||
let ctx: any
|
||||
|
||||
const handler = (app.config.warnHandler = jest.fn(
|
||||
(msg, instance, trace) => {
|
||||
expect(msg).toMatch(`Component is missing template or render function`)
|
||||
expect(instance).toBe(ctx.proxy)
|
||||
expect(trace).toMatch(`Hello`)
|
||||
}
|
||||
))
|
||||
const handler = jest.fn((msg, instance, trace) => {
|
||||
expect(msg).toMatch(`Component is missing template or render function`)
|
||||
expect(instance).toBe(ctx.proxy)
|
||||
expect(trace).toMatch(`Hello`)
|
||||
})
|
||||
|
||||
const Root = {
|
||||
name: 'Hello',
|
||||
@@ -349,7 +344,9 @@ describe('api: createApp', () => {
|
||||
}
|
||||
}
|
||||
|
||||
app.mount(Root, nodeOps.createElement('div'))
|
||||
const app = createApp(Root)
|
||||
app.config.warnHandler = handler
|
||||
app.mount(nodeOps.createElement('div'))
|
||||
expect(handler).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
@@ -357,104 +354,82 @@ describe('api: createApp', () => {
|
||||
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'))
|
||||
const app = createApp(Root)
|
||||
|
||||
Object.defineProperty(app.config, 'isNativeTag', {
|
||||
value: isNativeTag,
|
||||
writable: false
|
||||
})
|
||||
|
||||
app.mount(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'))
|
||||
const app = createApp(Root)
|
||||
Object.defineProperty(app.config, 'isNativeTag', {
|
||||
value: isNativeTag,
|
||||
writable: false
|
||||
})
|
||||
|
||||
app.mount(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'))
|
||||
const app = createApp(Root)
|
||||
Object.defineProperty(app.config, 'isNativeTag', {
|
||||
value: isNativeTag,
|
||||
writable: false
|
||||
})
|
||||
|
||||
app.mount(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()
|
||||
const app = createApp({
|
||||
render() {}
|
||||
})
|
||||
|
||||
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'))
|
||||
app.mount(nodeOps.createElement('div'))
|
||||
expect(
|
||||
`Do not use built-in or reserved HTML elements as component id: div`
|
||||
).toHaveBeenWarned()
|
||||
@@ -1,4 +1,4 @@
|
||||
import { createApp, getCurrentInstance, nodeOps } from '@vue/runtime-test'
|
||||
import { h, render, getCurrentInstance, nodeOps } from '@vue/runtime-test'
|
||||
import { mockWarn } from '@vue/shared'
|
||||
import { ComponentInternalInstance } from '../src/component'
|
||||
|
||||
@@ -6,7 +6,6 @@ describe('component: proxy', () => {
|
||||
mockWarn()
|
||||
|
||||
test('data', () => {
|
||||
const app = createApp()
|
||||
let instance: ComponentInternalInstance
|
||||
let instanceProxy: any
|
||||
const Comp = {
|
||||
@@ -23,14 +22,13 @@ describe('component: proxy', () => {
|
||||
return null
|
||||
}
|
||||
}
|
||||
app.mount(Comp, nodeOps.createElement('div'))
|
||||
render(h(Comp), nodeOps.createElement('div'))
|
||||
expect(instanceProxy.foo).toBe(1)
|
||||
instanceProxy.foo = 2
|
||||
expect(instance!.data.foo).toBe(2)
|
||||
})
|
||||
|
||||
test('renderContext', () => {
|
||||
const app = createApp()
|
||||
let instance: ComponentInternalInstance
|
||||
let instanceProxy: any
|
||||
const Comp = {
|
||||
@@ -47,14 +45,13 @@ describe('component: proxy', () => {
|
||||
return null
|
||||
}
|
||||
}
|
||||
app.mount(Comp, nodeOps.createElement('div'))
|
||||
render(h(Comp), nodeOps.createElement('div'))
|
||||
expect(instanceProxy.foo).toBe(1)
|
||||
instanceProxy.foo = 2
|
||||
expect(instance!.renderContext.foo).toBe(2)
|
||||
})
|
||||
|
||||
test('propsProxy', () => {
|
||||
const app = createApp()
|
||||
let instance: ComponentInternalInstance
|
||||
let instanceProxy: any
|
||||
const Comp = {
|
||||
@@ -72,7 +69,7 @@ describe('component: proxy', () => {
|
||||
instanceProxy = this
|
||||
}
|
||||
}
|
||||
app.mount(Comp, nodeOps.createElement('div'))
|
||||
render(h(Comp), nodeOps.createElement('div'))
|
||||
expect(instanceProxy.foo).toBe(1)
|
||||
expect(instance!.propsProxy!.foo).toBe(1)
|
||||
expect(() => (instanceProxy.foo = 2)).toThrow(TypeError)
|
||||
@@ -80,7 +77,6 @@ describe('component: proxy', () => {
|
||||
})
|
||||
|
||||
test('public properties', () => {
|
||||
const app = createApp()
|
||||
let instance: ComponentInternalInstance
|
||||
let instanceProxy: any
|
||||
const Comp = {
|
||||
@@ -92,7 +88,7 @@ describe('component: proxy', () => {
|
||||
instanceProxy = this
|
||||
}
|
||||
}
|
||||
app.mount(Comp, nodeOps.createElement('div'))
|
||||
render(h(Comp), nodeOps.createElement('div'))
|
||||
expect(instanceProxy.$data).toBe(instance!.data)
|
||||
expect(instanceProxy.$props).toBe(instance!.propsProxy)
|
||||
expect(instanceProxy.$attrs).toBe(instance!.attrs)
|
||||
@@ -108,7 +104,6 @@ describe('component: proxy', () => {
|
||||
})
|
||||
|
||||
test('sink', async () => {
|
||||
const app = createApp()
|
||||
let instance: ComponentInternalInstance
|
||||
let instanceProxy: any
|
||||
const Comp = {
|
||||
@@ -120,14 +115,13 @@ describe('component: proxy', () => {
|
||||
instanceProxy = this
|
||||
}
|
||||
}
|
||||
app.mount(Comp, nodeOps.createElement('div'))
|
||||
render(h(Comp), nodeOps.createElement('div'))
|
||||
instanceProxy.foo = 1
|
||||
expect(instanceProxy.foo).toBe(1)
|
||||
expect(instance!.sink.foo).toBe(1)
|
||||
})
|
||||
|
||||
test('has check', () => {
|
||||
const app = createApp()
|
||||
let instanceProxy: any
|
||||
const Comp = {
|
||||
render() {},
|
||||
@@ -148,7 +142,7 @@ describe('component: proxy', () => {
|
||||
instanceProxy = this
|
||||
}
|
||||
}
|
||||
app.mount(Comp, nodeOps.createElement('div'), { msg: 'hello' })
|
||||
render(h(Comp, { msg: 'hello' }), nodeOps.createElement('div'))
|
||||
|
||||
// props
|
||||
expect('msg' in instanceProxy).toBe(true)
|
||||
|
||||
@@ -12,7 +12,6 @@ import { mockWarn } from '@vue/shared'
|
||||
|
||||
describe('resolveAssets', () => {
|
||||
test('should work', () => {
|
||||
const app = createApp()
|
||||
const FooBar = () => null
|
||||
const BarBaz = { mounted: () => null }
|
||||
|
||||
@@ -49,8 +48,9 @@ describe('resolveAssets', () => {
|
||||
}
|
||||
}
|
||||
|
||||
const app = createApp(Root)
|
||||
const root = nodeOps.createElement('div')
|
||||
app.mount(Root, root)
|
||||
app.mount(root)
|
||||
expect(component1!).toBe(FooBar)
|
||||
expect(component2!).toBe(FooBar)
|
||||
expect(component3!).toBe(FooBar)
|
||||
@@ -78,7 +78,6 @@ describe('resolveAssets', () => {
|
||||
})
|
||||
|
||||
test('not exist', () => {
|
||||
const app = createApp()
|
||||
const Root = {
|
||||
setup() {
|
||||
resolveComponent('foo')
|
||||
@@ -87,14 +86,14 @@ describe('resolveAssets', () => {
|
||||
}
|
||||
}
|
||||
|
||||
const app = createApp(Root)
|
||||
const root = nodeOps.createElement('div')
|
||||
app.mount(Root, root)
|
||||
app.mount(root)
|
||||
expect('Failed to resolve component: foo').toHaveBeenWarned()
|
||||
expect('Failed to resolve directive: bar').toHaveBeenWarned()
|
||||
})
|
||||
|
||||
test('resolve dynamic component', () => {
|
||||
const app = createApp()
|
||||
const dynamicComponents = {
|
||||
foo: () => 'foo',
|
||||
bar: () => 'bar',
|
||||
@@ -112,8 +111,10 @@ describe('resolveAssets', () => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const app = createApp(Root)
|
||||
const root = nodeOps.createElement('div')
|
||||
app.mount(Root, root)
|
||||
app.mount(root)
|
||||
expect(foo).toBe(dynamicComponents.foo)
|
||||
expect(bar).toBe(dynamicComponents.bar)
|
||||
expect(baz).toBe(dynamicComponents.baz)
|
||||
|
||||
Reference in New Issue
Block a user