Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 28 additions & 7 deletions src/dom-wrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,26 +41,47 @@ export class DOMWrapper<ElementType extends Element> implements WrapperAPI {
return this.element.outerHTML
}

find<T extends Element>(selector: string): DOMWrapper<T> | ErrorWrapper {
const result = this.element.querySelector<T>(selector)
find<K extends keyof HTMLElementTagNameMap>(
selector: K
): DOMWrapper<HTMLElementTagNameMap[K]> | ErrorWrapper
find<K extends keyof SVGElementTagNameMap>(
selector: K
): DOMWrapper<SVGElementTagNameMap[K]> | ErrorWrapper
find<T extends Element>(selector: string): DOMWrapper<T> | ErrorWrapper
find(selector: string): DOMWrapper<Element> | ErrorWrapper {
const result = this.element.querySelector(selector)
if (result) {
return new DOMWrapper<T>(result)
return new DOMWrapper(result)
}

return new ErrorWrapper({ selector })
}

get<T extends Element>(selector: string): DOMWrapper<T> {
const result = this.find<T>(selector)
get<K extends keyof HTMLElementTagNameMap>(
selector: K
): DOMWrapper<HTMLElementTagNameMap[K]>
get<K extends keyof SVGElementTagNameMap>(
selector: K
): DOMWrapper<SVGElementTagNameMap[K]>
get<T extends Element>(selector: string): DOMWrapper<T>
get(selector: string): DOMWrapper<Element> {
const result = this.find(selector)
if (result instanceof ErrorWrapper) {
throw new Error(`Unable to find ${selector} within: ${this.html()}`)
}

return result
}

findAll<T extends Element>(selector: string): DOMWrapper<T>[] {
return Array.from(this.element.querySelectorAll<T>(selector)).map(
findAll<K extends keyof HTMLElementTagNameMap>(
selector: K
): DOMWrapper<HTMLElementTagNameMap[K]>[]
findAll<K extends keyof SVGElementTagNameMap>(
selector: K
): DOMWrapper<SVGElementTagNameMap[K]>[]
findAll<T extends Element>(selector: string): DOMWrapper<T>[]
findAll(selector: string): DOMWrapper<Element>[] {
return Array.from(this.element.querySelectorAll(selector)).map(
(x) => new DOMWrapper(x)
)
}
Expand Down
4 changes: 4 additions & 0 deletions src/error-wrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ export class ErrorWrapper {
throw this.wrapperError('find')
}

get(): never {
throw this.wrapperError('get')
}

findAll(): never {
throw this.wrapperError('findAll')
}
Expand Down
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export interface WrapperAPI {
classes: (className?: string) => string[] | boolean | ErrorWrapper
readonly element: Element
exists: () => boolean
get<T extends Element>(selector: string): DOMWrapper<T>
find<T extends Element>(selector: string): DOMWrapper<T> | ErrorWrapper
findAll<T extends Element>(selector: string): DOMWrapper<T>[]
html: () => string
Expand Down
35 changes: 28 additions & 7 deletions src/vue-wrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,18 +78,32 @@ export class VueWrapper<T extends ComponentPublicInstance>
return this.element.textContent?.trim()
}

find<T extends Element>(selector: string): DOMWrapper<T> | ErrorWrapper {
find<K extends keyof HTMLElementTagNameMap>(
selector: K
): DOMWrapper<HTMLElementTagNameMap[K]> | ErrorWrapper
find<K extends keyof SVGElementTagNameMap>(
selector: K
): DOMWrapper<SVGElementTagNameMap[K]> | ErrorWrapper
find<T extends Element>(selector: string): DOMWrapper<T> | ErrorWrapper
find(selector: string): DOMWrapper<Element> | ErrorWrapper {
// force using the parentElement to allow finding the root element
const result = this.parentElement.querySelector(selector) as T
const result = this.parentElement.querySelector(selector)
if (result) {
return new DOMWrapper(result)
}

return new ErrorWrapper({ selector })
}

get<T extends Element>(selector: string): DOMWrapper<T> {
const result = this.find<T>(selector)
get<K extends keyof HTMLElementTagNameMap>(
selector: K
): DOMWrapper<HTMLElementTagNameMap[K]>
get<K extends keyof SVGElementTagNameMap>(
selector: K
): DOMWrapper<SVGElementTagNameMap[K]>
get<T extends Element>(selector: string): DOMWrapper<T>
get(selector: string): DOMWrapper<Element> {
const result = this.find(selector)
if (result instanceof ErrorWrapper) {
throw new Error(`Unable to find ${selector} within: ${this.html()}`)
}
Expand All @@ -110,9 +124,16 @@ export class VueWrapper<T extends ComponentPublicInstance>
return find(this.vm.$.subTree, selector).map((c) => createWrapper(null, c))
}

findAll<T extends Element>(selector: string): DOMWrapper<T>[] {
const results = this.parentElement.querySelectorAll<T>(selector)
return Array.from(results).map((x) => new DOMWrapper(x))
findAll<K extends keyof HTMLElementTagNameMap>(
selector: K
): DOMWrapper<HTMLElementTagNameMap[K]>[]
findAll<K extends keyof SVGElementTagNameMap>(
selector: K
): DOMWrapper<SVGElementTagNameMap[K]>[]
findAll<T extends Element>(selector: string): DOMWrapper<T>[]
findAll(selector: string): DOMWrapper<Element>[] {
const results = this.parentElement.querySelectorAll(selector)
return Array.from(results).map((element) => new DOMWrapper(element))
}

setProps(props: Record<string, any>): Promise<void> {
Expand Down
File renamed without changes.
88 changes: 88 additions & 0 deletions test-dts/wrapper.d-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { expectType } from 'tsd'
import { defineComponent } from 'vue'
import { mount } from '../src'

const AppWithDefine = defineComponent({
template: ''
})

const wrapper = mount(AppWithDefine)
const domWrapper = wrapper.find('#other')

// find Vue wrapper
// HTML element selector
let inputMaybe = wrapper.find('input')
expectType<HTMLInputElement | undefined>(inputMaybe.element)

// SVG element selector
let lineMaybe = wrapper.find('line')
expectType<SVGLineElement | undefined>(lineMaybe.element)

// string selector
let byClassMaybe = wrapper.find('.todo')
expectType<Element | undefined>(byClassMaybe.element)

// find DOM wrapper
// HTML element selector
inputMaybe = domWrapper.find('input')
expectType<HTMLInputElement | undefined>(inputMaybe.element)

// SVG element selector
lineMaybe = domWrapper.find('line')
expectType<SVGLineElement | undefined>(lineMaybe.element)

// string selector
byClassMaybe = domWrapper.find('.todo')
expectType<Element | undefined>(byClassMaybe.element)

// findAll
// HTML element selector
let inputArray = wrapper.findAll('input')
expectType<HTMLInputElement | undefined>(inputArray[0].element)

// SVG element selector
let lineArray = wrapper.findAll('line')
expectType<SVGLineElement | undefined>(lineArray[0].element)

// string selector
let byClassArray = wrapper.findAll('.todo')
expectType<Element | undefined>(byClassArray[0].element)

// findAll DOM wrapper
// HTML element selector
inputArray = domWrapper.findAll('input')
expectType<HTMLInputElement | undefined>(inputArray[0].element)

// SVG element selector
lineArray = domWrapper.findAll('line')
expectType<SVGLineElement | undefined>(lineArray[0].element)

// string selector
byClassArray = domWrapper.findAll('.todo')
expectType<Element | undefined>(byClassArray[0].element)

// get
// HTML element selector
let input = wrapper.get('input')
expectType<HTMLInputElement>(input.element)

// SVG element selector
let line = wrapper.get('line')
expectType<SVGLineElement>(line.element)

// string selector
let byClass = wrapper.get('.todo')
expectType<Element>(byClass.element)

// get DOM wrapper
// HTML element selector
input = domWrapper.get('input')
expectType<HTMLInputElement>(input.element)

// SVG element selector
line = domWrapper.get('line')
expectType<SVGLineElement>(line.element)

// string selector
byClass = domWrapper.get('.todo')
expectType<Element>(byClass.element)