From b08cb494f7c1de10bbb8b4b77e2b39e57c201d77 Mon Sep 17 00:00:00 2001 From: Nandor Kraszlan Date: Wed, 10 Feb 2021 18:40:20 +0000 Subject: [PATCH] Started resolving typing issues --- src/config.ts | 6 +++--- src/createDomEvent.ts | 27 ++++++++++++++++++--------- src/domWrapper.ts | 4 ++-- src/stubs.ts | 2 +- src/types.ts | 2 ++ src/utils.ts | 6 +++--- src/utils/compileSlots.ts | 7 ++++--- src/utils/find.ts | 2 +- src/utils/isElementVisible.ts | 2 +- src/utils/matchName.ts | 4 ++-- src/vueWrapper.ts | 12 ++++++++---- tsconfig.json | 1 + 12 files changed, 46 insertions(+), 29 deletions(-) diff --git a/src/config.ts b/src/config.ts index b1a393c50..5f9f1be13 100644 --- a/src/config.ts +++ b/src/config.ts @@ -21,15 +21,15 @@ interface Plugin { class Pluggable> { installedPlugins: Plugin[] = [] - install(handler: (instance: Instance) => Record) + install(handler: (instance: Instance) => Record): void install( handler: (instance: Instance, options: O) => Record, options: O - ) + ): void install( handler: (instance: Instance, options?: O) => Record, options?: O - ) { + ): void { if (typeof handler !== 'function') { console.error('plugin.install must receive a function') handler = () => ({}) diff --git a/src/createDomEvent.ts b/src/createDomEvent.ts index 84c8428f6..f4955f8c8 100644 --- a/src/createDomEvent.ts +++ b/src/createDomEvent.ts @@ -1,3 +1,4 @@ +// @ts-expect-error No DefinitelyTyped package exists import eventTypes from 'dom-event-types' interface TriggerOptions { @@ -9,7 +10,7 @@ interface TriggerOptions { interface EventParams { eventType: string - modifiers: string[] + modifiers: KeyNameArray options?: TriggerOptions } @@ -21,8 +22,8 @@ const mouseKeyModifiers = ['left', 'middle', 'right'] /** * Groups modifiers into lists */ -function generateModifiers(modifiers: string[], isOnClick: boolean) { - const keyModifiers: string[] = [] +function generateModifiers(modifiers: KeyNameArray, isOnClick: boolean) { + const keyModifiers: KeyNameArray = [] const systemModifiers: string[] = [] for (let i = 0; i < modifiers.length; i++) { @@ -50,6 +51,7 @@ function generateModifiers(modifiers: string[], isOnClick: boolean) { } } +export type KeyNameArray = Array export const keyCodesByKeyName = { backspace: 8, tab: 9, @@ -98,10 +100,13 @@ function getEventProperties(eventParams: EventParams) { // convert `shift, ctrl` to `shiftKey, ctrlKey` // allows trigger('keydown.shift.ctrl.n') directly - const systemModifiersMeta = systemModifiers.reduce((all, key) => { - all[`${key}Key`] = true - return all - }, {}) + const systemModifiersMeta = systemModifiers.reduce( + (all: Record, key) => { + all[`${key}Key`] = true + return all + }, + {} + ) // get the keyCode for backwards compat const keyCode = @@ -148,8 +153,12 @@ function createDOMEvent(eventString: String, options?: TriggerOptions) { // split eventString like `keydown.ctrl.shift.c` into `keydown` and array of modifiers const [eventType, ...modifiers] = eventString.split('.') - const eventParams: EventParams = { eventType, modifiers, options } - const event: Event = createEvent(eventParams) + const eventParams: EventParams = { + eventType, + modifiers: modifiers as KeyNameArray, + options + } + const event: Event & TriggerOptions = createEvent(eventParams) const eventPrototype = Object.getPrototypeOf(event) // attach custom options to the event, like `relatedTarget` and so on. diff --git a/src/domWrapper.ts b/src/domWrapper.ts index 997b043f6..fee5b50d8 100644 --- a/src/domWrapper.ts +++ b/src/domWrapper.ts @@ -158,10 +158,10 @@ export class DOMWrapper { } element.selected = true - let parentElement = element.parentElement + let parentElement = element.parentElement! if (parentElement.tagName === 'OPTGROUP') { - parentElement = parentElement.parentElement + parentElement = parentElement.parentElement! } return new DOMWrapper(parentElement).trigger('change') diff --git a/src/stubs.ts b/src/stubs.ts index 0eaaec848..eade6a397 100644 --- a/src/stubs.ts +++ b/src/stubs.ts @@ -17,7 +17,7 @@ import { matchName } from './utils/matchName' import { ComponentInternalInstance } from '@vue/runtime-core' interface StubOptions { - name?: string + name: string props?: any propsDeclaration?: any } diff --git a/src/types.ts b/src/types.ts index ce94a66e5..afd878a3a 100644 --- a/src/types.ts +++ b/src/types.ts @@ -141,3 +141,5 @@ export type GlobalMountOptions = { */ renderStubDefaultSlot?: boolean } + +export type VueElement = Element & { __vue_app__?: any } diff --git a/src/utils.ts b/src/utils.ts index 13e3737df..ea8f52f86 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -42,8 +42,8 @@ export const mergeDeep = ( target: Record, source: Record ) => { - const isObject = (obj: unknown): obj is Object => - obj && typeof obj === 'object' + const isObject = (obj: unknown): obj is Record => + !!obj && typeof obj === 'object' if (!isObject(target) || !isObject(source)) { return source @@ -101,6 +101,6 @@ export function textContent(element: Element): string { // we check if the element is a comment first // to return an empty string in that case, instead of the comment content return element.nodeType !== Node.COMMENT_NODE - ? element.textContent?.trim() + ? element.textContent?.trim() ?? '' : '' } diff --git a/src/utils/compileSlots.ts b/src/utils/compileSlots.ts index f0f12a6d7..35fc6d7fc 100644 --- a/src/utils/compileSlots.ts +++ b/src/utils/compileSlots.ts @@ -1,5 +1,6 @@ import { compile } from '@vue/compiler-dom' import * as vue from 'vue' +import type { SetupContext } from 'vue' export function processSlot(source = '', Vue = vue) { let template = source.trim() @@ -25,14 +26,14 @@ export function processSlot(source = '', Vue = vue) { components: { SlotWrapper: { inheritAttrs: false, - setup(_, { slots, attrs }) { + setup(_: Record, ctx: SetupContext) { return () => { - const names = Object.keys(slots) + const names = Object.keys(ctx.slots) if (names.length === 0) { return [] } else { const slotName = names[0] - return slots[slotName](attrs) + return ctx.slots[slotName]!(ctx.attrs) } } } diff --git a/src/utils/find.ts b/src/utils/find.ts index 967cae38d..a60a7fc86 100644 --- a/src/utils/find.ts +++ b/src/utils/find.ts @@ -35,7 +35,7 @@ export function matches( return true } - let componentName + let componentName: string | undefined if ('name' in nodeType || 'displayName' in nodeType) { // match normal component definitions or functional components componentName = nodeType.name || nodeType.displayName diff --git a/src/utils/isElementVisible.ts b/src/utils/isElementVisible.ts index 4ca1ffb46..82ccb7abc 100644 --- a/src/utils/isElementVisible.ts +++ b/src/utils/isElementVisible.ts @@ -26,7 +26,7 @@ function isAttributeVisible(element: T) { ) } -export function isElementVisible(element: T) { +export function isElementVisible(element: T): boolean { return ( element.nodeName !== '#comment' && isStyleVisible(element) && diff --git a/src/utils/matchName.ts b/src/utils/matchName.ts index 824a73f34..fb5ec28de 100644 --- a/src/utils/matchName.ts +++ b/src/utils/matchName.ts @@ -1,11 +1,11 @@ import { camelize, capitalize } from './vueShared' -export function matchName(target: string, sourceName: string) { +export function matchName(target: string, sourceName: string): boolean { const camelized = camelize(target) const capitalized = capitalize(camelized) return ( - sourceName && + !!sourceName && (sourceName === target || sourceName === camelized || sourceName === capitalized || diff --git a/src/vueWrapper.ts b/src/vueWrapper.ts index ab8648606..732d1c0c4 100644 --- a/src/vueWrapper.ts +++ b/src/vueWrapper.ts @@ -3,7 +3,11 @@ import { ShapeFlags } from '@vue/shared' import { config } from './config' import { DOMWrapper } from './domWrapper' -import { FindAllComponentsSelector, FindComponentSelector } from './types' +import { + FindAllComponentsSelector, + FindComponentSelector, + VueElement +} from './types' import { createWrapperError } from './errorWrapper' import { TriggerOptions } from './createDomEvent' import { find, matches } from './utils/find' @@ -12,7 +16,7 @@ import { emitted } from './emit' export class VueWrapper { private componentVM: T - private rootVM: ComponentPublicInstance + private rootVM: ComponentPublicInstance | null private __app: App | null private __setProps: ((props: Record) => void) | undefined @@ -34,7 +38,7 @@ export class VueWrapper { return this.vm.$.subTree.shapeFlag === ShapeFlags.ARRAY_CHILDREN } - private get parentElement(): Element { + private get parentElement(): VueElement { return this.vm.$el.parentElement } @@ -148,7 +152,7 @@ export class VueWrapper { // eg: mount(Comp).findComponent(Comp) // this is the same as doing `wrapper.vm`, but we keep this behavior for back compat. if (matches(this.vm.$.vnode, selector)) { - return createWrapper(null, this.vm.$.vnode.component.proxy) + return createWrapper(null, this.vm.$.vnode.component?.proxy!) } return createWrapperError('VueWrapper') diff --git a/tsconfig.json b/tsconfig.json index 3a69a4a8f..7fec7a2df 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,6 +4,7 @@ "outDir": "dist", "module": "esnext", "lib": ["DOM", "ES2015", "ES2017"], + "strict": true, "moduleResolution": "node", "esModuleInterop": true, "experimentalDecorators": true,