From: Evan You Date: Tue, 10 Dec 2024 11:37:55 +0000 (+0800) Subject: test(vapor): componentEmits X-Git-Tag: v3.6.0-alpha.1~16^2~168 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5648dda0c04a349f1a01c13485e4619ad313e1f9;p=thirdparty%2Fvuejs%2Fcore.git test(vapor): componentEmits --- diff --git a/packages/runtime-core/src/componentEmits.ts b/packages/runtime-core/src/componentEmits.ts index 20b14ee2f9..638514f715 100644 --- a/packages/runtime-core/src/componentEmits.ts +++ b/packages/runtime-core/src/componentEmits.ts @@ -175,7 +175,8 @@ export function baseEmit( // for v-model update:xxx events, apply modifiers on args // it's ok to use static get because modelModifiers can only be in the static // part of the props - const modifiers = isModelListener && getModelModifiers(props, event.slice(7)) + const modifiers = + isModelListener && getModelModifiers(props, event.slice(7), getter) if (modifiers) { if (modifiers.trim) { args = rawArgs.map(a => (isString(a) ? a.trim() : a)) @@ -230,7 +231,7 @@ export function baseEmit( ) } - const onceHandler = props[handlerName + `Once`] + const onceHandler = getter(props, handlerName + `Once`) if (onceHandler) { if (!instance.emitted) { instance.emitted = {} @@ -239,7 +240,7 @@ export function baseEmit( } instance.emitted[handlerName] = true callWithAsyncErrorHandling( - onceHandler, + onceHandler as Function | Function[], instance, ErrorCodes.COMPONENT_EVENT_HANDLER, args, @@ -256,7 +257,10 @@ export function baseEmit( } } -function defaultPropGetter(props: Record, key: string): unknown { +export function defaultPropGetter( + props: Record, + key: string, +): unknown { return props[key] } diff --git a/packages/runtime-core/src/helpers/useModel.ts b/packages/runtime-core/src/helpers/useModel.ts index c40938ead3..befe762774 100644 --- a/packages/runtime-core/src/helpers/useModel.ts +++ b/packages/runtime-core/src/helpers/useModel.ts @@ -5,6 +5,7 @@ import { getCurrentInstance } from '../component' import { warn } from '../warning' import type { NormalizedProps } from '../componentProps' import { watchSyncEffect } from '../apiWatch' +import { defaultPropGetter } from '../componentEmits' export function useModel< M extends PropertyKey, @@ -35,7 +36,7 @@ export function useModel( } const hyphenatedName = hyphenate(name) - const modifiers = getModelModifiers(props, camelizedName) + const modifiers = getModelModifiers(props, camelizedName, defaultPropGetter) const res = customRef((track, trigger) => { let localValue: any @@ -120,10 +121,11 @@ export function useModel( export const getModelModifiers = ( props: Record, modelName: string, + getter: (props: Record, key: string) => any, ): Record | undefined => { return modelName === 'modelValue' || modelName === 'model-value' - ? props.modelModifiers - : props[`${modelName}Modifiers`] || - props[`${camelize(modelName)}Modifiers`] || - props[`${hyphenate(modelName)}Modifiers`] + ? getter(props, 'modelModifiers') + : getter(props, `${modelName}Modifiers`) || + getter(props, `${camelize(modelName)}Modifiers`) || + getter(props, `${hyphenate(modelName)}Modifiers`) } diff --git a/packages/runtime-vapor/__tests__/componentAttrs.spec.ts b/packages/runtime-vapor/__tests__/componentAttrs.spec.ts index fccc241376..99544d50dc 100644 --- a/packages/runtime-vapor/__tests__/componentAttrs.spec.ts +++ b/packages/runtime-vapor/__tests__/componentAttrs.spec.ts @@ -4,6 +4,8 @@ import { makeRender } from './_utils' const define = makeRender() +// TODO: port more tests from rendererAttrsFallthrough.spec.ts + describe('attribute fallthrough', () => { it('should allow attrs to fallthrough', async () => { const t0 = template('
') diff --git a/packages/runtime-vapor/__tests__/componentEmits.spec.ts b/packages/runtime-vapor/__tests__/componentEmits.spec.ts index 5ab6f53108..7c3bfe69ed 100644 --- a/packages/runtime-vapor/__tests__/componentEmits.spec.ts +++ b/packages/runtime-vapor/__tests__/componentEmits.spec.ts @@ -3,25 +3,25 @@ // Note: emits and listener fallthrough is tested in // ./rendererAttrsFallthrough.spec.ts. -import { toHandlers } from '@vue/runtime-core' import { - createComponent, - defineComponent, + isEmitListener, nextTick, onBeforeUnmount, -} from '../src' -import { isEmitListener } from '../src/componentEmits' + toHandlers, +} from '@vue/runtime-dom' +import { createComponent, defineVaporComponent } from '../src' import { makeRender } from './_utils' const define = makeRender() -describe.todo('component: emit', () => { +describe('component: emit', () => { test('trigger handlers', () => { const { render } = define({ setup(_, { emit }) { emit('foo') emit('bar') emit('!baz') + return [] }, }) const onFoo = vi.fn() @@ -44,16 +44,17 @@ describe.todo('component: emit', () => { emit('foo') emit('bar') emit('!baz') + return [] }, }) const onFoo = vi.fn() const onBar = vi.fn() const onBaz = vi.fn() - render(() => ({ - onfoo: onFoo, - onBar, - ['on!baz']: onBaz, - })) + render({ + onfoo: () => onFoo, + onBar: () => onBar, + ['on!baz']: () => onBaz, + }) expect(onFoo).not.toHaveBeenCalled() expect(onBar).toHaveBeenCalled() @@ -64,6 +65,7 @@ describe.todo('component: emit', () => { const { render } = define({ setup(_, { emit }) { emit('test-event') + return [] }, }) @@ -76,6 +78,7 @@ describe.todo('component: emit', () => { const { render } = define({ setup(_, { emit }) { emit('test-event') + return [] }, }) @@ -90,6 +93,7 @@ describe.todo('component: emit', () => { setup(_, { emit }) { emit('test-event') emit('testEvent') + return [] }, }) @@ -111,6 +115,7 @@ describe.todo('component: emit', () => { setup(_, { emit }) { emit('update:fooProp') emit('update:barProp') + return [] }, }) @@ -129,6 +134,7 @@ describe.todo('component: emit', () => { const { render } = define({ setup(_, { emit }) { emit('foo', 1) + return [] }, }) @@ -148,6 +154,7 @@ describe.todo('component: emit', () => { setup(_, { emit }) { emit('bar') + return [] }, }) render() @@ -164,6 +171,7 @@ describe.todo('component: emit', () => { setup(_, { emit }) { emit('bar') + return [] }, }) render() @@ -179,6 +187,7 @@ describe.todo('component: emit', () => { setup(_, { emit }) { emit('foo') + return [] }, }).render() expect( @@ -190,15 +199,6 @@ describe.todo('component: emit', () => { // TODO: warning validator }) - // NOTE: not supported mixins - // test.todo('merging from mixins', () => {}) - - // #2651 - // test.todo( - // 'should not attach normalized object when mixins do not contain emits', - // () => {}, - // ) - test('.once', () => { const { render } = define({ emits: { @@ -210,6 +210,7 @@ describe.todo('component: emit', () => { emit('foo') emit('bar') emit('bar') + return [] }, }) const fn = vi.fn() @@ -230,6 +231,7 @@ describe.todo('component: emit', () => { setup(_, { emit }) { emit('foo') emit('foo') + return [] }, }) const onFoo = vi.fn() @@ -247,6 +249,7 @@ describe.todo('component: emit', () => { setup(_, { emit }) { emit('update:modelValue', '1') emit('update:foo', '2') + return [] }, }) const fn1 = vi.fn() @@ -270,6 +273,7 @@ describe.todo('component: emit', () => { setup(_, { emit }) { emit('update:modelValue', ' one ') emit('update:foo', ' two ') + return [] }, }) const fn1 = vi.fn() @@ -305,6 +309,7 @@ describe.todo('component: emit', () => { setup(_, { emit }) { emit('update:modelValue', ' +01.2 ') emit('update:foo', ' 1 ') + return [] }, }) const fn1 = vi.fn() @@ -339,6 +344,7 @@ describe.todo('component: emit', () => { const { render } = define({ setup(_, { emit }) { emit('update:modelValue', ' foo ', { bar: ' bar ' }) + return [] }, }) const fn = vi.fn() @@ -389,13 +395,14 @@ describe.todo('component: emit', () => { test('does not emit after unmount', async () => { const fn = vi.fn() - const Foo = defineComponent({ + const Foo = defineVaporComponent({ emits: ['closing'], setup(_, { emit }) { onBeforeUnmount(async () => { await nextTick() emit('closing', true) }) + return [] }, }) diff --git a/packages/runtime-vapor/__tests__/componentExpose.spec.ts b/packages/runtime-vapor/__tests__/componentExpose.spec.ts deleted file mode 100644 index 47415b749d..0000000000 --- a/packages/runtime-vapor/__tests__/componentExpose.spec.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { describe, expect } from 'vitest' -import { makeRender } from './_utils' -import { type Ref, ref } from '@vue/reactivity' - -const define = makeRender() - -describe.todo('component expose', () => { - test('should work', async () => { - const expxosedObj = { foo: 1 } - const { render } = define({ - setup(_, { expose }) { - expose(expxosedObj) - }, - }) - const { instance } = render() - expect(instance?.exposed).toEqual(expxosedObj) - }) - - test('should warn when called multiple times', async () => { - const { render } = define({ - setup(_, { expose }) { - expose() - expose() - }, - }) - render() - expect( - 'expose() should be called only once per setup().', - ).toHaveBeenWarned() - }) - - test('should warn when passed non-object', async () => { - const exposedRef = ref([1, 2, 3]) - const { render } = define({ - setup(_, { expose }) { - expose(exposedRef.value) - }, - }) - render() - expect( - 'expose() should be passed a plain object, received array.', - ).toHaveBeenWarned() - exposedRef.value = ref(1) - render() - expect( - 'expose() should be passed a plain object, received ref.', - ).toHaveBeenWarned() - }) -})