Skip to content

Commit 1d5b30a

Browse files
committed
rebase with master
2 parents c01e235 + f26e0d4 commit 1d5b30a

29 files changed

+967
-219
lines changed

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ mixins | ✅ | (new!) nested in [`global`](https://vuejs.github.io/vue-test-util
5959
plugins | ✅ | (new!) nested in [`global`](https://vuejs.github.io/vue-test-utils-next-docs/api/#global)
6060
component | ✅ | (new!) nested in [`global`](https://vuejs.github.io/vue-test-utils-next-docs/api/#global)
6161
directives | ✅ | (new!) nested in [`global`](https://vuejs.github.io/vue-test-utils-next-docs/api/#global)
62-
stubs |
62+
stubs |
6363
attachToDocument | ❌| will rename to `attachTo`. See [here](https://github.com/vuejs/vue-test-utils/pull/1492)
6464
attrs | ❌ |
6565
scopedSlots | ⚰️ | scopedSlots are merged with slots in Vue 3
@@ -85,8 +85,9 @@ setValue | ✅ | works for select, checkbox, radio button, input, textarea. Retu
8585
text | ✅ |
8686
trigger | ✅ | returns `nextTick`. You can do `await wrapper.find('button').trigger('click')`
8787
setProps | ✅ |
88+
props | ✅
8889
setData | ❌ | has PR
89-
destroy |
90+
destroy | ✅ | renamed to `unmount` to match Vue 3 lifecycle hook name.
9091
props | ❌
9192
contains | ⚰️| use `find`
9293
emittedByOrder | ⚰️ | use `emitted`

docs/API.md

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,85 @@ test('findAll', () => {
348348
})
349349
```
350350

351+
### `findComponent`
352+
353+
Finds a Vue Component instance and returns a `VueWrapper` if one is found, otherwise returns `ErrorWrapper`.
354+
355+
**Supported syntax:**
356+
357+
* **querySelector** - `findComponent('.component')` - Matches standard query selector.
358+
* **Name** - `findComponent({ name: 'myComponent' })` - matches PascalCase, snake-case, camelCase
359+
* **ref** - `findComponent({ ref: 'dropdown' })` - Can be used only on direct ref children of mounted component
360+
* **SFC** - `findComponent(ImportedComponent)` - Pass an imported component directly.
361+
362+
```vue
363+
<template>
364+
<div class="foo">
365+
Foo
366+
</div>
367+
</template>
368+
<script>
369+
export default { name: 'Foo' }
370+
</script>
371+
```
372+
373+
```vue
374+
<template>
375+
<div>
376+
<span>Span</span>
377+
<Foo data-test="foo" ref="foo"/>
378+
</div>
379+
</template>
380+
```
381+
382+
```js
383+
test('findComponent', () => {
384+
const wrapper = mount(Component)
385+
386+
wrapper.findComponent('.foo') //=> found; returns VueWrapper
387+
wrapper.findComponent('[data-test="foo"]') //=> found; returns VueWrapper
388+
wrapper.findComponent({ name: 'Foo' }) //=> found; returns VueWrapper
389+
wrapper.findComponent({ name: 'foo' }) //=> found; returns VueWrapper
390+
wrapper.findComponent({ ref: 'foo' }) //=> found; returns VueWrapper
391+
wrapper.findComponent(Foo) //=> found; returns VueWrapper
392+
})
393+
```
394+
395+
### `findAllComponents`
396+
397+
Similar to `findComponent` but finds all Vue Component instances that match the query and returns an array of `VueWrapper`.
398+
399+
**Supported syntax:**
400+
401+
* **querySelector** - `findAllComponents('.component')`
402+
* **Name** - `findAllComponents({ name: 'myComponent' })`
403+
* **SFC** - `findAllComponents(ImportedComponent)`
404+
405+
**Note** - `Ref` is not supported here.
406+
407+
408+
```vue
409+
<template>
410+
<div>
411+
<FooComponent
412+
v-for="number in [1, 2, 3]"
413+
:key="number"
414+
data-test="number"
415+
>
416+
{{ number }}
417+
</FooComponent>
418+
</div>
419+
</template>
420+
```
421+
422+
```js
423+
test('findAllComponents', () => {
424+
const wrapper = mount(Component)
425+
426+
wrapper.findAllComponents('[data-test="number"]') //=> found; returns array of VueWrapper
427+
})
428+
```
429+
351430
### `trigger`
352431

353432
Simulates an event, for example `click`, `submit` or `keyup`. Since events often cause a re-render, `trigger` returs `Vue.nextTick`. If you expect the event to trigger a re-render, you should use `await` when you call `trigger` to ensure that Vue updates the DOM before you make an assertion.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
"@types/jest": "^24.9.1",
2525
"@types/node": "12.12.35",
2626
"@types/lodash": "^4.14.149",
27-
"@vue/compiler-sfc": "^3.0.0-alpha.13",
27+
"@vue/compiler-sfc": "^3.0.0-beta.2",
2828
"babel-jest": "^25.2.3",
2929
"babel-preset-jest": "^25.2.1",
3030
"dom-event-types": "^1.0.0",
@@ -38,7 +38,7 @@
3838
"ts-jest": "^25.0.0",
3939
"tsd": "0.11.0",
4040
"typescript": "^3.7.5",
41-
"vue": "^3.0.0-alpha.13",
41+
"vue": "^3.0.0-beta.2",
4242
"vue-jest": "vuejs/vue-jest#next",
4343
"vuex": "^4.0.0-alpha.1"
4444
},

rollup.config.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ function createEntry(options) {
2121
const config = {
2222
input,
2323
external: [
24-
'vue',
24+
'vue',
2525
'lodash/mergeWith',
2626
'lodash/camelCase',
2727
'lodash/upperFirst',
@@ -38,7 +38,7 @@ function createEntry(options) {
3838
}
3939

4040
if (format === 'es') {
41-
config.output.file = isBrowser ? pkg.browser : pkg.module
41+
config.output.file = isBrowser ? pkg.browser : pkg.module
4242
}
4343
if (format === 'cjs') {
4444
config.output.file = pkg.main

src/config.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { GlobalMountOptions } from './types'
2+
3+
export const config: { global: GlobalMountOptions } = {
4+
global: {}
5+
}

src/constants.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
export const MOUNT_ELEMENT_ID = 'app'
2+
export const MOUNT_COMPONENT_REF = 'VTU_COMPONENT'
3+
export const MOUNT_PARENT_NAME = 'VTU_ROOT'

src/create-dom-event.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ interface EventParams {
1414
options?: TriggerOptions
1515
}
1616

17-
const keyCodesByKeyName = {
17+
export const keyCodesByKeyName = {
1818
backspace: 8,
1919
tab: 9,
2020
enter: 13,

src/dom-wrapper.ts

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,26 +43,47 @@ export class DOMWrapper<ElementType extends Element> implements WrapperAPI {
4343
return this.element.outerHTML
4444
}
4545

46-
find<T extends Element>(selector: string): DOMWrapper<T> | ErrorWrapper {
47-
const result = this.element.querySelector<T>(selector)
46+
find<K extends keyof HTMLElementTagNameMap>(
47+
selector: K
48+
): DOMWrapper<HTMLElementTagNameMap[K]> | ErrorWrapper
49+
find<K extends keyof SVGElementTagNameMap>(
50+
selector: K
51+
): DOMWrapper<SVGElementTagNameMap[K]> | ErrorWrapper
52+
find<T extends Element>(selector: string): DOMWrapper<T> | ErrorWrapper
53+
find(selector: string): DOMWrapper<Element> | ErrorWrapper {
54+
const result = this.element.querySelector(selector)
4855
if (result) {
49-
return new DOMWrapper<T>(result)
56+
return new DOMWrapper(result)
5057
}
5158

5259
return new ErrorWrapper({ selector })
5360
}
5461

55-
get<T extends Element>(selector: string): DOMWrapper<T> {
56-
const result = this.find<T>(selector)
62+
get<K extends keyof HTMLElementTagNameMap>(
63+
selector: K
64+
): DOMWrapper<HTMLElementTagNameMap[K]>
65+
get<K extends keyof SVGElementTagNameMap>(
66+
selector: K
67+
): DOMWrapper<SVGElementTagNameMap[K]>
68+
get<T extends Element>(selector: string): DOMWrapper<T>
69+
get(selector: string): DOMWrapper<Element> {
70+
const result = this.find(selector)
5771
if (result instanceof ErrorWrapper) {
5872
throw new Error(`Unable to find ${selector} within: ${this.html()}`)
5973
}
6074

6175
return result
6276
}
6377

64-
findAll<T extends Element>(selector: string): DOMWrapper<T>[] {
65-
return Array.from(this.element.querySelectorAll<T>(selector)).map(
78+
findAll<K extends keyof HTMLElementTagNameMap>(
79+
selector: K
80+
): DOMWrapper<HTMLElementTagNameMap[K]>[]
81+
findAll<K extends keyof SVGElementTagNameMap>(
82+
selector: K
83+
): DOMWrapper<SVGElementTagNameMap[K]>[]
84+
findAll<T extends Element>(selector: string): DOMWrapper<T>[]
85+
findAll(selector: string): DOMWrapper<Element>[] {
86+
return Array.from(this.element.querySelectorAll(selector)).map(
6687
(x) => new DOMWrapper(x)
6788
)
6889
}

src/emitMixin.ts

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import { getCurrentInstance } from 'vue'
22

3-
export const createEmitMixin = () => {
4-
const events: Record<string, unknown[]> = {}
5-
6-
const emitMixin = {
3+
export const attachEmitListener = () => {
4+
return {
75
beforeCreate() {
6+
let events: Record<string, unknown[]> = {}
7+
this.__emitted = events
8+
89
getCurrentInstance().emit = (event: string, ...args: unknown[]) => {
910
events[event]
1011
? (events[event] = [...events[event], [...args]])
@@ -14,9 +15,4 @@ export const createEmitMixin = () => {
1415
}
1516
}
1617
}
17-
18-
return {
19-
events,
20-
emitMixin
21-
}
2218
}

src/error-wrapper.ts

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
import { FindComponentSelector } from './types'
2+
13
interface Options {
2-
selector: string
4+
selector: FindComponentSelector
35
}
46

57
export class ErrorWrapper {
6-
selector: string
8+
selector: FindComponentSelector
79
element: null
810

911
constructor({ selector }: Options) {
@@ -14,6 +16,10 @@ export class ErrorWrapper {
1416
return Error(`Cannot call ${method} on an empty wrapper.`)
1517
}
1618

19+
vm(): Error {
20+
throw this.wrapperError('vm')
21+
}
22+
1723
attributes() {
1824
throw this.wrapperError('attributes')
1925
}
@@ -30,12 +36,16 @@ export class ErrorWrapper {
3036
throw this.wrapperError('find')
3137
}
3238

39+
get(): never {
40+
throw this.wrapperError('get')
41+
}
42+
3343
findAll(): never {
3444
throw this.wrapperError('findAll')
3545
}
3646

37-
setChecked() {
38-
throw this.wrapperError('setChecked')
47+
setProps() {
48+
throw this.wrapperError('setProps')
3949
}
4050

4151
setValue() {
@@ -49,4 +59,8 @@ export class ErrorWrapper {
4959
trigger() {
5060
throw this.wrapperError('trigger')
5161
}
62+
63+
unmount() {
64+
throw this.wrapperError('unmount')
65+
}
5266
}

0 commit comments

Comments
 (0)