diff --git a/npm/vue/src/index.ts b/npm/vue/src/index.ts index e00871f66888..9a5778c57408 100644 --- a/npm/vue/src/index.ts +++ b/npm/vue/src/index.ts @@ -17,8 +17,9 @@ import type { ComponentPropsOptions, ComponentOptionsWithArrayProps, ComponentOptionsWithoutProps, + Prop, } from 'vue' -import type { MountingOptions, VueWrapper } from '@vue/test-utils' +import type { MountingOptions as VTUMountingOptions, VueWrapper } from '@vue/test-utils' import { injectStylesBeforeElement, StyleOptions, @@ -44,7 +45,7 @@ export { VueTestUtils } const DEFAULT_COMP_NAME = 'unknown' -type GlobalMountOptions = Required>['global'] +type GlobalMountOptions = Required>['global'] // when we mount a Vue component, we add it to the global Cypress object // so here we extend the global Cypress namespace and its Cypress interface @@ -58,7 +59,7 @@ declare global { } } -export type CyMountOptions = Omit, 'attachTo'> & { +type MountingOptions = Omit, 'attachTo'> & { log?: boolean /** * @deprecated use vue-test-utils `global` instead @@ -69,6 +70,8 @@ export type CyMountOptions = Omit, } } & Partial +export type CyMountOptions = MountingOptions + Cypress.on('run:start', () => { // `mount` is designed to work with component testing only. // it assumes ROOT_SELECTOR exists, which is not the case in e2e. @@ -89,38 +92,79 @@ Cypress.on('run:start', () => { }) /** - * the types for mount have been copied directly from the VTU mount - * https://github.com/vuejs/vue-test-utils-next/blob/master/src/mount.ts + * The types for mount have been copied directly from the VTU mount + * https://github.com/vuejs/vue-test-utils-next/blob/master/src/mount.ts. + * + * There isn't a good way to make them generic enough that we can extend them. + * + * In addition, we modify the types slightly. * - * If they are updated please copy and pase them again here. + * `MountOptions` are modifying, including some Cypress specific options like `styles`. + * The return type is different. Instead of VueWrapper, it's Cypress.Chainable>. */ +type PublicProps = VNodeProps & AllowedComponentProps & ComponentCustomProps + +type ComponentMountingOptions = T extends DefineComponent< + infer PropsOrPropOptions, + any, + infer D, + any, + any +> + ? MountingOptions< + Partial> & + Omit< + Readonly> & PublicProps, + keyof ExtractDefaultPropTypes + >, + D + > & + Record + : MountingOptions + +// Class component (without vue-class-component) - no props +export function mount( + originalComponent: { + new (...args: any[]): V + __vccOpts: any + }, + options?: MountingOptions & Record +): Cypress.Chainable>> -type PublicProps = VNodeProps & AllowedComponentProps & ComponentCustomProps; +// Class component (without vue-class-component) - props +export function mount( + originalComponent: { + new (...args: any[]): V + __vccOpts: any + defaultProps?: Record> | string[] + }, + options?: MountingOptions

& Record +): Cypress.Chainable>> // Class component - no props -export function mount( +export function mount( originalComponent: { new (...args: any[]): V registerHooks(keys: string[]): void }, - options?: MountingOptions -): Cypress.Chainable + options?: MountingOptions & Record +): Cypress.Chainable>> // Class component - props -export function mount( +export function mount( originalComponent: { new (...args: any[]): V props(Props: P): any registerHooks(keys: string[]): void }, - options?: CyMountOptions

-): Cypress.Chainable + options?: MountingOptions

