diff --git a/src/mount.ts b/src/mount.ts index f19a409231..d784a64cf2 100644 --- a/src/mount.ts +++ b/src/mount.ts @@ -50,13 +50,34 @@ import { trackInstance } from './utils/autoUnmount' // NOTE this should come from `vue` type PublicProps = VNodeProps & AllowedComponentProps & ComponentCustomProps +const MOUNT_OPTIONS: Array> = [ + 'attachTo', + 'attrs', + 'data', + 'props', + 'slots', + 'global', + 'shallow' +] + +function getInstanceOptions( + options: MountingOptions & Record +): Record { + const resultOptions = { ...options } + for (const key of Object.keys(options)) { + if (MOUNT_OPTIONS.includes(key as keyof MountingOptions)) { + delete resultOptions[key] + } + } + return resultOptions +} // Class component - no props export function mount( originalComponent: { new (...args: any[]): V registerHooks(keys: string[]): void }, - options?: MountingOptions + options?: MountingOptions & Record ): VueWrapper> // Class component - props @@ -66,13 +87,13 @@ export function mount( props(Props: P): any registerHooks(keys: string[]): void }, - options?: MountingOptions

+ options?: MountingOptions

& Record ): VueWrapper> // Functional component with emits export function mount( originalComponent: FunctionalComponent, - options?: MountingOptions + options?: MountingOptions & Record ): VueWrapper> // Component declared with defineComponent @@ -107,7 +128,8 @@ export function mount< options?: MountingOptions< Partial & Omit, D - > + > & + Record ): VueWrapper< InstanceType< DefineComponent< @@ -153,7 +175,8 @@ export function mount< options?: MountingOptions ): VueWrapper< ComponentPublicInstance -> +> & + Record // Component declared with { props: [] } export function mount< @@ -226,25 +249,28 @@ export function mount< // implementation export function mount( inputComponent: any, - options?: MountingOptions + options?: MountingOptions & Record ): VueWrapper { // normalise the incoming component let originalComponent = unwrapLegacyVueExtendComponent(inputComponent) let component: ConcreteComponent + const instanceOptions = getInstanceOptions(options ?? {}) if ( isFunctionalComponent(originalComponent) || isLegacyFunctionalComponent(originalComponent) ) { component = defineComponent({ + compatConfig: { MODE: 3, COMPONENT_FUNCTIONAL: true }, setup: (_, { attrs, slots }) => () => - h(originalComponent, attrs, slots) + h(originalComponent, attrs, slots), + ...instanceOptions }) addToDoNotStubComponents(originalComponent) } else if (isObjectComponent(originalComponent)) { - component = { ...originalComponent } + component = { ...originalComponent, ...instanceOptions } } else { component = originalComponent } diff --git a/tests/mountingOptions/options.spec.ts b/tests/mountingOptions/options.spec.ts new file mode 100644 index 0000000000..b03287cc55 --- /dev/null +++ b/tests/mountingOptions/options.spec.ts @@ -0,0 +1,13 @@ +import { defineComponent } from 'vue' +import { mount } from '../../src' + +describe('mounting options: other', () => { + it('passes other options as $options to component', () => { + const TestComponent = defineComponent({ template: '

test
' }) + const optionContent = {} + const wrapper = mount(TestComponent, { + someUnknownOption: optionContent + }) + expect(wrapper.vm.$options.someUnknownOption).toBe(optionContent) + }) +})