mirror of https://github.com/vuejs/core.git
test(runtime-vapor): refactor duplicate compoent test code (#120)
Co-authored-by: 三咲智子 Kevin Deng <sxzz@sxzz.moe>
This commit is contained in:
parent
75c8ff5cb7
commit
a15f609044
|
@ -0,0 +1,53 @@
|
||||||
|
import { type Data, isFunction } from '@vue/shared'
|
||||||
|
import {
|
||||||
|
type ComponentInternalInstance,
|
||||||
|
type ObjectComponent,
|
||||||
|
type SetupFn,
|
||||||
|
render as _render,
|
||||||
|
defineComponent,
|
||||||
|
} from '../src'
|
||||||
|
|
||||||
|
export function makeRender<Component = ObjectComponent | SetupFn>(
|
||||||
|
initHost = () => {
|
||||||
|
const host = document.createElement('div')
|
||||||
|
host.setAttribute('id', 'host')
|
||||||
|
document.body.appendChild(host)
|
||||||
|
return host
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
let host: HTMLElement
|
||||||
|
beforeEach(() => {
|
||||||
|
host = initHost()
|
||||||
|
})
|
||||||
|
afterEach(() => {
|
||||||
|
host.remove()
|
||||||
|
})
|
||||||
|
|
||||||
|
const define = (comp: Component) => {
|
||||||
|
const component = defineComponent(
|
||||||
|
isFunction(comp)
|
||||||
|
? {
|
||||||
|
setup: comp,
|
||||||
|
}
|
||||||
|
: comp,
|
||||||
|
)
|
||||||
|
let instance: ComponentInternalInstance
|
||||||
|
const render = (
|
||||||
|
props: Data = {},
|
||||||
|
container: string | ParentNode = '#host',
|
||||||
|
) => {
|
||||||
|
instance = _render(component, props, container)
|
||||||
|
return res()
|
||||||
|
}
|
||||||
|
const res = () => ({
|
||||||
|
component,
|
||||||
|
host,
|
||||||
|
instance,
|
||||||
|
render,
|
||||||
|
})
|
||||||
|
|
||||||
|
return res()
|
||||||
|
}
|
||||||
|
|
||||||
|
return define
|
||||||
|
}
|
|
@ -1,32 +1,19 @@
|
||||||
import {
|
import {
|
||||||
children,
|
children,
|
||||||
ref,
|
ref,
|
||||||
render,
|
|
||||||
setText,
|
setText,
|
||||||
template,
|
template,
|
||||||
unmountComponent,
|
unmountComponent,
|
||||||
watchEffect,
|
watchEffect,
|
||||||
} from '../src'
|
} from '../src'
|
||||||
import { afterEach, beforeEach, describe, expect } from 'vitest'
|
import { describe, expect } from 'vitest'
|
||||||
import { defineComponent } from '@vue/runtime-core'
|
import { makeRender } from './_utils'
|
||||||
|
|
||||||
let host: HTMLElement
|
const define = makeRender()
|
||||||
|
|
||||||
const initHost = () => {
|
|
||||||
host = document.createElement('div')
|
|
||||||
host.setAttribute('id', 'host')
|
|
||||||
document.body.appendChild(host)
|
|
||||||
}
|
|
||||||
beforeEach(() => {
|
|
||||||
initHost()
|
|
||||||
})
|
|
||||||
afterEach(() => {
|
|
||||||
host.remove()
|
|
||||||
})
|
|
||||||
describe('component', () => {
|
describe('component', () => {
|
||||||
test('unmountComponent', async () => {
|
test('unmountComponent', async () => {
|
||||||
const Comp = defineComponent({
|
const { host, instance } = define(() => {
|
||||||
setup() {
|
|
||||||
const count = ref(0)
|
const count = ref(0)
|
||||||
const t0 = template('<div></div>')
|
const t0 = template('<div></div>')
|
||||||
const n0 = t0()
|
const n0 = t0()
|
||||||
|
@ -37,9 +24,7 @@ describe('component', () => {
|
||||||
setText(n1, count.value)
|
setText(n1, count.value)
|
||||||
})
|
})
|
||||||
return n0
|
return n0
|
||||||
},
|
}).render()
|
||||||
})
|
|
||||||
const instance = render(Comp as any, {}, '#host')
|
|
||||||
expect(host.innerHTML).toBe('<div>0</div>')
|
expect(host.innerHTML).toBe('<div>0</div>')
|
||||||
unmountComponent(instance)
|
unmountComponent(instance)
|
||||||
expect(host.innerHTML).toBe('')
|
expect(host.innerHTML).toBe('')
|
||||||
|
|
|
@ -3,28 +3,15 @@
|
||||||
// Note: emits and listener fallthrough is tested in
|
// Note: emits and listener fallthrough is tested in
|
||||||
// ./rendererAttrsFallthrough.spec.ts.
|
// ./rendererAttrsFallthrough.spec.ts.
|
||||||
|
|
||||||
import {
|
import { nextTick, onBeforeUnmount, unmountComponent } from '../src'
|
||||||
defineComponent,
|
|
||||||
nextTick,
|
|
||||||
onBeforeUnmount,
|
|
||||||
render,
|
|
||||||
unmountComponent,
|
|
||||||
} from '../src'
|
|
||||||
import { isEmitListener } from '../src/componentEmits'
|
import { isEmitListener } from '../src/componentEmits'
|
||||||
|
import { makeRender } from './_utils'
|
||||||
|
|
||||||
let host: HTMLElement
|
const define = makeRender<any>()
|
||||||
|
|
||||||
const initHost = () => {
|
|
||||||
host = document.createElement('div')
|
|
||||||
host.setAttribute('id', 'host')
|
|
||||||
document.body.appendChild(host)
|
|
||||||
}
|
|
||||||
beforeEach(() => initHost())
|
|
||||||
afterEach(() => host.remove())
|
|
||||||
|
|
||||||
describe('component: emit', () => {
|
describe('component: emit', () => {
|
||||||
test('trigger handlers', () => {
|
test('trigger handlers', () => {
|
||||||
const Foo = defineComponent({
|
const { render } = define({
|
||||||
render() {},
|
render() {},
|
||||||
setup(_: any, { emit }: any) {
|
setup(_: any, { emit }: any) {
|
||||||
emit('foo')
|
emit('foo')
|
||||||
|
@ -35,9 +22,7 @@ describe('component: emit', () => {
|
||||||
const onfoo = vi.fn()
|
const onfoo = vi.fn()
|
||||||
const onBar = vi.fn()
|
const onBar = vi.fn()
|
||||||
const onBaz = vi.fn()
|
const onBaz = vi.fn()
|
||||||
render(
|
render({
|
||||||
Foo,
|
|
||||||
{
|
|
||||||
get onfoo() {
|
get onfoo() {
|
||||||
return onfoo
|
return onfoo
|
||||||
},
|
},
|
||||||
|
@ -47,9 +32,7 @@ describe('component: emit', () => {
|
||||||
get ['on!baz']() {
|
get ['on!baz']() {
|
||||||
return onBaz
|
return onBaz
|
||||||
},
|
},
|
||||||
},
|
})
|
||||||
'#host',
|
|
||||||
)
|
|
||||||
|
|
||||||
expect(onfoo).not.toHaveBeenCalled()
|
expect(onfoo).not.toHaveBeenCalled()
|
||||||
expect(onBar).toHaveBeenCalled()
|
expect(onBar).toHaveBeenCalled()
|
||||||
|
@ -57,7 +40,7 @@ describe('component: emit', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
test('trigger camelCase handler', () => {
|
test('trigger camelCase handler', () => {
|
||||||
const Foo = defineComponent({
|
const { render } = define({
|
||||||
render() {},
|
render() {},
|
||||||
setup(_: any, { emit }: any) {
|
setup(_: any, { emit }: any) {
|
||||||
emit('test-event')
|
emit('test-event')
|
||||||
|
@ -65,20 +48,16 @@ describe('component: emit', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
const fooSpy = vi.fn()
|
const fooSpy = vi.fn()
|
||||||
render(
|
render({
|
||||||
Foo,
|
|
||||||
{
|
|
||||||
get onTestEvent() {
|
get onTestEvent() {
|
||||||
return fooSpy
|
return fooSpy
|
||||||
},
|
},
|
||||||
},
|
})
|
||||||
'#host',
|
|
||||||
)
|
|
||||||
expect(fooSpy).toHaveBeenCalled()
|
expect(fooSpy).toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
test('trigger kebab-case handler', () => {
|
test('trigger kebab-case handler', () => {
|
||||||
const Foo = defineComponent({
|
const { render } = define({
|
||||||
render() {},
|
render() {},
|
||||||
setup(_: any, { emit }: any) {
|
setup(_: any, { emit }: any) {
|
||||||
emit('test-event')
|
emit('test-event')
|
||||||
|
@ -86,21 +65,17 @@ describe('component: emit', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
const fooSpy = vi.fn()
|
const fooSpy = vi.fn()
|
||||||
render(
|
render({
|
||||||
Foo,
|
|
||||||
{
|
|
||||||
get ['onTest-event']() {
|
get ['onTest-event']() {
|
||||||
return fooSpy
|
return fooSpy
|
||||||
},
|
},
|
||||||
},
|
})
|
||||||
'#host',
|
|
||||||
)
|
|
||||||
expect(fooSpy).toHaveBeenCalledTimes(1)
|
expect(fooSpy).toHaveBeenCalledTimes(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
// #3527
|
// #3527
|
||||||
test.todo('trigger mixed case handlers', () => {
|
test.todo('trigger mixed case handlers', () => {
|
||||||
const Foo = defineComponent({
|
const { render } = define({
|
||||||
render() {},
|
render() {},
|
||||||
setup(_: any, { emit }: any) {
|
setup(_: any, { emit }: any) {
|
||||||
emit('test-event')
|
emit('test-event')
|
||||||
|
@ -111,7 +86,6 @@ describe('component: emit', () => {
|
||||||
const fooSpy = vi.fn()
|
const fooSpy = vi.fn()
|
||||||
const barSpy = vi.fn()
|
const barSpy = vi.fn()
|
||||||
render(
|
render(
|
||||||
Foo,
|
|
||||||
// TODO: impl `toHandlers`
|
// TODO: impl `toHandlers`
|
||||||
{
|
{
|
||||||
get ['onTest-Event']() {
|
get ['onTest-Event']() {
|
||||||
|
@ -121,7 +95,6 @@ describe('component: emit', () => {
|
||||||
return barSpy
|
return barSpy
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'#host',
|
|
||||||
)
|
)
|
||||||
expect(fooSpy).toHaveBeenCalledTimes(1)
|
expect(fooSpy).toHaveBeenCalledTimes(1)
|
||||||
expect(barSpy).toHaveBeenCalledTimes(1)
|
expect(barSpy).toHaveBeenCalledTimes(1)
|
||||||
|
@ -129,7 +102,7 @@ describe('component: emit', () => {
|
||||||
|
|
||||||
// for v-model:foo-bar usage in DOM templates
|
// for v-model:foo-bar usage in DOM templates
|
||||||
test('trigger hyphenated events for update:xxx events', () => {
|
test('trigger hyphenated events for update:xxx events', () => {
|
||||||
const Foo = defineComponent({
|
const { render } = define({
|
||||||
render() {},
|
render() {},
|
||||||
setup(_: any, { emit }: any) {
|
setup(_: any, { emit }: any) {
|
||||||
emit('update:fooProp')
|
emit('update:fooProp')
|
||||||
|
@ -139,25 +112,21 @@ describe('component: emit', () => {
|
||||||
|
|
||||||
const fooSpy = vi.fn()
|
const fooSpy = vi.fn()
|
||||||
const barSpy = vi.fn()
|
const barSpy = vi.fn()
|
||||||
render(
|
render({
|
||||||
Foo,
|
|
||||||
{
|
|
||||||
get ['onUpdate:fooProp']() {
|
get ['onUpdate:fooProp']() {
|
||||||
return fooSpy
|
return fooSpy
|
||||||
},
|
},
|
||||||
get ['onUpdate:bar-prop']() {
|
get ['onUpdate:bar-prop']() {
|
||||||
return barSpy
|
return barSpy
|
||||||
},
|
},
|
||||||
},
|
})
|
||||||
'#host',
|
|
||||||
)
|
|
||||||
|
|
||||||
expect(fooSpy).toHaveBeenCalled()
|
expect(fooSpy).toHaveBeenCalled()
|
||||||
expect(barSpy).toHaveBeenCalled()
|
expect(barSpy).toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should trigger array of listeners', async () => {
|
test('should trigger array of listeners', async () => {
|
||||||
const App = defineComponent({
|
const { render } = define({
|
||||||
render() {},
|
render() {},
|
||||||
setup(_: any, { emit }: any) {
|
setup(_: any, { emit }: any) {
|
||||||
emit('foo', 1)
|
emit('foo', 1)
|
||||||
|
@ -167,15 +136,11 @@ describe('component: emit', () => {
|
||||||
const fn1 = vi.fn()
|
const fn1 = vi.fn()
|
||||||
const fn2 = vi.fn()
|
const fn2 = vi.fn()
|
||||||
|
|
||||||
render(
|
render({
|
||||||
App,
|
|
||||||
{
|
|
||||||
get onFoo() {
|
get onFoo() {
|
||||||
return [fn1, fn2]
|
return [fn1, fn2]
|
||||||
},
|
},
|
||||||
},
|
})
|
||||||
'#host',
|
|
||||||
)
|
|
||||||
expect(fn1).toHaveBeenCalledTimes(1)
|
expect(fn1).toHaveBeenCalledTimes(1)
|
||||||
expect(fn1).toHaveBeenCalledWith(1)
|
expect(fn1).toHaveBeenCalledWith(1)
|
||||||
expect(fn2).toHaveBeenCalledTimes(1)
|
expect(fn2).toHaveBeenCalledTimes(1)
|
||||||
|
@ -191,15 +156,14 @@ describe('component: emit', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should not warn if has equivalent onXXX prop', () => {
|
test('should not warn if has equivalent onXXX prop', () => {
|
||||||
const Foo = defineComponent({
|
define({
|
||||||
props: ['onFoo'],
|
props: ['onFoo'],
|
||||||
emits: [],
|
emits: [],
|
||||||
render() {},
|
render() {},
|
||||||
setup(_: any, { emit }: any) {
|
setup(_: any, { emit }: any) {
|
||||||
emit('foo')
|
emit('foo')
|
||||||
},
|
},
|
||||||
})
|
}).render()
|
||||||
render(Foo, {}, '#host')
|
|
||||||
expect(
|
expect(
|
||||||
`Component emitted event "foo" but it is neither declared`,
|
`Component emitted event "foo" but it is neither declared`,
|
||||||
).not.toHaveBeenWarned()
|
).not.toHaveBeenWarned()
|
||||||
|
@ -219,7 +183,7 @@ describe('component: emit', () => {
|
||||||
// )
|
// )
|
||||||
|
|
||||||
test('.once', () => {
|
test('.once', () => {
|
||||||
const Foo = defineComponent({
|
const { render } = define({
|
||||||
render() {},
|
render() {},
|
||||||
emits: {
|
emits: {
|
||||||
foo: null,
|
foo: null,
|
||||||
|
@ -234,24 +198,20 @@ describe('component: emit', () => {
|
||||||
})
|
})
|
||||||
const fn = vi.fn()
|
const fn = vi.fn()
|
||||||
const barFn = vi.fn()
|
const barFn = vi.fn()
|
||||||
render(
|
render({
|
||||||
Foo,
|
|
||||||
{
|
|
||||||
get onFooOnce() {
|
get onFooOnce() {
|
||||||
return fn
|
return fn
|
||||||
},
|
},
|
||||||
get onBarOnce() {
|
get onBarOnce() {
|
||||||
return barFn
|
return barFn
|
||||||
},
|
},
|
||||||
},
|
})
|
||||||
'#host',
|
|
||||||
)
|
|
||||||
expect(fn).toHaveBeenCalledTimes(1)
|
expect(fn).toHaveBeenCalledTimes(1)
|
||||||
expect(barFn).toHaveBeenCalledTimes(1)
|
expect(barFn).toHaveBeenCalledTimes(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('.once with normal listener of the same name', () => {
|
test('.once with normal listener of the same name', () => {
|
||||||
const Foo = defineComponent({
|
const { render } = define({
|
||||||
render() {},
|
render() {},
|
||||||
emits: {
|
emits: {
|
||||||
foo: null,
|
foo: null,
|
||||||
|
@ -263,24 +223,20 @@ describe('component: emit', () => {
|
||||||
})
|
})
|
||||||
const onFoo = vi.fn()
|
const onFoo = vi.fn()
|
||||||
const onFooOnce = vi.fn()
|
const onFooOnce = vi.fn()
|
||||||
render(
|
render({
|
||||||
Foo,
|
|
||||||
{
|
|
||||||
get onFoo() {
|
get onFoo() {
|
||||||
return onFoo
|
return onFoo
|
||||||
},
|
},
|
||||||
get onFooOnce() {
|
get onFooOnce() {
|
||||||
return onFooOnce
|
return onFooOnce
|
||||||
},
|
},
|
||||||
},
|
})
|
||||||
'#host',
|
|
||||||
)
|
|
||||||
expect(onFoo).toHaveBeenCalledTimes(2)
|
expect(onFoo).toHaveBeenCalledTimes(2)
|
||||||
expect(onFooOnce).toHaveBeenCalledTimes(1)
|
expect(onFooOnce).toHaveBeenCalledTimes(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('.number modifier should work with v-model on component', () => {
|
test('.number modifier should work with v-model on component', () => {
|
||||||
const Foo = defineComponent({
|
const { render } = define({
|
||||||
render() {},
|
render() {},
|
||||||
setup(_: any, { emit }: any) {
|
setup(_: any, { emit }: any) {
|
||||||
emit('update:modelValue', '1')
|
emit('update:modelValue', '1')
|
||||||
|
@ -289,9 +245,7 @@ describe('component: emit', () => {
|
||||||
})
|
})
|
||||||
const fn1 = vi.fn()
|
const fn1 = vi.fn()
|
||||||
const fn2 = vi.fn()
|
const fn2 = vi.fn()
|
||||||
render(
|
render({
|
||||||
Foo,
|
|
||||||
{
|
|
||||||
get modelValue() {
|
get modelValue() {
|
||||||
return null
|
return null
|
||||||
},
|
},
|
||||||
|
@ -310,9 +264,7 @@ describe('component: emit', () => {
|
||||||
get ['onUpdate:foo']() {
|
get ['onUpdate:foo']() {
|
||||||
return fn2
|
return fn2
|
||||||
},
|
},
|
||||||
},
|
})
|
||||||
'#host',
|
|
||||||
)
|
|
||||||
expect(fn1).toHaveBeenCalledTimes(1)
|
expect(fn1).toHaveBeenCalledTimes(1)
|
||||||
expect(fn1).toHaveBeenCalledWith(1)
|
expect(fn1).toHaveBeenCalledWith(1)
|
||||||
expect(fn2).toHaveBeenCalledTimes(1)
|
expect(fn2).toHaveBeenCalledTimes(1)
|
||||||
|
@ -320,7 +272,7 @@ describe('component: emit', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
test('.trim modifier should work with v-model on component', () => {
|
test('.trim modifier should work with v-model on component', () => {
|
||||||
const Foo = defineComponent({
|
const { render } = define({
|
||||||
render() {},
|
render() {},
|
||||||
setup(_: any, { emit }: any) {
|
setup(_: any, { emit }: any) {
|
||||||
emit('update:modelValue', ' one ')
|
emit('update:modelValue', ' one ')
|
||||||
|
@ -329,9 +281,7 @@ describe('component: emit', () => {
|
||||||
})
|
})
|
||||||
const fn1 = vi.fn()
|
const fn1 = vi.fn()
|
||||||
const fn2 = vi.fn()
|
const fn2 = vi.fn()
|
||||||
render(
|
render({
|
||||||
Foo,
|
|
||||||
{
|
|
||||||
get modelValue() {
|
get modelValue() {
|
||||||
return null
|
return null
|
||||||
},
|
},
|
||||||
|
@ -350,9 +300,7 @@ describe('component: emit', () => {
|
||||||
get 'onUpdate:foo'() {
|
get 'onUpdate:foo'() {
|
||||||
return fn2
|
return fn2
|
||||||
},
|
},
|
||||||
},
|
})
|
||||||
'#host',
|
|
||||||
)
|
|
||||||
expect(fn1).toHaveBeenCalledTimes(1)
|
expect(fn1).toHaveBeenCalledTimes(1)
|
||||||
expect(fn1).toHaveBeenCalledWith('one')
|
expect(fn1).toHaveBeenCalledWith('one')
|
||||||
expect(fn2).toHaveBeenCalledTimes(1)
|
expect(fn2).toHaveBeenCalledTimes(1)
|
||||||
|
@ -360,7 +308,7 @@ describe('component: emit', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
test('.trim and .number modifiers should work with v-model on component', () => {
|
test('.trim and .number modifiers should work with v-model on component', () => {
|
||||||
const Foo = defineComponent({
|
const { render } = define({
|
||||||
render() {},
|
render() {},
|
||||||
setup(_: any, { emit }: any) {
|
setup(_: any, { emit }: any) {
|
||||||
emit('update:modelValue', ' +01.2 ')
|
emit('update:modelValue', ' +01.2 ')
|
||||||
|
@ -369,9 +317,7 @@ describe('component: emit', () => {
|
||||||
})
|
})
|
||||||
const fn1 = vi.fn()
|
const fn1 = vi.fn()
|
||||||
const fn2 = vi.fn()
|
const fn2 = vi.fn()
|
||||||
render(
|
render({
|
||||||
Foo,
|
|
||||||
{
|
|
||||||
get modelValue() {
|
get modelValue() {
|
||||||
return null
|
return null
|
||||||
},
|
},
|
||||||
|
@ -390,9 +336,7 @@ describe('component: emit', () => {
|
||||||
get ['onUpdate:foo']() {
|
get ['onUpdate:foo']() {
|
||||||
return fn2
|
return fn2
|
||||||
},
|
},
|
||||||
},
|
})
|
||||||
'#host',
|
|
||||||
)
|
|
||||||
expect(fn1).toHaveBeenCalledTimes(1)
|
expect(fn1).toHaveBeenCalledTimes(1)
|
||||||
expect(fn1).toHaveBeenCalledWith(1.2)
|
expect(fn1).toHaveBeenCalledWith(1.2)
|
||||||
expect(fn2).toHaveBeenCalledTimes(1)
|
expect(fn2).toHaveBeenCalledTimes(1)
|
||||||
|
@ -400,16 +344,14 @@ describe('component: emit', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
test('only trim string parameter when work with v-model on component', () => {
|
test('only trim string parameter when work with v-model on component', () => {
|
||||||
const Foo = defineComponent({
|
const { render } = define({
|
||||||
render() {},
|
render() {},
|
||||||
setup(_: any, { emit }: any) {
|
setup(_: any, { emit }: any) {
|
||||||
emit('update:modelValue', ' foo ', { bar: ' bar ' })
|
emit('update:modelValue', ' foo ', { bar: ' bar ' })
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
const fn = vi.fn()
|
const fn = vi.fn()
|
||||||
render(
|
render({
|
||||||
Foo,
|
|
||||||
{
|
|
||||||
get modelValue() {
|
get modelValue() {
|
||||||
return null
|
return null
|
||||||
},
|
},
|
||||||
|
@ -419,9 +361,7 @@ describe('component: emit', () => {
|
||||||
get ['onUpdate:modelValue']() {
|
get ['onUpdate:modelValue']() {
|
||||||
return fn
|
return fn
|
||||||
},
|
},
|
||||||
},
|
})
|
||||||
'#host',
|
|
||||||
)
|
|
||||||
expect(fn).toHaveBeenCalledTimes(1)
|
expect(fn).toHaveBeenCalledTimes(1)
|
||||||
expect(fn).toHaveBeenCalledWith('foo', { bar: ' bar ' })
|
expect(fn).toHaveBeenCalledWith('foo', { bar: ' bar ' })
|
||||||
})
|
})
|
||||||
|
@ -457,7 +397,7 @@ describe('component: emit', () => {
|
||||||
|
|
||||||
test('does not emit after unmount', async () => {
|
test('does not emit after unmount', async () => {
|
||||||
const fn = vi.fn()
|
const fn = vi.fn()
|
||||||
const Foo = defineComponent({
|
const { instance } = define({
|
||||||
emits: ['closing'],
|
emits: ['closing'],
|
||||||
setup(_: any, { emit }: any) {
|
setup(_: any, { emit }: any) {
|
||||||
onBeforeUnmount(async () => {
|
onBeforeUnmount(async () => {
|
||||||
|
@ -466,18 +406,13 @@ describe('component: emit', () => {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
render() {},
|
render() {},
|
||||||
})
|
}).render({
|
||||||
const i = render(
|
|
||||||
Foo,
|
|
||||||
{
|
|
||||||
get onClosing() {
|
get onClosing() {
|
||||||
return fn
|
return fn
|
||||||
},
|
},
|
||||||
},
|
})
|
||||||
'#host',
|
|
||||||
)
|
|
||||||
await nextTick()
|
await nextTick()
|
||||||
unmountComponent(i)
|
unmountComponent(instance)
|
||||||
await nextTick()
|
await nextTick()
|
||||||
expect(fn).not.toHaveBeenCalled()
|
expect(fn).not.toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
|
@ -16,22 +16,16 @@ import {
|
||||||
template,
|
template,
|
||||||
watchEffect,
|
watchEffect,
|
||||||
} from '../src'
|
} from '../src'
|
||||||
|
import { makeRender } from './_utils'
|
||||||
|
|
||||||
let host: HTMLElement
|
const define = makeRender<any>()
|
||||||
const initHost = () => {
|
|
||||||
host = document.createElement('div')
|
|
||||||
host.setAttribute('id', 'host')
|
|
||||||
document.body.appendChild(host)
|
|
||||||
}
|
|
||||||
beforeEach(() => initHost())
|
|
||||||
afterEach(() => host.remove())
|
|
||||||
|
|
||||||
describe('component props (vapor)', () => {
|
describe('component props (vapor)', () => {
|
||||||
test('stateful', () => {
|
test('stateful', () => {
|
||||||
let props: any
|
let props: any
|
||||||
// TODO: attrs
|
// TODO: attrs
|
||||||
|
|
||||||
const Comp = defineComponent({
|
const { render } = define({
|
||||||
props: ['fooBar', 'barBaz'],
|
props: ['fooBar', 'barBaz'],
|
||||||
render() {
|
render() {
|
||||||
const instance = getCurrentInstance()!
|
const instance = getCurrentInstance()!
|
||||||
|
@ -39,46 +33,34 @@ describe('component props (vapor)', () => {
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
render(
|
render({
|
||||||
Comp,
|
|
||||||
{
|
|
||||||
get fooBar() {
|
get fooBar() {
|
||||||
return 1
|
return 1
|
||||||
},
|
},
|
||||||
},
|
})
|
||||||
host,
|
|
||||||
)
|
|
||||||
expect(props.fooBar).toEqual(1)
|
expect(props.fooBar).toEqual(1)
|
||||||
|
|
||||||
// test passing kebab-case and resolving to camelCase
|
// test passing kebab-case and resolving to camelCase
|
||||||
render(
|
render({
|
||||||
Comp,
|
|
||||||
{
|
|
||||||
get ['foo-bar']() {
|
get ['foo-bar']() {
|
||||||
return 2
|
return 2
|
||||||
},
|
},
|
||||||
},
|
})
|
||||||
host,
|
|
||||||
)
|
|
||||||
expect(props.fooBar).toEqual(2)
|
expect(props.fooBar).toEqual(2)
|
||||||
|
|
||||||
// test updating kebab-case should not delete it (#955)
|
// test updating kebab-case should not delete it (#955)
|
||||||
render(
|
render({
|
||||||
Comp,
|
|
||||||
{
|
|
||||||
get ['foo-bar']() {
|
get ['foo-bar']() {
|
||||||
return 3
|
return 3
|
||||||
},
|
},
|
||||||
get barBaz() {
|
get barBaz() {
|
||||||
return 5
|
return 5
|
||||||
},
|
},
|
||||||
},
|
})
|
||||||
host,
|
|
||||||
)
|
|
||||||
expect(props.fooBar).toEqual(3)
|
expect(props.fooBar).toEqual(3)
|
||||||
expect(props.barBaz).toEqual(5)
|
expect(props.barBaz).toEqual(5)
|
||||||
|
|
||||||
render(Comp, {}, host)
|
render({})
|
||||||
expect(props.fooBar).toBeUndefined()
|
expect(props.fooBar).toBeUndefined()
|
||||||
expect(props.barBaz).toBeUndefined()
|
expect(props.barBaz).toBeUndefined()
|
||||||
// expect(props.qux).toEqual(5) // TODO: attrs
|
// expect(props.qux).toEqual(5) // TODO: attrs
|
||||||
|
@ -92,7 +74,7 @@ describe('component props (vapor)', () => {
|
||||||
let props: any
|
let props: any
|
||||||
// TODO: attrs
|
// TODO: attrs
|
||||||
|
|
||||||
const Comp: FunctionalComponent = defineComponent((_props: any) => {
|
const { component: Comp, render } = define((_props: any) => {
|
||||||
const instance = getCurrentInstance()!
|
const instance = getCurrentInstance()!
|
||||||
props = instance.props
|
props = instance.props
|
||||||
return {}
|
return {}
|
||||||
|
@ -100,29 +82,21 @@ describe('component props (vapor)', () => {
|
||||||
Comp.props = ['foo']
|
Comp.props = ['foo']
|
||||||
Comp.render = (() => {}) as any
|
Comp.render = (() => {}) as any
|
||||||
|
|
||||||
render(
|
render({
|
||||||
Comp,
|
|
||||||
{
|
|
||||||
get foo() {
|
get foo() {
|
||||||
return 1
|
return 1
|
||||||
},
|
},
|
||||||
},
|
})
|
||||||
host,
|
|
||||||
)
|
|
||||||
expect(props.foo).toEqual(1)
|
expect(props.foo).toEqual(1)
|
||||||
|
|
||||||
render(
|
render({
|
||||||
Comp,
|
|
||||||
{
|
|
||||||
get foo() {
|
get foo() {
|
||||||
return 2
|
return 2
|
||||||
},
|
},
|
||||||
},
|
})
|
||||||
host,
|
|
||||||
)
|
|
||||||
expect(props.foo).toEqual(2)
|
expect(props.foo).toEqual(2)
|
||||||
|
|
||||||
render(Comp, {}, host)
|
render({})
|
||||||
expect(props.foo).toBeUndefined()
|
expect(props.foo).toBeUndefined()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -130,7 +104,7 @@ describe('component props (vapor)', () => {
|
||||||
let props: any
|
let props: any
|
||||||
// TODO: attrs
|
// TODO: attrs
|
||||||
|
|
||||||
const Comp: FunctionalComponent = defineComponent((_props: any) => {
|
const { component: Comp, render } = define((_props: any) => {
|
||||||
const instance = getCurrentInstance()!
|
const instance = getCurrentInstance()!
|
||||||
props = instance.props
|
props = instance.props
|
||||||
return {}
|
return {}
|
||||||
|
@ -138,32 +112,24 @@ describe('component props (vapor)', () => {
|
||||||
Comp.props = undefined as any
|
Comp.props = undefined as any
|
||||||
Comp.render = (() => {}) as any
|
Comp.render = (() => {}) as any
|
||||||
|
|
||||||
render(
|
render({
|
||||||
Comp,
|
|
||||||
{
|
|
||||||
get foo() {
|
get foo() {
|
||||||
return 1
|
return 1
|
||||||
},
|
},
|
||||||
},
|
})
|
||||||
host,
|
|
||||||
)
|
|
||||||
expect(props.foo).toBeUndefined()
|
expect(props.foo).toBeUndefined()
|
||||||
|
|
||||||
render(
|
render({
|
||||||
Comp,
|
|
||||||
{
|
|
||||||
get foo() {
|
get foo() {
|
||||||
return 2
|
return 2
|
||||||
},
|
},
|
||||||
},
|
})
|
||||||
host,
|
|
||||||
)
|
|
||||||
expect(props.foo).toBeUndefined()
|
expect(props.foo).toBeUndefined()
|
||||||
})
|
})
|
||||||
|
|
||||||
test('boolean casting', () => {
|
test('boolean casting', () => {
|
||||||
let props: any
|
let props: any
|
||||||
const Comp = defineComponent({
|
const { render } = define({
|
||||||
props: {
|
props: {
|
||||||
foo: Boolean,
|
foo: Boolean,
|
||||||
bar: Boolean,
|
bar: Boolean,
|
||||||
|
@ -176,16 +142,12 @@ describe('component props (vapor)', () => {
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
render(
|
render({
|
||||||
Comp,
|
|
||||||
{
|
|
||||||
// absent should cast to false
|
// absent should cast to false
|
||||||
bar: '', // empty string should cast to true
|
bar: '', // empty string should cast to true
|
||||||
baz: 'baz', // same string should cast to true
|
baz: 'baz', // same string should cast to true
|
||||||
qux: 'ok', // other values should be left in-tact (but raise warning)
|
qux: 'ok', // other values should be left in-tact (but raise warning)
|
||||||
},
|
})
|
||||||
host,
|
|
||||||
)
|
|
||||||
|
|
||||||
expect(props.foo).toBe(false)
|
expect(props.foo).toBe(false)
|
||||||
expect(props.bar).toBe(true)
|
expect(props.bar).toBe(true)
|
||||||
|
@ -198,7 +160,7 @@ describe('component props (vapor)', () => {
|
||||||
const defaultFn = vi.fn(() => ({ a: 1 }))
|
const defaultFn = vi.fn(() => ({ a: 1 }))
|
||||||
const defaultBaz = vi.fn(() => ({ b: 1 }))
|
const defaultBaz = vi.fn(() => ({ b: 1 }))
|
||||||
|
|
||||||
const Comp = defineComponent({
|
const { render } = define({
|
||||||
props: {
|
props: {
|
||||||
foo: {
|
foo: {
|
||||||
default: 1,
|
default: 1,
|
||||||
|
@ -217,15 +179,11 @@ describe('component props (vapor)', () => {
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
render(
|
render({
|
||||||
Comp,
|
|
||||||
{
|
|
||||||
get foo() {
|
get foo() {
|
||||||
return 2
|
return 2
|
||||||
},
|
},
|
||||||
},
|
})
|
||||||
host,
|
|
||||||
)
|
|
||||||
expect(props.foo).toBe(2)
|
expect(props.foo).toBe(2)
|
||||||
// const prevBar = props.bar
|
// const prevBar = props.bar
|
||||||
props.bar
|
props.bar
|
||||||
|
@ -237,58 +195,42 @@ describe('component props (vapor)', () => {
|
||||||
|
|
||||||
// #999: updates should not cause default factory of unchanged prop to be
|
// #999: updates should not cause default factory of unchanged prop to be
|
||||||
// called again
|
// called again
|
||||||
render(
|
render({
|
||||||
Comp,
|
|
||||||
{
|
|
||||||
get foo() {
|
get foo() {
|
||||||
return 3
|
return 3
|
||||||
},
|
},
|
||||||
},
|
})
|
||||||
host,
|
|
||||||
)
|
|
||||||
expect(props.foo).toBe(3)
|
expect(props.foo).toBe(3)
|
||||||
expect(props.bar).toEqual({ a: 1 })
|
expect(props.bar).toEqual({ a: 1 })
|
||||||
// expect(props.bar).toBe(prevBar) // failed: (caching is not supported)
|
// expect(props.bar).toBe(prevBar) // failed: (caching is not supported)
|
||||||
// expect(defaultFn).toHaveBeenCalledTimes(1) // failed: caching is not supported (called 3 times)
|
// expect(defaultFn).toHaveBeenCalledTimes(1) // failed: caching is not supported (called 3 times)
|
||||||
|
|
||||||
render(
|
render({
|
||||||
Comp,
|
|
||||||
{
|
|
||||||
get bar() {
|
get bar() {
|
||||||
return { b: 2 }
|
return { b: 2 }
|
||||||
},
|
},
|
||||||
},
|
})
|
||||||
host,
|
|
||||||
)
|
|
||||||
expect(props.foo).toBe(1)
|
expect(props.foo).toBe(1)
|
||||||
expect(props.bar).toEqual({ b: 2 })
|
expect(props.bar).toEqual({ b: 2 })
|
||||||
// expect(defaultFn).toHaveBeenCalledTimes(1) // failed: caching is not supported (called 3 times)
|
// expect(defaultFn).toHaveBeenCalledTimes(1) // failed: caching is not supported (called 3 times)
|
||||||
|
|
||||||
render(
|
render({
|
||||||
Comp,
|
|
||||||
{
|
|
||||||
get foo() {
|
get foo() {
|
||||||
return 3
|
return 3
|
||||||
},
|
},
|
||||||
get bar() {
|
get bar() {
|
||||||
return { b: 3 }
|
return { b: 3 }
|
||||||
},
|
},
|
||||||
},
|
})
|
||||||
host,
|
|
||||||
)
|
|
||||||
expect(props.foo).toBe(3)
|
expect(props.foo).toBe(3)
|
||||||
expect(props.bar).toEqual({ b: 3 })
|
expect(props.bar).toEqual({ b: 3 })
|
||||||
// expect(defaultFn).toHaveBeenCalledTimes(1) // failed: caching is not supported (called 3 times)
|
// expect(defaultFn).toHaveBeenCalledTimes(1) // failed: caching is not supported (called 3 times)
|
||||||
|
|
||||||
render(
|
render({
|
||||||
Comp,
|
|
||||||
{
|
|
||||||
get bar() {
|
get bar() {
|
||||||
return { b: 4 }
|
return { b: 4 }
|
||||||
},
|
},
|
||||||
},
|
})
|
||||||
host,
|
|
||||||
)
|
|
||||||
expect(props.foo).toBe(1)
|
expect(props.foo).toBe(1)
|
||||||
expect(props.bar).toEqual({ b: 4 })
|
expect(props.bar).toEqual({ b: 4 })
|
||||||
// expect(defaultFn).toHaveBeenCalledTimes(1) // failed: caching is not supported (called 3 times)
|
// expect(defaultFn).toHaveBeenCalledTimes(1) // failed: caching is not supported (called 3 times)
|
||||||
|
@ -301,7 +243,7 @@ describe('component props (vapor)', () => {
|
||||||
// NOTE: maybe it's unnecessary
|
// NOTE: maybe it's unnecessary
|
||||||
// https://github.com/vuejs/core-vapor/pull/99#discussion_r1472647377
|
// https://github.com/vuejs/core-vapor/pull/99#discussion_r1472647377
|
||||||
test('optimized props updates', async () => {
|
test('optimized props updates', async () => {
|
||||||
const Child = defineComponent({
|
const renderChild = define({
|
||||||
props: ['foo'],
|
props: ['foo'],
|
||||||
render() {
|
render() {
|
||||||
const instance = getCurrentInstance()!
|
const instance = getCurrentInstance()!
|
||||||
|
@ -315,19 +257,18 @@ describe('component props (vapor)', () => {
|
||||||
})
|
})
|
||||||
return n0
|
return n0
|
||||||
},
|
},
|
||||||
})
|
}).render
|
||||||
|
|
||||||
const foo = ref(1)
|
const foo = ref(1)
|
||||||
const id = ref('a')
|
const id = ref('a')
|
||||||
const Comp = defineComponent({
|
const { instance, host } = define({
|
||||||
setup() {
|
setup() {
|
||||||
return { foo, id }
|
return { foo, id }
|
||||||
},
|
},
|
||||||
render(_ctx: Record<string, any>) {
|
render(_ctx: Record<string, any>) {
|
||||||
const t0 = template('')
|
const t0 = template('')
|
||||||
const n0 = t0()
|
const n0 = t0()
|
||||||
render(
|
renderChild(
|
||||||
Child,
|
|
||||||
{
|
{
|
||||||
get foo() {
|
get foo() {
|
||||||
return _ctx.foo
|
return _ctx.foo
|
||||||
|
@ -340,10 +281,8 @@ describe('component props (vapor)', () => {
|
||||||
)
|
)
|
||||||
return n0
|
return n0
|
||||||
},
|
},
|
||||||
})
|
}).render()
|
||||||
|
const reset = setCurrentInstance(instance)
|
||||||
const instace = render(Comp, {}, host)
|
|
||||||
const reset = setCurrentInstance(instace)
|
|
||||||
// expect(host.innerHTML).toBe('<div id="a">1</div>') // TODO: Fallthrough Attributes
|
// expect(host.innerHTML).toBe('<div id="a">1</div>') // TODO: Fallthrough Attributes
|
||||||
expect(host.innerHTML).toBe('<div>1</div>')
|
expect(host.innerHTML).toBe('<div>1</div>')
|
||||||
|
|
||||||
|
@ -366,7 +305,16 @@ describe('component props (vapor)', () => {
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
const Comp = defineComponent({
|
const props = {
|
||||||
|
get foo() {
|
||||||
|
return 1
|
||||||
|
},
|
||||||
|
get bar() {
|
||||||
|
return 2
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
define({
|
||||||
props: {
|
props: {
|
||||||
foo: {
|
foo: {
|
||||||
type: Number,
|
type: Number,
|
||||||
|
@ -381,18 +329,8 @@ describe('component props (vapor)', () => {
|
||||||
const n0 = t0()
|
const n0 = t0()
|
||||||
return n0
|
return n0
|
||||||
},
|
},
|
||||||
})
|
}).render(props)
|
||||||
|
|
||||||
const props = {
|
|
||||||
get foo() {
|
|
||||||
return 1
|
|
||||||
},
|
|
||||||
get bar() {
|
|
||||||
return 2
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
render(Comp, props, host)
|
|
||||||
expect(mockFn).toHaveBeenCalled()
|
expect(mockFn).toHaveBeenCalled()
|
||||||
// NOTE: Vapor Component props defined by getter. So, `props` not Equal to `{ foo: 1, bar: 2 }`
|
// NOTE: Vapor Component props defined by getter. So, `props` not Equal to `{ foo: 1, bar: 2 }`
|
||||||
// expect(mockFn).toHaveBeenCalledWith(1, { foo: 1, bar: 2 })
|
// expect(mockFn).toHaveBeenCalledWith(1, { foo: 1, bar: 2 })
|
||||||
|
@ -407,7 +345,7 @@ describe('component props (vapor)', () => {
|
||||||
'validator should not be able to mutate other props',
|
'validator should not be able to mutate other props',
|
||||||
async () => {
|
async () => {
|
||||||
const mockFn = vi.fn((...args: any[]) => true)
|
const mockFn = vi.fn((...args: any[]) => true)
|
||||||
const Comp = defineComponent({
|
defineComponent({
|
||||||
props: {
|
props: {
|
||||||
foo: {
|
foo: {
|
||||||
type: Number,
|
type: Number,
|
||||||
|
@ -423,20 +361,15 @@ describe('component props (vapor)', () => {
|
||||||
const n0 = t0()
|
const n0 = t0()
|
||||||
return n0
|
return n0
|
||||||
},
|
},
|
||||||
})
|
}).render({
|
||||||
|
|
||||||
render(
|
|
||||||
Comp,
|
|
||||||
{
|
|
||||||
get foo() {
|
get foo() {
|
||||||
return 1
|
return 1
|
||||||
},
|
},
|
||||||
get bar() {
|
get bar() {
|
||||||
return 2
|
return 2
|
||||||
},
|
},
|
||||||
},
|
})
|
||||||
host,
|
|
||||||
)
|
|
||||||
expect(
|
expect(
|
||||||
`Set operation on key "bar" failed: target is readonly.`,
|
`Set operation on key "bar" failed: target is readonly.`,
|
||||||
).toHaveBeenWarnedLast()
|
).toHaveBeenWarnedLast()
|
||||||
|
@ -450,7 +383,7 @@ describe('component props (vapor)', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
test('warn absent required props', () => {
|
test('warn absent required props', () => {
|
||||||
const Comp = defineComponent({
|
define({
|
||||||
props: {
|
props: {
|
||||||
bool: { type: Boolean, required: true },
|
bool: { type: Boolean, required: true },
|
||||||
str: { type: String, required: true },
|
str: { type: String, required: true },
|
||||||
|
@ -459,8 +392,7 @@ describe('component props (vapor)', () => {
|
||||||
setup() {
|
setup() {
|
||||||
return () => null
|
return () => null
|
||||||
},
|
},
|
||||||
})
|
}).render()
|
||||||
render(Comp, {}, host)
|
|
||||||
expect(`Missing required prop: "bool"`).toHaveBeenWarned()
|
expect(`Missing required prop: "bool"`).toHaveBeenWarned()
|
||||||
expect(`Missing required prop: "str"`).toHaveBeenWarned()
|
expect(`Missing required prop: "str"`).toHaveBeenWarned()
|
||||||
expect(`Missing required prop: "num"`).toHaveBeenWarned()
|
expect(`Missing required prop: "num"`).toHaveBeenWarned()
|
||||||
|
@ -471,29 +403,23 @@ describe('component props (vapor)', () => {
|
||||||
|
|
||||||
// #3495
|
// #3495
|
||||||
test('should not warn required props using kebab-case', async () => {
|
test('should not warn required props using kebab-case', async () => {
|
||||||
const Comp = defineComponent({
|
define({
|
||||||
props: {
|
props: {
|
||||||
fooBar: { type: String, required: true },
|
fooBar: { type: String, required: true },
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
return () => null
|
return () => null
|
||||||
},
|
},
|
||||||
})
|
}).render({
|
||||||
|
|
||||||
render(
|
|
||||||
Comp,
|
|
||||||
{
|
|
||||||
get ['foo-bar']() {
|
get ['foo-bar']() {
|
||||||
return 'hello'
|
return 'hello'
|
||||||
},
|
},
|
||||||
},
|
})
|
||||||
host,
|
|
||||||
)
|
|
||||||
expect(`Missing required prop: "fooBar"`).not.toHaveBeenWarned()
|
expect(`Missing required prop: "fooBar"`).not.toHaveBeenWarned()
|
||||||
})
|
})
|
||||||
|
|
||||||
test('props type support BigInt', () => {
|
test('props type support BigInt', () => {
|
||||||
const Comp = defineComponent({
|
const { host } = define({
|
||||||
props: {
|
props: {
|
||||||
foo: BigInt,
|
foo: BigInt,
|
||||||
},
|
},
|
||||||
|
@ -509,19 +435,11 @@ describe('component props (vapor)', () => {
|
||||||
})
|
})
|
||||||
return n0
|
return n0
|
||||||
},
|
},
|
||||||
})
|
}).render({
|
||||||
|
|
||||||
render(
|
|
||||||
Comp,
|
|
||||||
{
|
|
||||||
get foo() {
|
get foo() {
|
||||||
return (
|
return BigInt(BigInt(100000111)) + BigInt(2000000000) * BigInt(30000000)
|
||||||
BigInt(BigInt(100000111)) + BigInt(2000000000) * BigInt(30000000)
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
},
|
})
|
||||||
'#host',
|
|
||||||
)
|
|
||||||
expect(host.innerHTML).toBe('<div>60000000100000111</div>')
|
expect(host.innerHTML).toBe('<div>60000000100000111</div>')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -560,7 +478,7 @@ describe('component props (vapor)', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
test('support null in required + multiple-type declarations', () => {
|
test('support null in required + multiple-type declarations', () => {
|
||||||
const Comp = defineComponent({
|
const { render } = define({
|
||||||
props: {
|
props: {
|
||||||
foo: { type: [Function, null], required: true },
|
foo: { type: [Function, null], required: true },
|
||||||
},
|
},
|
||||||
|
@ -568,11 +486,11 @@ describe('component props (vapor)', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(() => {
|
expect(() => {
|
||||||
render(Comp, { foo: () => {} }, host)
|
render({ foo: () => {} })
|
||||||
}).not.toThrow()
|
}).not.toThrow()
|
||||||
|
|
||||||
expect(() => {
|
expect(() => {
|
||||||
render(Comp, { foo: null }, host)
|
render({ foo: null })
|
||||||
}).not.toThrow()
|
}).not.toThrow()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -588,12 +506,7 @@ describe('component props (vapor)', () => {
|
||||||
type: String,
|
type: String,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
const Comp = defineComponent({
|
define({ props, render() {} }).render({ msg: 'test' })
|
||||||
props,
|
|
||||||
render() {},
|
|
||||||
})
|
|
||||||
|
|
||||||
render(Comp, { msg: 'test' }, host)
|
|
||||||
|
|
||||||
expect(Object.keys(props.msg).length).toBe(1)
|
expect(Object.keys(props.msg).length).toBe(1)
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import { defineComponent } from 'vue'
|
|
||||||
import {
|
import {
|
||||||
append,
|
append,
|
||||||
children,
|
children,
|
||||||
|
@ -6,26 +5,14 @@ import {
|
||||||
insert,
|
insert,
|
||||||
nextTick,
|
nextTick,
|
||||||
ref,
|
ref,
|
||||||
render,
|
|
||||||
renderEffect,
|
renderEffect,
|
||||||
setText,
|
setText,
|
||||||
template,
|
template,
|
||||||
} from '../src'
|
} from '../src'
|
||||||
import type { Mock } from 'vitest'
|
import type { Mock } from 'vitest'
|
||||||
|
import { makeRender } from './_utils'
|
||||||
|
|
||||||
let host: HTMLElement
|
const define = makeRender()
|
||||||
|
|
||||||
const initHost = () => {
|
|
||||||
host = document.createElement('div')
|
|
||||||
host.setAttribute('id', 'host')
|
|
||||||
document.body.appendChild(host)
|
|
||||||
}
|
|
||||||
beforeEach(() => {
|
|
||||||
initHost()
|
|
||||||
})
|
|
||||||
afterEach(() => {
|
|
||||||
host.remove()
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('createIf', () => {
|
describe('createIf', () => {
|
||||||
test('basic', async () => {
|
test('basic', async () => {
|
||||||
|
@ -44,10 +31,7 @@ describe('createIf', () => {
|
||||||
const t1 = template('<p></p>')
|
const t1 = template('<p></p>')
|
||||||
const t2 = template('<p>zero</p>')
|
const t2 = template('<p>zero</p>')
|
||||||
|
|
||||||
const component = defineComponent({
|
const { host } = define(() => {
|
||||||
setup() {
|
|
||||||
// render
|
|
||||||
return (() => {
|
|
||||||
const n0 = t0()
|
const n0 = t0()
|
||||||
const {
|
const {
|
||||||
0: [n1],
|
0: [n1],
|
||||||
|
@ -76,10 +60,7 @@ describe('createIf', () => {
|
||||||
n1 as any as ParentNode,
|
n1 as any as ParentNode,
|
||||||
)
|
)
|
||||||
return n0
|
return n0
|
||||||
})()
|
}).render()
|
||||||
},
|
|
||||||
})
|
|
||||||
render(component as any, {}, '#host')
|
|
||||||
|
|
||||||
expect(host.innerHTML).toBe('<div><p>zero</p><!--if--></div>')
|
expect(host.innerHTML).toBe('<div><p>zero</p><!--if--></div>')
|
||||||
expect(spyIfFn!).toHaveBeenCalledTimes(0)
|
expect(spyIfFn!).toHaveBeenCalledTimes(0)
|
||||||
|
@ -115,11 +96,7 @@ describe('createIf', () => {
|
||||||
|
|
||||||
const t0 = template('Vapor')
|
const t0 = template('Vapor')
|
||||||
const t1 = template('Hello ')
|
const t1 = template('Hello ')
|
||||||
render(
|
const { host } = define(() => {
|
||||||
defineComponent({
|
|
||||||
setup() {
|
|
||||||
// render
|
|
||||||
return (() => {
|
|
||||||
const n1 = createIf(
|
const n1 = createIf(
|
||||||
() => ok1.value,
|
() => ok1.value,
|
||||||
() => {
|
() => {
|
||||||
|
@ -136,12 +113,8 @@ describe('createIf', () => {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
return [n1]
|
return [n1]
|
||||||
})()
|
}).render()
|
||||||
},
|
|
||||||
}) as any,
|
|
||||||
{},
|
|
||||||
'#host',
|
|
||||||
)
|
|
||||||
expect(host.innerHTML).toBe('Hello Vapor<!--if--><!--if-->')
|
expect(host.innerHTML).toBe('Hello Vapor<!--if--><!--if-->')
|
||||||
|
|
||||||
ok1.value = false
|
ok1.value = false
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
import { defineComponent } from 'vue'
|
|
||||||
import {
|
import {
|
||||||
nextTick,
|
nextTick,
|
||||||
onBeforeUpdate,
|
onBeforeUpdate,
|
||||||
onEffectCleanup,
|
onEffectCleanup,
|
||||||
onUpdated,
|
onUpdated,
|
||||||
ref,
|
ref,
|
||||||
render,
|
|
||||||
renderEffect,
|
renderEffect,
|
||||||
renderWatch,
|
renderWatch,
|
||||||
template,
|
template,
|
||||||
|
@ -13,41 +11,25 @@ import {
|
||||||
watchPostEffect,
|
watchPostEffect,
|
||||||
watchSyncEffect,
|
watchSyncEffect,
|
||||||
} from '../src'
|
} from '../src'
|
||||||
|
import { makeRender } from './_utils'
|
||||||
|
|
||||||
let host: HTMLElement
|
const define = makeRender<any>()
|
||||||
|
const createDemo = (setupFn: () => any, renderFn: (ctx: any) => any) =>
|
||||||
const initHost = () => {
|
define({
|
||||||
host = document.createElement('div')
|
setup: () => {
|
||||||
host.setAttribute('id', 'host')
|
const returned = setupFn()
|
||||||
document.body.appendChild(host)
|
|
||||||
}
|
|
||||||
beforeEach(() => {
|
|
||||||
initHost()
|
|
||||||
})
|
|
||||||
afterEach(() => {
|
|
||||||
host.remove()
|
|
||||||
})
|
|
||||||
const createDemo = (
|
|
||||||
setupFn: (porps: any, ctx: any) => any,
|
|
||||||
renderFn: (ctx: any) => any,
|
|
||||||
) => {
|
|
||||||
const demo = defineComponent({
|
|
||||||
setup(...args) {
|
|
||||||
const returned = setupFn(...args)
|
|
||||||
Object.defineProperty(returned, '__isScriptSetup', {
|
Object.defineProperty(returned, '__isScriptSetup', {
|
||||||
enumerable: false,
|
enumerable: false,
|
||||||
value: true,
|
value: true,
|
||||||
})
|
})
|
||||||
return returned
|
return returned
|
||||||
},
|
},
|
||||||
})
|
render: (ctx: any) => {
|
||||||
demo.render = (ctx: any) => {
|
|
||||||
const t0 = template('<div></div>')
|
const t0 = template('<div></div>')
|
||||||
renderFn(ctx)
|
renderFn(ctx)
|
||||||
return t0()
|
return t0()
|
||||||
}
|
},
|
||||||
return () => render(demo as any, {}, '#host')
|
})
|
||||||
}
|
|
||||||
|
|
||||||
describe('renderWatch', () => {
|
describe('renderWatch', () => {
|
||||||
test('effect', async () => {
|
test('effect', async () => {
|
||||||
|
@ -79,7 +61,7 @@ describe('renderWatch', () => {
|
||||||
test('should run with the scheduling order', async () => {
|
test('should run with the scheduling order', async () => {
|
||||||
const calls: string[] = []
|
const calls: string[] = []
|
||||||
|
|
||||||
const mount = createDemo(
|
const { instance } = createDemo(
|
||||||
() => {
|
() => {
|
||||||
// setup
|
// setup
|
||||||
const source = ref(0)
|
const source = ref(0)
|
||||||
|
@ -129,10 +111,7 @@ describe('renderWatch', () => {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)
|
).render()
|
||||||
|
|
||||||
// Mount
|
|
||||||
const instance = mount()
|
|
||||||
const { change, changeRender } = instance.setupState as any
|
const { change, changeRender } = instance.setupState as any
|
||||||
|
|
||||||
expect(calls).toEqual(['pre 0', 'sync 0', 'renderEffect 0'])
|
expect(calls).toEqual(['pre 0', 'sync 0', 'renderEffect 0'])
|
||||||
|
@ -164,7 +143,7 @@ describe('renderWatch', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
test('errors should include the execution location with beforeUpdate hook', async () => {
|
test('errors should include the execution location with beforeUpdate hook', async () => {
|
||||||
const mount = createDemo(
|
const { instance } = createDemo(
|
||||||
// setup
|
// setup
|
||||||
() => {
|
() => {
|
||||||
const source = ref()
|
const source = ref()
|
||||||
|
@ -180,9 +159,7 @@ describe('renderWatch', () => {
|
||||||
ctx.source
|
ctx.source
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
)
|
).render()
|
||||||
|
|
||||||
const instance = mount()
|
|
||||||
const { update } = instance.setupState as any
|
const { update } = instance.setupState as any
|
||||||
await expect(async () => {
|
await expect(async () => {
|
||||||
update()
|
update()
|
||||||
|
@ -195,7 +172,7 @@ describe('renderWatch', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
test('errors should include the execution location with updated hook', async () => {
|
test('errors should include the execution location with updated hook', async () => {
|
||||||
const mount = createDemo(
|
const { instance } = createDemo(
|
||||||
// setup
|
// setup
|
||||||
() => {
|
() => {
|
||||||
const source = ref(0)
|
const source = ref(0)
|
||||||
|
@ -211,9 +188,8 @@ describe('renderWatch', () => {
|
||||||
ctx.source
|
ctx.source
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
)
|
).render()
|
||||||
|
|
||||||
const instance = mount()
|
|
||||||
const { update } = instance.setupState as any
|
const { update } = instance.setupState as any
|
||||||
await expect(async () => {
|
await expect(async () => {
|
||||||
update()
|
update()
|
||||||
|
|
|
@ -1,23 +1,12 @@
|
||||||
import { children, on, render, template, vShow, withDirectives } from '../src'
|
import { children, on, template, vShow, withDirectives } from '../src'
|
||||||
import { defineComponent, nextTick, ref } from 'vue'
|
import { nextTick, ref } from 'vue'
|
||||||
import { afterEach, beforeEach, describe, expect, test } from 'vitest'
|
import { describe, expect, test } from 'vitest'
|
||||||
|
import { makeRender } from './_utils'
|
||||||
|
|
||||||
let host: HTMLElement
|
const define = makeRender()
|
||||||
|
|
||||||
const initHost = () => {
|
|
||||||
host = document.createElement('div')
|
|
||||||
host.setAttribute('id', 'host')
|
|
||||||
document.body.appendChild(host)
|
|
||||||
}
|
|
||||||
beforeEach(() => {
|
|
||||||
initHost()
|
|
||||||
})
|
|
||||||
afterEach(() => {
|
|
||||||
host.remove()
|
|
||||||
})
|
|
||||||
const createDemo = (defaultValue: boolean) =>
|
const createDemo = (defaultValue: boolean) =>
|
||||||
defineComponent({
|
define(() => {
|
||||||
setup() {
|
|
||||||
const visible = ref(defaultValue)
|
const visible = ref(defaultValue)
|
||||||
function handleClick() {
|
function handleClick() {
|
||||||
visible.value = !visible.value
|
visible.value = !visible.value
|
||||||
|
@ -31,12 +20,10 @@ const createDemo = (defaultValue: boolean) =>
|
||||||
withDirectives(n2, [[vShow, () => visible.value]])
|
withDirectives(n2, [[vShow, () => visible.value]])
|
||||||
on(n1 as HTMLElement, 'click', () => handleClick)
|
on(n1 as HTMLElement, 'click', () => handleClick)
|
||||||
return n0
|
return n0
|
||||||
},
|
|
||||||
})
|
})
|
||||||
describe('directive: v-show', () => {
|
describe('directive: v-show', () => {
|
||||||
test('basic', async () => {
|
test('basic', async () => {
|
||||||
const demo = createDemo(true)
|
const { host } = createDemo(true).render()
|
||||||
render(demo as any, {}, '#host')
|
|
||||||
const btn = host.querySelector('button')
|
const btn = host.querySelector('button')
|
||||||
expect(host.innerHTML).toBe('<button>toggle</button><h1>hello world</h1>')
|
expect(host.innerHTML).toBe('<button>toggle</button><h1>hello world</h1>')
|
||||||
btn?.click()
|
btn?.click()
|
||||||
|
@ -46,8 +33,7 @@ describe('directive: v-show', () => {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
test('should hide content when default value is false', async () => {
|
test('should hide content when default value is false', async () => {
|
||||||
const demo = createDemo(false)
|
const { host } = createDemo(false).render()
|
||||||
render(demo as any, {}, '#host')
|
|
||||||
const btn = host.querySelector('button')
|
const btn = host.querySelector('button')
|
||||||
const h1 = host.querySelector('h1')
|
const h1 = host.querySelector('h1')
|
||||||
expect(h1?.style.display).toBe('none')
|
expect(h1?.style.display).toBe('none')
|
||||||
|
|
|
@ -16,7 +16,7 @@ interface ForBlock extends Fragment {
|
||||||
export const createFor = (
|
export const createFor = (
|
||||||
src: () => any[] | Record<string, string> | Set<any> | Map<any, any>,
|
src: () => any[] | Record<string, string> | Set<any> | Map<any, any>,
|
||||||
renderItem: (block: ForBlock) => Block,
|
renderItem: (block: ForBlock) => Block,
|
||||||
getKey: ((item: any, index: number) => any) | null,
|
getKey?: (item: any, index: number) => any,
|
||||||
getMemo?: (item: any) => any[],
|
getMemo?: (item: any) => any[],
|
||||||
hydrationNode?: Node,
|
hydrationNode?: Node,
|
||||||
): Fragment => {
|
): Fragment => {
|
||||||
|
|
|
@ -39,7 +39,14 @@ export {
|
||||||
} from '@vue/reactivity'
|
} from '@vue/reactivity'
|
||||||
|
|
||||||
export { nextTick } from './scheduler'
|
export { nextTick } from './scheduler'
|
||||||
export { getCurrentInstance, type ComponentInternalInstance } from './component'
|
export {
|
||||||
|
getCurrentInstance,
|
||||||
|
type ComponentInternalInstance,
|
||||||
|
type Component,
|
||||||
|
type ObjectComponent,
|
||||||
|
type FunctionalComponent,
|
||||||
|
type SetupFn,
|
||||||
|
} from './component'
|
||||||
export * from './render'
|
export * from './render'
|
||||||
export * from './renderWatch'
|
export * from './renderWatch'
|
||||||
export * from './template'
|
export * from './template'
|
||||||
|
|
Loading…
Reference in New Issue