Skip to content

Commit 11f64fa

Browse files
committed
fix(find): finding by ref may return Node, not just Element
1 parent bfce74d commit 11f64fa

File tree

6 files changed

+45
-24
lines changed

6 files changed

+45
-24
lines changed

src/baseWrapper.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,9 @@ export default abstract class BaseWrapper<ElementType extends Node>
4646
selector: K
4747
): DOMWrapper<SVGElementTagNameMap[K]>
4848
find<T extends Element>(selector: string | RefSelector): DOMWrapper<T>
49-
find(selector: string | RefSelector): DOMWrapper<Element>
50-
find(selector: string | RefSelector): DOMWrapper<Element> {
49+
find(selector: string): DOMWrapper<Element>
50+
find(selector: RefSelector): DOMWrapper<Node>
51+
find(selector: string | RefSelector): DOMWrapper<Node> {
5152
// allow finding the root element
5253
if (!isElement(this.element)) {
5354
return createWrapperError('DOMWrapper')
@@ -61,7 +62,7 @@ export default abstract class BaseWrapper<ElementType extends Node>
6162

6263
const result = currentComponent.refs[selector.ref]
6364

64-
if (result instanceof HTMLElement) {
65+
if (result instanceof Node) {
6566
return createDOMWrapper(result)
6667
} else {
6768
return createWrapperError('DOMWrapper')
@@ -110,8 +111,9 @@ export default abstract class BaseWrapper<ElementType extends Node>
110111
selector: T | Exclude<FindComponentSelector, FunctionalComponent>
111112
): VueWrapper<InstanceType<T>>
112113
// searching for functional component results in DOMWrapper
114+
findComponent<T extends FunctionalComponent>(selector: T): DOMWrapper<Node>
113115
findComponent<T extends FunctionalComponent>(
114-
selector: T | string
116+
selector: string
115117
): DOMWrapper<Element>
116118
// searching by name or ref always results in VueWrapper
117119
findComponent<T extends never>(
@@ -154,7 +156,10 @@ export default abstract class BaseWrapper<ElementType extends Node>
154156
selector: T | Exclude<FindAllComponentsSelector, FunctionalComponent>
155157
): VueWrapper<InstanceType<T>>[]
156158
findAllComponents<T extends FunctionalComponent>(
157-
selector: T | string
159+
selector: T
160+
): DOMWrapper<Node>[]
161+
findAllComponents<T extends FunctionalComponent>(
162+
selector: string
158163
): DOMWrapper<Element>[]
159164
findAllComponents<T extends never>(selector: NameSelector): VueWrapper[]
160165
findAllComponents<T extends ComponentPublicInstance>(
@@ -223,7 +228,8 @@ export default abstract class BaseWrapper<ElementType extends Node>
223228
selector: K
224229
): Omit<DOMWrapper<SVGElementTagNameMap[K]>, 'exists'>
225230
get<T extends Element>(selector: string): Omit<DOMWrapper<T>, 'exists'>
226-
get(selector: string): Omit<DOMWrapper<Element>, 'exists'> {
231+
get(selector: RefSelector): Omit<DOMWrapper<Node>, 'exists'>
232+
get(selector: string | RefSelector): Omit<DOMWrapper<Element>, 'exists'> {
227233
const result = this.find(selector)
228234
if (result.exists()) {
229235
return result

src/config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ interface Plugin<Instance, O> {
1717
options: O
1818
}
1919

20-
class Pluggable<Instance = DOMWrapper<Element>> {
20+
class Pluggable<Instance = DOMWrapper<Node>> {
2121
installedPlugins: Plugin<Instance, any>[] = []
2222

2323
install<O>(handler: (instance: Instance) => Record<string, any>): void

src/interfaces/wrapperLike.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ export default interface WrapperLike {
1818
selector: K
1919
): DOMWrapper<SVGElementTagNameMap[K]>
2020
find<T extends Element>(selector: string | RefSelector): DOMWrapper<T>
21-
find(selector: string | RefSelector): DOMWrapper<Element>
21+
find(selector: string): DOMWrapper<Element>
22+
find(selector: RefSelector): DOMWrapper<Node>
2223

2324
findAll<K extends keyof HTMLElementTagNameMap>(
2425
selector: K
@@ -50,8 +51,11 @@ export default interface WrapperLike {
5051
selector: T | Exclude<FindAllComponentsSelector, FunctionalComponent>
5152
): VueWrapper<InstanceType<T>>[]
5253
findAllComponents<T extends FunctionalComponent>(
53-
selector: T | string
54+
selector: string
5455
): DOMWrapper<Element>[]
56+
findAllComponents<T extends FunctionalComponent>(
57+
selector: T
58+
): DOMWrapper<Node>[]
5559
findAllComponents<T extends never>(selector: NameSelector): VueWrapper[]
5660
findAllComponents<T extends ComponentPublicInstance>(
5761
selector: T | FindAllComponentsSelector
@@ -65,6 +69,7 @@ export default interface WrapperLike {
6569
selector: K
6670
): Omit<DOMWrapper<SVGElementTagNameMap[K]>, 'exists'>
6771
get<T extends Element>(selector: string): Omit<DOMWrapper<T>, 'exists'>
72+
get(selector: RefSelector): Omit<DOMWrapper<Node>, 'exists'>
6873
get(selector: string): Omit<DOMWrapper<Element>, 'exists'>
6974

7075
getComponent<T extends never>(selector: string): Omit<WrapperLike, 'exists'>
@@ -75,10 +80,6 @@ export default interface WrapperLike {
7580
getComponent<T extends FunctionalComponent>(
7681
selector: T | string
7782
): Omit<DOMWrapper<Element>, 'exists'>
78-
// searching by name or ref always results in VueWrapper
79-
getComponent<T extends never>(
80-
selector: NameSelector | RefSelector
81-
): Omit<VueWrapper, 'exists'>
8283
getComponent<T extends ComponentPublicInstance>(
8384
selector: T | FindComponentSelector
8485
): Omit<VueWrapper<T>, 'exists'>

src/wrapperFactory.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export enum WrapperType {
77
VueWrapper
88
}
99

10-
type DOMWrapperFactory = <T extends Element>(element: T) => DOMWrapperType<T>
10+
type DOMWrapperFactory = <T extends Node>(element: T) => DOMWrapperType<T>
1111
type VueWrapperFactory = <T extends ComponentPublicInstance>(
1212
app: App | null,
1313
vm: T,

test-dts/findComponent.d-test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ expectType<VueWrapper<InstanceType<typeof ComponentWithEmits>>>(
4141

4242
// find by type - functional
4343
const functionalComponentByType = wrapper.findComponent(FuncComponent)
44-
expectType<DOMWrapper<Element>>(functionalComponentByType)
44+
expectType<DOMWrapper<Node>>(functionalComponentByType)
4545

4646
// find by string
4747
const componentByString = wrapper.findComponent('.foo')

tests/find.spec.ts

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { defineComponent, h, nextTick } from 'vue'
1+
import { defineComponent, h, nextTick, Fragment } from 'vue'
22

33
import { mount, VueWrapper } from '../src'
44
import SuspenseComponent from './components/Suspense.vue'
@@ -15,15 +15,29 @@ describe('find', () => {
1515
expect(wrapper.find('#my-span').exists()).toBe(true)
1616
})
1717

18-
it('find DOM element by ref', () => {
19-
const Component = defineComponent({
20-
render() {
21-
return h('div', {}, [h('span', { ref: 'span', id: 'my-span' })])
22-
}
18+
describe('find DOM element by ref', () => {
19+
it('works for root element', () => {
20+
const Component = defineComponent({
21+
render() {
22+
return h('div', {}, [h('span', { ref: 'span', id: 'my-span' })])
23+
}
24+
})
25+
const wrapper = mount(Component)
26+
expect(wrapper.find({ ref: 'span' }).exists()).toBe(true)
27+
expect(wrapper.find({ ref: 'span' }).attributes('id')).toBe('my-span')
28+
})
29+
30+
it('works when ref is pointing to non-element node', () => {
31+
const Component = defineComponent({
32+
render() {
33+
return h('div', null, h(Fragment, { ref: 'plain'}, ['hello']))
34+
}
35+
})
36+
37+
const wrapper = mount(Component)
38+
expect(wrapper.find({ ref: 'plain' }).exists()).toBe(true)
39+
expect(wrapper.find({ ref: 'plain' }).element).toBeInstanceOf(Text)
2340
})
24-
const wrapper = mount(Component)
25-
expect(wrapper.find({ ref: 'span' }).exists()).toBe(true)
26-
expect(wrapper.find({ ref: 'span' }).attributes('id')).toBe('my-span')
2741
})
2842

2943
it('find using multiple root nodes', () => {

0 commit comments

Comments
 (0)