Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@
"react",
"react-dom"
]
},
"patchedDependencies": {
"@vue/[email protected]": "patches/@[email protected]"
}
}
}
417 changes: 417 additions & 0 deletions patches/@[email protected]

Large diffs are not rendered by default.

10 changes: 8 additions & 2 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

89 changes: 70 additions & 19 deletions src/baseWrapper.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import { textContent } from './utils'
import type { TriggerOptions } from './createDomEvent'
import {
DefineComponentOptions,
DefineComponentFromOptions,
ComponentInjectOptions,
ComponentInstance,
ComponentInternalInstance,
ComponentOptions,
ComponentOptionsMixin,
ComponentPublicInstance,
ComputedOptions,
CreateComponentPublicInstance,
EmitsOptions,
FunctionalComponent,
MethodOptions,
SlotsType,
nextTick
} from 'vue'
import { createDOMEvent } from './createDomEvent'
Expand All @@ -19,6 +26,7 @@ import {
FindComponentSelector,
NameSelector,
RefSelector,
UnknownRenderedVue,
VueNode
} from './types'
import WrapperLike from './interfaces/wrapperLike'
Expand Down Expand Up @@ -108,16 +116,57 @@ export default abstract class BaseWrapper<ElementType extends Node>

// searching by string without specifying component results in WrapperLike object
findComponent<T extends never>(selector: string): WrapperLike

// Find Component Options aka plain object
findComponent<
Props,
RawBindings = any,
D = any,
C extends ComputedOptions = ComputedOptions,
M extends MethodOptions = MethodOptions
Props = {},
RawBindings = {},
D = {},
C extends ComputedOptions = {},
M extends MethodOptions = {},
Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
E extends EmitsOptions = {},
EE extends string = string,
I extends ComponentInjectOptions = {},
II extends string = string,
S extends SlotsType = {},
Options = {}
>(
selector: ComponentOptions<Props, RawBindings, D, C, M>
): VueWrapper<CreateComponentPublicInstance<Props, RawBindings, D, C, M>>
selector: DefineComponentOptions<
Props,
RawBindings,
D,
C,
M,
Mixin,
Extends,
E,
EE,
I,
II,
S,
Options
>
): VueWrapper<
Props extends DefinedComponent
? ComponentInstance<Props>
: DefineComponentFromOptions<
Props,
RawBindings,
D,
C,
M,
Mixin,
Extends,
E,
EE,
I,
II,
S,
Options
>
>
findComponent<T extends ComponentOptions>(
selector: string
): VueWrapper<
Expand All @@ -129,21 +178,23 @@ export default abstract class BaseWrapper<ElementType extends Node>
infer M
>
? CreateComponentPublicInstance<Props, RawBindings, D, C, M>
: VueWrapper<CreateComponentPublicInstance>
: CreateComponentPublicInstance
>
// searching for component created via defineComponent results in VueWrapper of proper type
findComponent<T extends DefinedComponent>(
selector: T | Exclude<FindComponentSelector, FunctionalComponent>
): VueWrapper<InstanceType<T>>
// searching for functional component results in DOMWrapper
findComponent<T extends FunctionalComponent>(selector: T): DOMWrapper<Node>
findComponent<T extends FunctionalComponent>(
selector: string
): DOMWrapper<Element>

// searching by name or ref always results in VueWrapper
findComponent<T extends never>(
selector: NameSelector | RefSelector
): VueWrapper
): VueWrapper<UnknownRenderedVue>
// searching for component created via defineComponent results in VueWrapper of proper type
findComponent<T extends DefinedComponent>(
selector: T | Exclude<FindComponentSelector, FunctionalComponent>
): VueWrapper<ComponentInstance<T>>