& Record +): Cypress.Chainable>> // Functional component with emits -export function mount( +export function mount( originalComponent: FunctionalComponent, - options?: CyMountOptions -): Cypress.Chainable + options?: MountingOptions & Record +): Cypress.Chainable>> // Component declared with defineComponent export function mount< @@ -135,7 +179,7 @@ export function mount< EE extends string = string, PP = PublicProps, Props = Readonly>, - Defaults = ExtractDefaultPropTypes + Defaults extends {} = ExtractDefaultPropTypes >( component: DefineComponent< PropsOrPropOptions, @@ -151,17 +195,43 @@ export function mount< Props, Defaults >, - options?: CyMountOptions< + options?: MountingOptions< Partial & Omit, D + > & + Record +): Cypress.Chainable< + VueWrapper< + InstanceType< + DefineComponent< + PropsOrPropOptions, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + EE, + PP, + Props, + Defaults + > + > > -): Cypress.Chainable +> + +// component declared by vue-tsc ScriptSetup +export function mount>( + component: T, + options?: ComponentMountingOptions +): Cypress.Chainable>> // Component declared with no props export function mount< Props = {}, RawBindings = {}, - D = {}, + D extends {} = {}, C extends ComputedOptions = {}, M extends Record = {}, E extends EmitsOptions = Record, @@ -172,25 +242,31 @@ export function mount< componentOptions: ComponentOptionsWithoutProps< Props, RawBindings, - D + D, + C, + M, + E, + Mixin, + Extends, + EE >, - options?: CyMountOptions -): Cypress.Chainable + options?: MountingOptions +): Cypress.Chainable>> & Record // Component declared with { props: [] } export function mount< PropNames extends string, RawBindings, - D, + D extends {}, C extends ComputedOptions = {}, M extends Record = {}, E extends EmitsOptions = Record, Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, Extends extends ComponentOptionsMixin = ComponentOptionsMixin, EE extends string = string, - Props extends Readonly<{ [key in PropNames]?: any }> = Readonly< - { [key in PropNames]?: any } - > + Props extends Readonly<{ [key in PropNames]?: any }> = Readonly<{ + [key in PropNames]?: any + }> >( componentOptions: ComponentOptionsWithArrayProps< PropNames, @@ -204,8 +280,8 @@ export function mount< EE, Props >, - options?: CyMountOptions -): Cypress.Chainable + options?: MountingOptions +): Cypress.Chainable>> // Component declared with { props: { ... } } export function mount< @@ -213,7 +289,7 @@ export function mount< // as constant instead of boolean. PropsOptions extends Readonly, RawBindings, - D, + D extends {}, C extends ComputedOptions = {}, M extends Record = {}, E extends EmitsOptions = Record, @@ -232,14 +308,23 @@ export function mount< Extends, EE >, - options?: CyMountOptions & PublicProps, D> -): Cypress.Chainable + options?: MountingOptions & PublicProps, D> +): Cypress.Chainable< + VueWrapper< + ComponentPublicInstance< + ExtractPropTypes, + RawBindings, + D, + C, + M, + E, + VNodeProps & ExtractPropTypes + > + > +> // implementation -export function mount ( - componentOptions: any, - options: CyMountOptions = {}, -) { +export function mount (componentOptions: any, options: any) { // TODO: get the real displayName and props from VTU shallowMount const componentName = getComponentDisplayName(componentOptions) diff --git a/npm/vue/test-tsd/Slots.vue b/npm/vue/test-tsd/Slots.vue new file mode 100644 index 000000000000..e4c666f0a670 --- /dev/null +++ b/npm/vue/test-tsd/Slots.vue @@ -0,0 +1,15 @@ + + + diff --git a/npm/vue/test-tsd/mount-test.ts b/npm/vue/test-tsd/mount-test.ts index d787014f2203..f4ddecfa0f7d 100644 --- a/npm/vue/test-tsd/mount-test.ts +++ b/npm/vue/test-tsd/mount-test.ts @@ -1,4 +1,4 @@ -import { expectError, expectType } from './index' +import { expectType } from './index' import { mount, VueTestUtils } from '../dist' import * as VTU from '@vue/test-utils' import { defineComponent } from 'vue' diff --git a/npm/vue/test-tsd/test.ts b/npm/vue/test-tsd/test.ts new file mode 100644 index 000000000000..bf7f9d8e93a4 --- /dev/null +++ b/npm/vue/test-tsd/test.ts @@ -0,0 +1,4 @@ +import { mount } from '../dist' +import Slots from './Slots.vue' + +mount(Slots) diff --git a/yarn.lock b/yarn.lock index e2d3157c30a8..942b46c25e92 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7575,7 +7575,17 @@ estree-walker "^2.0.2" source-map "^0.6.1" -"@vue/compiler-dom@3.2.31", "@vue/compiler-dom@^3.2.6": +"@vue/compiler-core@3.2.39": + version "3.2.39" + resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.2.39.tgz#0d77e635f4bdb918326669155a2dc977c053943e" + integrity sha512-mf/36OWXqWn0wsC40nwRRGheR/qoID+lZXbIuLnr4/AngM0ov8Xvv8GHunC0rKRIkh60bTqydlqTeBo49rlbqw== + dependencies: + "@babel/parser" "^7.16.4" + "@vue/shared" "3.2.39" + estree-walker "^2.0.2" + source-map "^0.6.1" + +"@vue/compiler-dom@3.2.31": version "3.2.31" resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.2.31.tgz#b1b7dfad55c96c8cc2b919cd7eb5fd7e4ddbf00e" integrity sha512-60zIlFfzIDf3u91cqfqy9KhCKIJgPeqxgveH2L+87RcGU/alT6BRrk5JtUso0OibH3O7NXuNOQ0cDc9beT0wrg== @@ -7583,7 +7593,15 @@ "@vue/compiler-core" "3.2.31" "@vue/shared" "3.2.31" -"@vue/compiler-sfc@3.2.31", "@vue/compiler-sfc@^3.2.20", "@vue/compiler-sfc@^3.2.4": +"@vue/compiler-dom@3.2.39", "@vue/compiler-dom@^3.2.6": + version "3.2.39" + resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.2.39.tgz#bd69d35c1a48fe2cea4ab9e96d2a3a735d146fdf" + integrity sha512-HMFI25Be1C8vLEEv1hgEO1dWwG9QQ8LTTPmCkblVJY/O3OvWx6r1+zsox5mKPMGvqYEZa6l8j+xgOfUspgo7hw== + dependencies: + "@vue/compiler-core" "3.2.39" + "@vue/shared" "3.2.39" + +"@vue/compiler-sfc@3.2.31": version "3.2.31" resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.2.31.tgz#d02b29c3fe34d599a52c5ae1c6937b4d69f11c2f" integrity sha512-748adc9msSPGzXgibHiO6T7RWgfnDcVQD+VVwYgSsyyY8Ans64tALHZANrKtOzvkwznV/F4H7OAod/jIlp/dkQ== @@ -7599,6 +7617,22 @@ postcss "^8.1.10" source-map "^0.6.1" +"@vue/compiler-sfc@^3.2.20", "@vue/compiler-sfc@^3.2.4": + version "3.2.39" + resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.2.39.tgz#8fe29990f672805b7c5a2ecfa5b05e681c862ea2" + integrity sha512-fqAQgFs1/BxTUZkd0Vakn3teKUt//J3c420BgnYgEOoVdTwYpBTSXCMJ88GOBCylmUBbtquGPli9tVs7LzsWIA== + dependencies: + "@babel/parser" "^7.16.4" + "@vue/compiler-core" "3.2.39" + "@vue/compiler-dom" "3.2.39" + "@vue/compiler-ssr" "3.2.39" + "@vue/reactivity-transform" "3.2.39" + "@vue/shared" "3.2.39" + estree-walker "^2.0.2" + magic-string "^0.25.7" + postcss "^8.1.10" + source-map "^0.6.1" + "@vue/compiler-ssr@3.2.31": version "3.2.31" resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.2.31.tgz#4fa00f486c9c4580b40a4177871ebbd650ecb99c" @@ -7607,6 +7641,14 @@ "@vue/compiler-dom" "3.2.31" "@vue/shared" "3.2.31" +"@vue/compiler-ssr@3.2.39": + version "3.2.39" + resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.2.39.tgz#4f3bfb535cb98b764bee45e078700e03ccc60633" + integrity sha512-EoGCJ6lincKOZGW+0Ky4WOKsSmqL7hp1ZYgen8M7u/mlvvEQUaO9tKKOy7K43M9U2aA3tPv0TuYYQFrEbK2eFQ== + dependencies: + "@vue/compiler-dom" "3.2.39" + "@vue/shared" "3.2.39" + "@vue/devtools-api@^6.0.0-beta.13", "@vue/devtools-api@^6.0.0-beta.14", "@vue/devtools-api@^6.0.0-beta.19", "@vue/devtools-api@^6.0.0-beta.5": version "6.0.0-beta.19" resolved "https://registry.yarnpkg.com/@vue/devtools-api/-/devtools-api-6.0.0-beta.19.tgz#f8e88059daa424515992426a0c7ea5cde07e99bf" @@ -7623,13 +7665,31 @@ estree-walker "^2.0.2" magic-string "^0.25.7" -"@vue/reactivity@3.2.31", "@vue/reactivity@^3.2.6": +"@vue/reactivity-transform@3.2.39": + version "3.2.39" + resolved "https://registry.yarnpkg.com/@vue/reactivity-transform/-/reactivity-transform-3.2.39.tgz#da6ae6c8fd77791b9ae21976720d116591e1c4aa" + integrity sha512-HGuWu864zStiWs9wBC6JYOP1E00UjMdDWIG5W+FpUx28hV3uz9ODOKVNm/vdOy/Pvzg8+OcANxAVC85WFBbl3A== + dependencies: + "@babel/parser" "^7.16.4" + "@vue/compiler-core" "3.2.39" + "@vue/shared" "3.2.39" + estree-walker "^2.0.2" + magic-string "^0.25.7" + +"@vue/reactivity@3.2.31": version "3.2.31" resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.2.31.tgz#fc90aa2cdf695418b79e534783aca90d63a46bbd" integrity sha512-HVr0l211gbhpEKYr2hYe7hRsV91uIVGFYNHj73njbARVGHQvIojkImKMaZNDdoDZOIkMsBc9a1sMqR+WZwfSCw== dependencies: "@vue/shared" "3.2.31" +"@vue/reactivity@^3.2.6": + version "3.2.39" + resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.2.39.tgz#e6e3615fe2288d4232b104640ddabd0729a78c80" + integrity sha512-vlaYX2a3qMhIZfrw3Mtfd+BuU+TZmvDrPMa+6lpfzS9k/LnGxkSuf0fhkP0rMGfiOHPtyKoU9OJJJFGm92beVQ== + dependencies: + "@vue/shared" "3.2.39" + "@vue/runtime-core@3.2.31": version "3.2.31" resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.2.31.tgz#9d284c382f5f981b7a7b5971052a1dc4ef39ac7a" @@ -7655,11 +7715,16 @@ "@vue/compiler-ssr" "3.2.31" "@vue/shared" "3.2.31" -"@vue/shared@3.2.31", "@vue/shared@^3.2.6": +"@vue/shared@3.2.31": version "3.2.31" resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.31.tgz#c90de7126d833dcd3a4c7534d534be2fb41faa4e" integrity sha512-ymN2pj6zEjiKJZbrf98UM2pfDd6F2H7ksKw7NDt/ZZ1fh5Ei39X5tABugtT03ZRlWd9imccoK0hE8hpjpU7irQ== +"@vue/shared@3.2.39", "@vue/shared@^3.2.6": + version "3.2.39" + resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.39.tgz#302df167559a1a5156da162d8cc6760cef67f8e3" + integrity sha512-D3dl2ZB9qE6mTuWPk9RlhDeP1dgNRUKC3NJxji74A4yL8M2MwlhLKUC/49WHjrNzSPug58fWx/yFbaTzGAQSBw== + "@vue/test-utils@2.0.2": version "2.0.2" resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-2.0.2.tgz#0b5edd683366153d5bc5a91edc62f292118710eb"