Skip to content

Commit

Permalink
Merge pull request #74 from cexbrayat/fix/props-type
Browse files Browse the repository at this point in the history
feat: properly type mount with props
  • Loading branch information
lmiller1990 authored Apr 20, 2020
2 parents 4fefe74 + ef173f7 commit 140b72b
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 16 deletions.
46 changes: 37 additions & 9 deletions src/mount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ import {
Directive,
Component,
reactive,
ComponentPublicInstance
ComponentPublicInstance,
ComponentOptionsWithObjectProps,
ComponentOptionsWithArrayProps,
ComponentOptionsWithoutProps,
ExtractPropTypes
} from 'vue'

import { createWrapper, VueWrapper } from './vue-wrapper'
Expand All @@ -25,9 +29,9 @@ import { stubComponents } from './stubs'

type Slot = VNode | string | { render: Function }

interface MountingOptions {
interface MountingOptions<Props> {
data?: () => Record<string, unknown>
props?: Record<string, any>
props?: Props
slots?: {
default?: Slot
[key: string]: Slot
Expand All @@ -45,17 +49,41 @@ interface MountingOptions {
stubs?: Record<string, any>
}

export function mount<TestedComponent extends ComponentPublicInstance>(
// Component declared with defineComponent
export function mount<
TestedComponent extends ComponentPublicInstance,
PublicProps extends TestedComponent['$props']
>(
originalComponent: new () => TestedComponent,
options?: MountingOptions
options?: MountingOptions<PublicProps>
): VueWrapper<TestedComponent>
export function mount(
originalComponent: Component,
options?: MountingOptions
// Component declared with { props: { ... } }
export function mount<
TestedComponent extends ComponentOptionsWithObjectProps,
PublicProps extends ExtractPropTypes<TestedComponent['props']>
>(
originalComponent: TestedComponent,
options?: MountingOptions<PublicProps>
): VueWrapper<any>
// Component declared with { props: [] }
export function mount<
TestedComponent extends ComponentOptionsWithArrayProps,
PublicProps extends Record<string, any>
>(
originalComponent: TestedComponent,
options?: MountingOptions<PublicProps>
): VueWrapper<any>
// Component declared with no props
export function mount<
TestedComponent extends ComponentOptionsWithoutProps,
PublicProps extends Record<string, any>
>(
originalComponent: TestedComponent,
options?: MountingOptions<PublicProps>
): VueWrapper<any>
export function mount(
originalComponent: any,
options?: MountingOptions
options?: MountingOptions<any>
): VueWrapper<any> {
const component = { ...originalComponent }

Expand Down
78 changes: 71 additions & 7 deletions test-dts/index.d-test.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,87 @@
import { expectType } from 'tsd'
import { expectError, expectType } from 'tsd'
import { defineComponent } from 'vue'
import { mount } from '../src'

const App = defineComponent({
const AppWithDefine = defineComponent({
props: {
a: String
a: {
type: String,
required: true
}
},
template: ''
})

let wrapper = mount(App)
// accept props
let wrapper = mount(AppWithDefine, {
props: { a: 'Hello' }
})
// vm is properly typed
expectType<string>(wrapper.vm.a)

const AppWithoutDefine = {
// can receive extra props
mount(AppWithDefine, {
props: { a: 'Hello', b: 2 }
})

// wrong prop type should not compile
expectError(
mount(AppWithDefine, {
props: { a: 2 }
})
)

const AppWithProps = {
props: {
a: String
a: {
type: String,
required: true
}
},
template: ''
}

wrapper = mount(AppWithoutDefine)
// accept props
wrapper = mount(AppWithProps, {
props: { a: 'Hello' }
})
// vm is properly typed
expectType<string>(wrapper.vm.a)

// can receive extra props
mount(AppWithProps, {
props: { a: 'Hello', b: 2 }
})

// wrong prop type should not compile
expectError(
mount(AppWithProps, {
props: { a: 2 }
})
)

const AppWithArrayProps = {
props: ['a'],
template: ''
}

// accept props
wrapper = mount(AppWithArrayProps, {
props: { a: 'Hello' }
})
// vm is properly typed
expectType<string>(wrapper.vm.a)

// can receive extra props
mount(AppWithArrayProps, {
props: { a: 'Hello', b: 2 }
})

const AppWithoutProps = {
template: ''
}

// can receive extra props
wrapper = mount(AppWithoutProps, {
props: { b: 'Hello' }
})

0 comments on commit 140b72b

Please sign in to comment.