findComponent<T extends ComponentPublicInstance>(
selector: T | FindComponentSelector
): VueWrapper<T>
Expand Down Expand Up @@ -185,7 +236,7 @@ export default abstract class BaseWrapper<ElementType extends Node>
findAllComponents<T extends never>(selector: string): WrapperLike[]
findAllComponents<T extends DefinedComponent>(
selector: T | Exclude<FindAllComponentsSelector, FunctionalComponent>
): VueWrapper<InstanceType<T>>[]
): VueWrapper<ComponentInstance<T>>[]
findAllComponents<T extends FunctionalComponent>(
selector: T
): DOMWrapper<Node>[]
Expand Down Expand Up @@ -290,17 +341,17 @@ export default abstract class BaseWrapper<ElementType extends Node>
}

getComponent<T extends never>(selector: string): Omit<WrapperLike, 'exists'>
// searching by name or ref always results in VueWrapper
getComponent<T extends never>(
selector: NameSelector | RefSelector
): Omit<VueWrapper<UnknownRenderedVue>, 'exists'>
getComponent<T extends DefinedComponent>(
selector: T | Exclude<FindComponentSelector, FunctionalComponent>
): Omit<VueWrapper<InstanceType<T>>, 'exists'>
): Omit<VueWrapper<ComponentInstance<T>>, 'exists'>
// searching for functional component results in DOMWrapper
getComponent<T extends FunctionalComponent>(
selector: T | string
): Omit<DOMWrapper<Element>, 'exists'>
// searching by name or ref always results in VueWrapper
getComponent<T extends never>(
selector: NameSelector | RefSelector
): Omit<VueWrapper, 'exists'>
getComponent<T extends ComponentPublicInstance>(
selector: T | FindComponentSelector
): Omit<VueWrapper<T>, 'exists'>
Expand Down
12 changes: 8 additions & 4 deletions src/interfaces/wrapperLike.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ import {
RefSelector
} from '../types'
import { VueWrapper } from '../vueWrapper'
import { ComponentPublicInstance, FunctionalComponent } from 'vue'
import {
ComponentInstance,
ComponentPublicInstance,
FunctionalComponent
} from 'vue'
import type { DOMWrapper } from '../domWrapper'

