From 9d3c2a6526f3d8751d29b2f9112ad2a3332bbf52 Mon Sep 17 00:00:00 2001 From: Nandor Kraszlan Date: Fri, 12 Feb 2021 18:29:11 +0000 Subject: [PATCH] chore: PR fixes --- src/createDomEvent.ts | 80 ++++++++++++++++------------- src/domWrapper.ts | 2 + src/emit.ts | 6 +-- src/mount.ts | 4 +- src/vueWrapper.ts | 17 +++--- tests/isVisible.spec.ts | 24 +++------ tests/mountingOptions/data.spec.ts | 9 ++-- tests/mountingOptions/mocks.spec.ts | 12 ++--- tests/setData.spec.ts | 5 +- tests/setProps.spec.ts | 5 +- tests/trigger.spec.ts | 5 +- tsconfig.json | 3 +- types/testing.d.ts | 7 +++ 13 files changed, 93 insertions(+), 86 deletions(-) create mode 100644 types/testing.d.ts diff --git a/src/createDomEvent.ts b/src/createDomEvent.ts index 8b04bec2e..e2b22ed56 100644 --- a/src/createDomEvent.ts +++ b/src/createDomEvent.ts @@ -1,5 +1,34 @@ -// @ts-ignore No DefinitelyTyped package exists +// @ts-ignore todo - No DefinitelyTyped package exists for this import eventTypes from 'dom-event-types' +import { Key } from 'readline' + +const keyCodesByKeyName = { + backspace: 8, + tab: 9, + enter: 13, + esc: 27, + space: 32, + pageup: 33, + pagedown: 34, + end: 35, + home: 36, + left: 37, + up: 38, + right: 39, + down: 40, + insert: 45, + delete: 46 +} as const + +// modifiers to keep an eye on +const ignorableKeyModifiers = ['stop', 'prevent', 'self', 'exact'] +const systemKeyModifiers = ['ctrl', 'shift', 'alt', 'meta'] as const +const mouseKeyModifiers = ['left', 'middle', 'right'] as const + +type KeyName = keyof typeof keyCodesByKeyName +type Modifier = + | typeof systemKeyModifiers[number] + | typeof mouseKeyModifiers[number] interface TriggerOptions { code?: String @@ -10,24 +39,19 @@ interface TriggerOptions { interface EventParams { eventType: string - modifiers: KeyNameArray + modifiers: KeyName[] options?: TriggerOptions } -// modifiers to keep an eye on -const ignorableKeyModifiers = ['stop', 'prevent', 'self', 'exact'] -const systemKeyModifiers = ['ctrl', 'shift', 'alt', 'meta'] -const mouseKeyModifiers = ['left', 'middle', 'right'] - /** * Groups modifiers into lists */ -function generateModifiers(modifiers: KeyNameArray, isOnClick: boolean) { - const keyModifiers: KeyNameArray = [] - const systemModifiers: string[] = [] +function generateModifiers(modifiers: KeyName[], isOnClick: boolean) { + const keyModifiers: KeyName[] = [] + const systemModifiers: Modifier[] = [] for (let i = 0; i < modifiers.length; i++) { - const modifier = modifiers[i] + const modifier: KeyName | Modifier = modifiers[i] // addEventListener() options, e.g. .passive & .capture, that we dont need to handle if (ignorableKeyModifiers.includes(modifier)) { @@ -36,10 +60,15 @@ function generateModifiers(modifiers: KeyNameArray, isOnClick: boolean) { // modifiers that require special conversion // if passed a left/right key modifier with onClick, add it here as well. if ( - systemKeyModifiers.includes(modifier) || - (mouseKeyModifiers.includes(modifier) && isOnClick) + systemKeyModifiers.includes( + modifier as Exclude + ) || + (mouseKeyModifiers.includes( + modifier as Exclude + ) && + isOnClick) ) { - systemModifiers.push(modifier) + systemModifiers.push(modifier as Modifier) } else { keyModifiers.push(modifier) } @@ -51,25 +80,6 @@ function generateModifiers(modifiers: KeyNameArray, isOnClick: boolean) { } } -export type KeyNameArray = Array -export const keyCodesByKeyName = { - backspace: 8, - tab: 9, - enter: 13, - esc: 27, - space: 32, - pageup: 33, - pagedown: 34, - end: 35, - home: 36, - left: 37, - up: 38, - right: 39, - down: 40, - insert: 45, - delete: 46 -} - function getEventProperties(eventParams: EventParams) { let { modifiers, options = {}, eventType } = eventParams @@ -155,7 +165,7 @@ function createDOMEvent(eventString: String, options?: TriggerOptions) { const eventParams: EventParams = { eventType, - modifiers: modifiers as KeyNameArray, + modifiers: modifiers as KeyName[], options } const event: Event & TriggerOptions = createEvent(eventParams) @@ -178,4 +188,4 @@ function createDOMEvent(eventString: String, options?: TriggerOptions) { return event } -export { TriggerOptions, createDOMEvent } +export { TriggerOptions, createDOMEvent, keyCodesByKeyName, KeyName } diff --git a/src/domWrapper.ts b/src/domWrapper.ts index fee5b50d8..d5b929dad 100644 --- a/src/domWrapper.ts +++ b/src/domWrapper.ts @@ -157,6 +157,8 @@ export class DOMWrapper { return } + // todo - review all non-null assertion operators in project + // search globally for `!.` and with regex `!$` element.selected = true let parentElement = element.parentElement! diff --git a/src/emit.ts b/src/emit.ts index bd8797be0..27e292534 100644 --- a/src/emit.ts +++ b/src/emit.ts @@ -5,7 +5,7 @@ import { ComponentInternalInstance } from 'vue' -export type Events = Record> +type Events = Record> const enum DevtoolsHooks { COMPONENT_EMIT = 'component:emit' @@ -16,10 +16,10 @@ let events: Events export function emitted( vm: ComponentPublicInstance, eventName?: string -): undefined | Events[number][string] | Events[number] { +): undefined | T[] | Record { const cid = vm.$.uid - const vmEvents: Events[number] = (events as Events)[cid] || {} + const vmEvents: Record = (events as Events)[cid] || {} if (eventName) { return vmEvents ? vmEvents[eventName] : undefined } diff --git a/src/mount.ts b/src/mount.ts index 38872b59f..87ad1cf9b 100644 --- a/src/mount.ts +++ b/src/mount.ts @@ -268,8 +268,8 @@ export function mount( [name, slot]: [string, Slot] ): { [key: string]: Function } => { // case of an SFC getting passed - if (typeof slot === 'object' && 'render' in slot) { - acc[name] = slot.render! + if (typeof slot === 'object' && 'render' in slot && slot.render) { + acc[name] = slot.render return acc } diff --git a/src/vueWrapper.ts b/src/vueWrapper.ts index 445f90274..e0792fae7 100644 --- a/src/vueWrapper.ts +++ b/src/vueWrapper.ts @@ -13,7 +13,6 @@ import { TriggerOptions } from './createDomEvent' import { find, matches } from './utils/find' import { mergeDeep, textContent } from './utils' import { emitted } from './emit' -import type { Events } from './emit' export class VueWrapper { private componentVM: T @@ -62,26 +61,28 @@ export class VueWrapper { classes(): string[] classes(className: string): boolean classes(className?: string): string[] | boolean { - return new DOMWrapper(this.element).classes(className!) + return className + ? new DOMWrapper(this.element).classes(className) + : new DOMWrapper(this.element).classes() } attributes(): { [key: string]: string } attributes(key: string): string attributes(key?: string): { [key: string]: string } | string { - return new DOMWrapper(this.element).attributes(key!) + return key + ? new DOMWrapper(this.element).attributes(key) + : new DOMWrapper(this.element).attributes() } exists() { return true } - emitted(): Events[number] + emitted(): Record + emitted(eventName?: string): undefined | T[] emitted( eventName?: string - ): undefined | Events[number][string] - emitted( - eventName?: string - ): undefined | Events[number][string] | Events[number] { + ): undefined | T[] | Record { return emitted(this.vm, eventName) } diff --git a/tests/isVisible.spec.ts b/tests/isVisible.spec.ts index 559ed68ba..0ac38876b 100644 --- a/tests/isVisible.spec.ts +++ b/tests/isVisible.spec.ts @@ -1,4 +1,5 @@ import { mount } from '../src' +import { defineComponent, ref } from 'vue' describe('isVisible', () => { const Comp = { @@ -79,7 +80,7 @@ describe('isVisible', () => { }) it('handles transition-group', async () => { - const Comp = { + const Comp = defineComponent({ template: `
@@ -91,22 +92,13 @@ describe('isVisible', () => {
`, - methods: { - add() { - // @ts-expect-error - this.items.push(2) - }, - remove() { - // @ts-expect-error - this.items.splice(1) // back to [1] - } - }, - data() { - return { - items: [1] - } + setup() { + const items = ref([1]) + const add = () => items.value.push(2) + const remove = () => items.value.splice(1) + return { add, remove, items } } - } + }) const wrapper = mount(Comp) expect(wrapper.html()).toContain('Item: 1') diff --git a/tests/mountingOptions/data.spec.ts b/tests/mountingOptions/data.spec.ts index 0e54c3502..fc7b6e95d 100644 --- a/tests/mountingOptions/data.spec.ts +++ b/tests/mountingOptions/data.spec.ts @@ -1,21 +1,20 @@ -import { h } from 'vue' +import { defineComponent, h } from 'vue' import { mount } from '../../src' describe('mounting options: data', () => { it('merges data from mounting options with component', () => { - const Comp = { + const Comp = defineComponent({ data() { return { foo: 'foo', bar: 'bar' } }, - render(): Function { - // @ts-expect-error + render() { return h('div', `Foo is ${this.foo} bar is ${this.bar}`) } - } + }) const wrapper = mount(Comp, { data() { diff --git a/tests/mountingOptions/mocks.spec.ts b/tests/mountingOptions/mocks.spec.ts index be8c96fe3..adcda4eb5 100644 --- a/tests/mountingOptions/mocks.spec.ts +++ b/tests/mountingOptions/mocks.spec.ts @@ -1,4 +1,5 @@ import { mount, RouterLinkStub } from '../../src' +import { defineComponent } from 'vue' describe('mocks', () => { it('mocks a vuex store', async () => { @@ -29,7 +30,7 @@ describe('mocks', () => { }) it('mocks vue-router', async () => { - const Foo = { + const Foo = defineComponent({ template: `
Go to post: {{ id }} @@ -37,22 +38,19 @@ describe('mocks', () => {
`, computed: { - url(): string { - // @ts-expect-error + url() { return `/posts/${this.$route.params.id}` }, - id(): number { - // @ts-expect-error + id() { return this.$route.params.id } }, methods: { submit() { - // @ts-expect-error this.$router.push(`/posts/${this.id}`) } } - } + }) const $router = { push: jest.fn() diff --git a/tests/setData.spec.ts b/tests/setData.spec.ts index ee5dca858..f7fcbd0a6 100644 --- a/tests/setData.spec.ts +++ b/tests/setData.spec.ts @@ -20,7 +20,7 @@ describe('setData', () => { // See: https://github.com/vuejs/vue-test-utils/issues/1756 // Making sure it does not regress here. it('triggers a watcher', async () => { - const Comp = { + const Comp = defineComponent({ template: `
`, data() { return { @@ -34,12 +34,11 @@ describe('setData', () => { myObject: { immediate: true, handler() { - // @ts-expect-error this.watchCounter += 1 } } } - } + }) const initial = 'value' const expected = 'something else' diff --git a/tests/setProps.spec.ts b/tests/setProps.spec.ts index b7d54faf2..b5b3bcfbc 100644 --- a/tests/setProps.spec.ts +++ b/tests/setProps.spec.ts @@ -56,7 +56,7 @@ describe('setProps', () => { }) it('triggers a watcher', async () => { - const Foo = { + const Foo = defineComponent({ props: ['foo'], data() { return { @@ -65,13 +65,12 @@ describe('setProps', () => { }, watch: { foo(val: string) { - // @ts-expect-error this.bar = val } }, template: `
{{ bar }}
` - } + }) const wrapper = mount(Foo) expect(wrapper.html()).toContain('original-bar') diff --git a/tests/trigger.spec.ts b/tests/trigger.spec.ts index 4a3a0de12..88986242c 100644 --- a/tests/trigger.spec.ts +++ b/tests/trigger.spec.ts @@ -1,7 +1,7 @@ import { defineComponent, h, ref } from 'vue' import { mount } from '../src' -import { keyCodesByKeyName, KeyNameArray } from '../src/createDomEvent' +import { keyCodesByKeyName, KeyName } from '../src/createDomEvent' describe('trigger', () => { describe('on click', () => { @@ -233,8 +233,7 @@ describe('trigger', () => { const wrapper = mount(Component, {}) for (const keyName in keyCodesByKeyName) { - const keyCode = - keyCodesByKeyName[keyName as keyof typeof keyCodesByKeyName] + const keyCode = keyCodesByKeyName[keyName as KeyName] wrapper.trigger(`keydown.${keyName}`) const calls = keydownHandler.mock.calls diff --git a/tsconfig.json b/tsconfig.json index 7fec7a2df..1fa5a428a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -18,6 +18,7 @@ }, "include": [ "tests", - "src" + "src", + "types" ] } diff --git a/types/testing.d.ts b/types/testing.d.ts new file mode 100644 index 000000000..4aa77f8f2 --- /dev/null +++ b/types/testing.d.ts @@ -0,0 +1,7 @@ +import type { Router } from 'vue-router' + +declare module '@vue/runtime-core' { + interface ComponentCustomProperties { + $router: Router + } +}