+++ /dev/null
-import {
- h,
- ref,
- render,
- nodeOps,
- nextTick,
- defineComponent
-} from '@vue/runtime-test'
-
-describe('renderer: component', () => {
- test.todo('should work')
-
- test.todo('shouldUpdateComponent')
-
- test.todo('componentProxy')
-
- describe('componentProps', () => {
- test.todo('should work')
-
- test('should convert empty booleans to true', () => {
- let b1: any, b2: any, b3: any
-
- const Comp = defineComponent({
- props: {
- b1: Boolean,
- b2: [Boolean, String],
- b3: [String, Boolean]
- },
- setup(props) {
- ;({ b1, b2, b3 } = props)
- return () => ''
- }
- })
-
- render(
- h(Comp, <any>{ b1: '', b2: '', b3: '' }),
- nodeOps.createElement('div')
- )
-
- expect(b1).toBe(true)
- expect(b2).toBe(true)
- expect(b3).toBe('')
- })
- })
-
- describe('slots', () => {
- test('should respect $stable flag', async () => {
- const flag1 = ref(1)
- const flag2 = ref(2)
- const spy = jest.fn()
-
- const Child = () => {
- spy()
- return 'child'
- }
-
- const App = {
- setup() {
- return () => [
- flag1.value,
- h(
- Child,
- { n: flag2.value },
- {
- foo: () => 'foo',
- $stable: true
- }
- )
- ]
- }
- }
-
- render(h(App), nodeOps.createElement('div'))
- expect(spy).toHaveBeenCalledTimes(1)
-
- // parent re-render, props didn't change, slots are stable
- // -> child should not update
- flag1.value++
- await nextTick()
- expect(spy).toHaveBeenCalledTimes(1)
-
- // parent re-render, props changed
- // -> child should update
- flag2.value++
- await nextTick()
- expect(spy).toHaveBeenCalledTimes(2)
- })
- })
-
- test('emit', async () => {
- let noMatchEmitResult: any
- let singleEmitResult: any
- let multiEmitResult: any
-
- const Child = defineComponent({
- setup(_, { emit }) {
- noMatchEmitResult = emit('foo')
- singleEmitResult = emit('bar')
- multiEmitResult = emit('baz')
- return () => h('div')
- }
- })
-
- const App = {
- setup() {
- return () =>
- h(Child, {
- // emit triggering single handler
- onBar: () => 1,
- // emit triggering multiple handlers
- onBaz: [() => Promise.resolve(2), () => Promise.resolve(3)]
- })
- }
- }
-
- render(h(App), nodeOps.createElement('div'))
-
- // assert return values from emit
- expect(noMatchEmitResult).toMatchObject([])
- expect(singleEmitResult).toMatchObject([1])
- expect(await Promise.all(multiEmitResult)).toMatchObject([2, 3])
- })
-
- // for v-model:foo-bar usage in DOM templates
- test('emit update:xxx events should trigger kebab-case equivalent', () => {
- const Child = defineComponent({
- setup(_, { emit }) {
- emit('update:fooBar', 1)
- return () => h('div')
- }
- })
-
- const handler = jest.fn()
- const App = {
- setup() {
- return () =>
- h(Child, {
- 'onUpdate:foo-bar': handler
- })
- }
- }
-
- render(h(App), nodeOps.createElement('div'))
- expect(handler).toHaveBeenCalled()
- })
-})
import { render, defineComponent, h, nodeOps } from '@vue/runtime-test'
import { isEmitListener } from '../src/componentEmits'
-describe('emits option', () => {
+describe('component: emit', () => {
mockWarn()
test('trigger both raw event and capitalize handlers', () => {
expect(onBar).toHaveBeenCalled()
})
+ // for v-model:foo-bar usage in DOM templates
test('trigger hyphendated events for update:xxx events', () => {
const Foo = defineComponent({
render() {},
expect(barSpy).toHaveBeenCalled()
})
+ test('should trigger array of listeners', async () => {
+ const Child = defineComponent({
+ setup(_, { emit }) {
+ emit('foo', 1)
+ return () => h('div')
+ }
+ })
+
+ const fn1 = jest.fn()
+ const fn2 = jest.fn()
+
+ const App = {
+ setup() {
+ return () =>
+ h(Child, {
+ onFoo: [fn1, fn2]
+ })
+ }
+ }
+
+ render(h(App), nodeOps.createElement('div'))
+ expect(fn1).toHaveBeenCalledTimes(1)
+ expect(fn1).toHaveBeenCalledWith(1)
+ expect(fn2).toHaveBeenCalledTimes(1)
+ expect(fn1).toHaveBeenCalledWith(1)
+ })
+
test('warning for undeclared event (array)', () => {
const Foo = defineComponent({
emits: ['foo'],
--- /dev/null
+import { ref, render, h, nodeOps, nextTick } from '@vue/runtime-test'
+
+describe('component: slots', () => {
+ // TODO more tests for slots normalization etc.
+
+ test('should respect $stable flag', async () => {
+ const flag1 = ref(1)
+ const flag2 = ref(2)
+ const spy = jest.fn()
+
+ const Child = () => {
+ spy()
+ return 'child'
+ }
+
+ const App = {
+ setup() {
+ return () => [
+ flag1.value,
+ h(
+ Child,
+ { n: flag2.value },
+ {
+ foo: () => 'foo',
+ $stable: true
+ }
+ )
+ ]
+ }
+ }
+
+ render(h(App), nodeOps.createElement('div'))
+ expect(spy).toHaveBeenCalledTimes(1)
+
+ // parent re-render, props didn't change, slots are stable
+ // -> child should not update
+ flag1.value++
+ await nextTick()
+ expect(spy).toHaveBeenCalledTimes(1)
+
+ // parent re-render, props changed
+ // -> child should update
+ flag2.value++
+ await nextTick()
+ expect(spy).toHaveBeenCalledTimes(2)
+ })
+})
}
}
- let res: any
const Child = {
+ props: ['onFoo'],
setup(props: any, { emit }: any) {
- res = emit('foo')
+ emit('foo')
return () => null
}
}
render(h(Comp), nodeOps.createElement('div'))
-
- try {
- await Promise.all(res)
- } catch (e) {
- expect(e).toBe(err)
- }
+ await nextTick()
expect(fn).toHaveBeenCalledWith(err, 'component event handler')
})
const err = new Error('foo')
const fn = jest.fn()
+ const res: Promise<any>[] = []
+ const createAsyncHandler = (p: Promise<any>) => () => {
+ res.push(p)
+ return p
+ }
+
const Comp = {
setup() {
onErrorCaptured((err, instance, info) => {
})
return () =>
h(Child, {
- onFoo: [() => Promise.reject(err), () => Promise.resolve(1)]
+ onFoo: [
+ createAsyncHandler(Promise.reject(err)),
+ createAsyncHandler(Promise.resolve(1))
+ ]
})
}
}
- let res: any
const Child = {
setup(props: any, { emit }: any) {
- res = emit('foo')
+ emit('foo')
return () => null
}
}
Options = ObjectEmitsOptions,
Event extends keyof Options = keyof Options
> = Options extends any[]
- ? (event: Options[0], ...args: any[]) => unknown[]
+ ? (event: Options[0], ...args: any[]) => void
: UnionToIntersection<
{
[key in Event]: Options[key] extends ((...args: infer Args) => any)
- ? (event: key, ...args: Args) => unknown[]
- : (event: key, ...args: any[]) => unknown[]
+ ? (event: key, ...args: Args) => void
+ : (event: key, ...args: any[]) => void
}[Event]
>
instance: ComponentInternalInstance,
event: string,
...args: any[]
-): any[] {
+) {
const props = instance.vnode.props || EMPTY_OBJ
if (__DEV__) {
handler = props[`on${event}`] || props[`on${capitalize(event)}`]
}
if (handler) {
- const res = callWithAsyncErrorHandling(
+ callWithAsyncErrorHandling(
handler,
instance,
ErrorCodes.COMPONENT_EVENT_HANDLER,
args
)
- return isArray(res) ? res : [res]
- } else {
- return []
}
}