Skip to content

Commit 3caf178

Browse files
committed
chore: fix tests
2 parents f73633e + e63f1dd commit 3caf178

27 files changed

+1130
-251
lines changed

package.json

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@vue/test-utils",
3-
"version": "2.0.0-alpha.3",
3+
"version": "2.0.0-alpha.6",
44
"license": "MIT",
55
"main": "dist/vue-test-utils.cjs.js",
66
"browser": "dist/vue-test-utils.browser.js",
@@ -12,10 +12,6 @@
1212
"README.md",
1313
"dist/index.d.ts"
1414
],
15-
"dependencies": {
16-
"dom-event-types": "^1.0.0",
17-
"lodash": "^4.17.15"
18-
},
1915
"devDependencies": {
2016
"@babel/core": "^7.9.0",
2117
"@babel/preset-env": "^7.8.4",
@@ -26,11 +22,12 @@
2622
"@rollup/plugin-replace": "^2.3.2",
2723
"@types/estree": "^0.0.42",
2824
"@types/jest": "^24.9.1",
29-
"@types/lodash": "^4.14.149",
3025
"@types/node": "12.12.35",
31-
"@vue/compiler-sfc": "^3.0.0-beta.5",
26+
"@vue/compiler-dom": "^3.0.0-beta.12",
27+
"@vue/compiler-sfc": "^3.0.0-beta.12",
3228
"babel-jest": "^25.2.3",
3329
"babel-preset-jest": "^25.2.1",
30+
"dom-event-types": "^1.0.0",
3431
"flush-promises": "^1.0.2",
3532
"husky": "^4.2.3",
3633
"jest": "^25.1.0",
@@ -43,13 +40,14 @@
4340
"ts-jest": "^25.0.0",
4441
"tsd": "0.11.0",
4542
"typescript": "^3.7.5",
46-
"vue": "^3.0.0-beta.5",
43+
"vue": "^3.0.0-beta.12",
4744
"vue-jest": "vuejs/vue-jest#next",
4845
"vuex": "^4.0.0-beta.1"
4946
},
5047
"peerDependencies": {
51-
"@vue/compiler-sfc": "^3.0.0-beta.4",
52-
"vue": "^3.0.0-beta.4"
48+
"@vue/compiler-dom": "^3.0.0-beta.12",
49+
"@vue/compiler-sfc": "^3.0.0-beta.12",
50+
"vue": "^3.0.0-beta.12"
5351
},
5452
"author": {
5553
"name": "Lachlan Miller",

rollup.config.js

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,7 @@ function createEntry(options) {
2525
input,
2626
external: [
2727
'vue',
28-
'lodash/mergeWith',
29-
'lodash/isString'
28+
'@vue/compiler-dom',
3029
],
3130
plugins: [
3231
replace({
@@ -41,30 +40,25 @@ function createEntry(options) {
4140
format,
4241
globals: {
4342
vue: 'Vue',
44-
'lodash/mergeWith': '_.mergeWith',
45-
'lodash/isString': '_.isString',
43+
'@vue/compiler-dom': 'VueCompilerDOM',
4644
}
4745
}
4846
}
4947

50-
if (['es', 'cjs'].includes(format)) {
51-
config.external.push('dom-event-types')
52-
}
53-
5448
if (format === 'es') {
55-
config.output.file = isBrowser ? pkg.browser : pkg.module
49+
config.output.file = pkg.module
5650
}
5751
if (format === 'cjs') {
5852
config.output.file = pkg.main
5953
}
60-
console.log('file is', config.output.file)
54+
console.log(`Building ${format}: ${config.output.file}`)
6155

6256
config.plugins.push(
6357
ts({
6458
check: format === 'es' && isBrowser,
6559
tsconfigOverride: {
6660
compilerOptions: {
67-
declaration: format === 'es' && isBrowser,
61+
declaration: format === 'es',
6862
target: 'es5', // not sure what this should be?
6963
module: format === 'cjs' ? 'es2015' : 'esnext'
7064
},
@@ -78,7 +72,6 @@ function createEntry(options) {
7872

7973
export default [
8074
createEntry({ format: 'es', input: 'src/index.ts', isBrowser: false }),
81-
createEntry({ format: 'es', input: 'src/index.ts', isBrowser: true }),
8275
createEntry({ format: 'iife', input: 'src/index.ts', isBrowser: true }),
8376
createEntry({ format: 'cjs', input: 'src/index.ts', isBrowser: false }),
8477
]

src/config.ts

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import { GlobalMountOptions } from './types'
2+
import { VueWrapper } from './vue-wrapper'
3+
import { ComponentPublicInstance } from 'vue'
24

35
interface GlobalConfigOptions {
46
global: GlobalMountOptions
@@ -9,27 +11,36 @@ interface GlobalConfigOptions {
911
renderStubDefaultSlot: boolean
1012
}
1113

14+
interface Plugin {
15+
handler: (
16+
instance: VueWrapper<ComponentPublicInstance>
17+
) => Record<string, any>
18+
options: Record<string, any>
19+
}
20+
1221
class Pluggable {
13-
installedPlugins: any
14-
constructor() {
15-
this.installedPlugins = []
16-
}
22+
installedPlugins = [] as Array<Plugin>
1723

18-
install(handler, options = {}) {
24+
install(
25+
handler: (
26+
instance: VueWrapper<ComponentPublicInstance>
27+
) => Record<string, any>,
28+
options: Record<string, any> = {}
29+
) {
1930
if (typeof handler !== 'function') {
2031
console.error('plugin.install must receive a function')
2132
handler = () => ({})
2233
}
2334
this.installedPlugins.push({ handler, options })
2435
}
2536

26-
extend(instance) {
27-
const invokeSetup = (plugin) => plugin.handler(instance) // invoke the setup method passed to install
37+
extend(instance: VueWrapper<ComponentPublicInstance>) {
38+
const invokeSetup = (plugin: Plugin) => plugin.handler(instance) // invoke the setup method passed to install
2839
const bindProperty = ([property, value]: [string, any]) => {
29-
instance[property] =
40+
;(instance as any)[property] =
3041
typeof value === 'function' ? value.bind(instance) : value
3142
}
32-
const addAllPropertiesFromSetup = (setupResult) => {
43+
const addAllPropertiesFromSetup = (setupResult: Record<string, any>) => {
3344
setupResult = typeof setupResult === 'object' ? setupResult : {}
3445
Object.entries(setupResult).forEach(bindProperty)
3546
}

src/create-dom-event.ts

Lines changed: 94 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import * as eventTypes from 'dom-event-types'
1+
import eventTypes from 'dom-event-types'
22

33
interface TriggerOptions {
44
code?: String
@@ -9,11 +9,47 @@ interface TriggerOptions {
99

1010
interface EventParams {
1111
eventType: string
12-
modifier: string
13-
meta: any
12+
modifiers: string[]
1413
options?: TriggerOptions
1514
}
1615

16+
// modifiers to keep an eye on
17+
const ignorableKeyModifiers = ['stop', 'prevent', 'self', 'exact']
18+
const systemKeyModifiers = ['ctrl', 'shift', 'alt', 'meta']
19+
const mouseKeyModifiers = ['left', 'middle', 'right']
20+
21+
/**
22+
* Groups modifiers into lists
23+
*/
24+
function generateModifiers(modifiers: string[], isOnClick: boolean) {
25+
const keyModifiers: string[] = []
26+
const systemModifiers: string[] = []
27+
28+
for (let i = 0; i < modifiers.length; i++) {
29+
const modifier = modifiers[i]
30+
31+
// addEventListener() options, e.g. .passive & .capture, that we dont need to handle
32+
if (ignorableKeyModifiers.includes(modifier)) {
33+
continue
34+
}
35+
// modifiers that require special conversion
36+
// if passed a left/right key modifier with onClick, add it here as well.
37+
if (
38+
systemKeyModifiers.includes(modifier) ||
39+
(mouseKeyModifiers.includes(modifier) && isOnClick)
40+
) {
41+
systemModifiers.push(modifier)
42+
} else {
43+
keyModifiers.push(modifier)
44+
}
45+
}
46+
47+
return {
48+
keyModifiers,
49+
systemModifiers
50+
}
51+
}
52+
1753
export const keyCodesByKeyName = {
1854
backspace: 8,
1955
tab: 9,
@@ -33,52 +69,90 @@ export const keyCodesByKeyName = {
3369
}
3470

3571
function getEventProperties(eventParams: EventParams) {
36-
const { modifier, meta, options } = eventParams
72+
let { modifiers, options = {}, eventType } = eventParams
73+
74+
let isOnClick = eventType === 'click'
75+
76+
const { keyModifiers, systemModifiers } = generateModifiers(
77+
modifiers,
78+
isOnClick
79+
)
80+
81+
if (isOnClick) {
82+
// if it's a right click, it should fire a `contextmenu` event
83+
if (systemModifiers.includes('right')) {
84+
eventType = 'contextmenu'
85+
options.button = 2
86+
// if its a middle click, fire a `mouseup` event
87+
} else if (systemModifiers.includes('middle')) {
88+
eventType = 'mouseup'
89+
options.button = 1
90+
}
91+
}
92+
93+
const meta = eventTypes[eventType] || {
94+
eventInterface: 'Event',
95+
cancelable: true,
96+
bubbles: true
97+
}
98+
99+
// convert `shift, ctrl` to `shiftKey, ctrlKey`
100+
// allows trigger('keydown.shift.ctrl.n') directly
101+
const systemModifiersMeta = systemModifiers.reduce((all, key) => {
102+
all[`${key}Key`] = true
103+
return all
104+
}, {})
105+
106+
// get the keyCode for backwards compat
37107
const keyCode =
38-
keyCodesByKeyName[modifier] ||
108+
keyCodesByKeyName[keyModifiers[0]] ||
39109
(options && (options.keyCode || options.code))
40110

41-
return {
111+
const eventProperties = {
112+
...systemModifiersMeta, // shiftKey, metaKey etc
42113
...options, // What the user passed in as the second argument to #trigger
43114
bubbles: meta.bubbles,
44115
meta: meta.cancelable,
45116
// Any derived options should go here
46117
keyCode,
47-
code: keyCode
118+
code: keyCode,
119+
// if we have a `key`, use it, otherwise dont set anything (allows user to pass custom key)
120+
...(keyModifiers[0] ? { key: keyModifiers[0] } : {})
121+
}
122+
123+
return {
124+
eventProperties,
125+
meta,
126+
eventType
48127
}
49128
}
50129

51130
function createEvent(eventParams: EventParams) {
52-
const { eventType, meta } = eventParams
131+
const { eventProperties, meta, eventType } = getEventProperties(eventParams)
132+
133+
// user defined eventInterface
53134
const metaEventInterface = window[meta.eventInterface]
54135

55136
const SupportedEventInterface =
56137
typeof metaEventInterface === 'function' ? metaEventInterface : window.Event
57138

58-
const eventProperties = getEventProperties(eventParams)
59-
60-
const event = new SupportedEventInterface(
139+
return new SupportedEventInterface(
61140
eventType,
62141
// event properties can only be added when the event is instantiated
63142
// custom properties must be added after the event has been instantiated
64143
eventProperties
65144
)
66-
67-
return event
68145
}
69146

70147
function createDOMEvent(eventString: String, options?: TriggerOptions) {
71-
const [eventType, modifier] = eventString.split('.')
72-
const meta = eventTypes[eventType] || {
73-
eventInterface: 'Event',
74-
cancelable: true,
75-
bubbles: true
76-
}
148+
// split eventString like `keydown.ctrl.shift.c` into `keydown` and array of modifiers
149+
const [eventType, ...modifiers] = eventString.split('.')
77150

78-
const eventParams: EventParams = { eventType, modifier, meta, options }
151+
const eventParams: EventParams = { eventType, modifiers, options }
79152
const event: Event = createEvent(eventParams)
80153
const eventPrototype = Object.getPrototypeOf(event)
81154

155+
// attach custom options to the event, like `relatedTarget` and so on.
82156
options &&
83157
Object.keys(options).forEach((key) => {
84158
const propertyDescriptor = Object.getOwnPropertyDescriptor(

src/dom-wrapper.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,23 @@ export class DOMWrapper<ElementType extends Element> {
1010
this.element = element
1111
}
1212

13-
classes(className?: string) {
13+
classes(): string[]
14+
classes(className: string): boolean
15+
classes(className?: string): string[] | boolean {
1416
const classes = this.element.classList
1517

1618
if (className) return classes.contains(className)
1719

1820
return Array.from(classes)
1921
}
2022

21-
attributes(key?: string) {
22-
const attributes = this.element.attributes
23-
const attributeMap = {}
24-
for (let i = 0; i < attributes.length; i++) {
25-
const att = attributes.item(i)
26-
attributeMap[att.localName] = att.value
23+
attributes(): { [key: string]: string }
24+
attributes(key: string): string
25+
attributes(key?: string): { [key: string]: string } | string {
26+
const attributes = Array.from(this.element.attributes)
27+
const attributeMap: Record<string, string> = {}
28+
for (const attribute of attributes) {
29+
attributeMap[attribute.localName] = attribute.value
2730
}
2831

2932
return key ? attributeMap[key] : attributeMap

0 commit comments

Comments
 (0)