export default interface WrapperLike {
Expand All @@ -35,7 +39,7 @@ export default interface WrapperLike {
findComponent<T extends never>(selector: string): WrapperLike
findComponent<T extends DefinedComponent>(
selector: T | Exclude<FindComponentSelector, FunctionalComponent>
): VueWrapper<InstanceType<T>>
): VueWrapper<ComponentInstance<T>>
findComponent<T extends FunctionalComponent>(
selector: T | string
): DOMWrapper<Element>
Expand All @@ -50,7 +54,7 @@ export default interface WrapperLike {
findAllComponents<T extends never>(selector: string): WrapperLike[]
findAllComponents<T extends DefinedComponent>(
selector: T | Exclude<FindAllComponentsSelector, FunctionalComponent>
): VueWrapper<InstanceType<T>>[]
): VueWrapper<ComponentInstance<T>>[]
findAllComponents<T extends FunctionalComponent>(
selector: string
): DOMWrapper<Element>[]
Expand Down Expand Up @@ -79,7 +83,7 @@ export default interface WrapperLike {
getComponent<T extends never>(selector: string): Omit<WrapperLike, 'exists'>
getComponent<T extends DefinedComponent>(
selector: T | Exclude<FindComponentSelector, FunctionalComponent>
): Omit<VueWrapper<InstanceType<T>>, 'exists'>
): Omit<VueWrapper<ComponentInstance<T>>, 'exists'>
// searching for functional component results in DOMWrapper
getComponent<T extends FunctionalComponent>(
selector: T | string
Expand Down
48 changes: 15 additions & 33 deletions src/mount.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,28 @@
import { ComponentPublicInstance, DefineComponent, VNode } from 'vue'
import type {
ComponentExposed,
ComponentProps,
import {
ComponentPublicInstance,
DefineComponent,
VNode,
ComponentInstance,
ComponentSlots
} from 'vue-component-type-helpers'
} from 'vue'
import { createInstance } from './createInstance'
import { MountingOptions } from './types'
import { trackInstance } from './utils/autoUnmount'
import { VueWrapper } from './vueWrapper'
import { createVueWrapper } from './wrapperFactory'

type ShimSlotReturnType<T> = T extends (...args: infer P) => any
? (...args: P) => any
: never
import { ComponentPropsWithDefaultOptional } from 'vue'

type WithArray<T> = T | T[]

type ComponentData<T> = T extends { data?(...args: any): infer D } ? D : {}

export type ComponentMountingOptions<
T,
P extends ComponentProps<T> = ComponentProps<T>
> = Omit<MountingOptions<P, ComponentData<T>>, 'slots'> & {
export type ComponentMountingOptions<T, P> = Omit<
MountingOptions<P, ComponentData<T>>,
'slots'
> & {
slots?: {
[K in keyof ComponentSlots<T>]: WithArray<
| ShimSlotReturnType<ComponentSlots<T>[K]>
| ComponentSlots<T>[K]
| string
| VNode
| (new () => any)
Expand All @@ -34,27 +32,11 @@ export type ComponentMountingOptions<
} & Record<string, unknown>

export function mount<
T,
C = T extends ((...args: any) => any) | (new (...args: any) => any)
? T
: T extends { props?: infer Props }
? DefineComponent<
Props extends Readonly<(infer PropNames)[]> | (infer PropNames)[]
? { [key in PropNames extends string ? PropNames : string]?: any }
: Props
>
: DefineComponent,
P extends ComponentProps<C> = ComponentProps<C>
T extends DefineComponent<any, any, any, any, any, any, any, any, any, any>
>(
originalComponent: T,
options?: ComponentMountingOptions<C, P>
): VueWrapper<
ComponentProps<C> & ComponentData<C> & ComponentExposed<C>,
ComponentPublicInstance<
ComponentProps<C>,
ComponentData<C> & ComponentExposed<C> & Omit<P, keyof ComponentProps<C>>
>
>
options?: ComponentMountingOptions<T, ComponentPropsWithDefaultOptional<T>>
): VueWrapper<ComponentInstance<T>>

// implementation
export function mount(
Expand Down
45 changes: 33 additions & 12 deletions src/renderToString.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,44 @@
import { renderToString as baseRenderToString } from '@vue/server-renderer'
import { DefineComponent } from 'vue'
import { ComponentProps, DefineComponent } from 'vue'
import { createInstance } from './createInstance'
import { ComponentMountingOptions } from './mount'
import { RenderMountingOptions } from './types'

// export function renderToString<
// T,
// C = T extends ((...args: any) => any) | (new (...args: any) => any)
// ? T
// : T extends { props?: infer Props }
// ? DefineComponent<
// Props extends Readonly<(infer PropNames)[]> | (infer PropNames)[]
// ? { [key in PropNames extends string ? PropNames : string]?: any }
// : Props
// >
// : DefineComponent
// >(
// originalComponent: T,
// options?: ComponentMountingOptions<C> &
// Pick<RenderMountingOptions<any>, 'attachTo'>
// ): Promise<string>

// defineComponent
export function renderToString<
T,
C = T extends ((...args: any) => any) | (new (...args: any) => any)
? T
: T extends { props?: infer Props }
? DefineComponent<
Props extends Readonly<(infer PropNames)[]> | (infer PropNames)[]
? { [key in PropNames extends string ? PropNames : string]?: any }
: Props
>
: DefineComponent
T extends DefineComponent<
PropsOrOptions,
any,
any,
any,
any,
any,
any,
any,
any,
any
>,
PropsOrOptions
>(
originalComponent: T,
options?: ComponentMountingOptions<C> &
options?: ComponentMountingOptions<T, ComponentProps<T>> &
Pick<RenderMountingOptions<any>, 'attachTo'>
): Promise<string>

Expand Down
7 changes: 6 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,4 +166,9 @@ export type VueNode<T extends Node = Node> = T & {

export type VueElement = VueNode<Element>

export type DefinedComponent = new (...args: any[]) => any
export type DefinedComponent = Component

export type UnknownRenderedVue = {
$props: Record<string, any>
$data: Record<string, any>
}
Loading