diff --git a/docs/api/wrapper/README.md b/docs/api/wrapper/README.md index 2cfb8edb0..80346d1d1 100644 --- a/docs/api/wrapper/README.md +++ b/docs/api/wrapper/README.md @@ -20,6 +20,10 @@ A `Wrapper` is an object that contains a mounted component or vnode and methods `Boolean` (read-only): True if component is attached to document when rendered. +### `selector` + +`Selector`: the selector that was used by [`find()`](./find.md) or [`findAll()`](./findAll.md) to create this wrapper + ## Methods !!!include(docs/api/wrapper/attributes.md)!!! diff --git a/flow/wrapper.flow.js b/flow/wrapper.flow.js index 891722326..8bc2d2bf2 100644 --- a/flow/wrapper.flow.js +++ b/flow/wrapper.flow.js @@ -28,6 +28,7 @@ declare interface BaseWrapper { name(): string | void; props(key?: string): { [name: string]: any } | any | void; text(): string | void; + selector: Selector | void; setData(data: Object): void; setMethods(methods: Object): void; setValue(value: any): void; diff --git a/packages/test-utils/src/error-wrapper.js b/packages/test-utils/src/error-wrapper.js index 6b65d3d47..3365e1017 100644 --- a/packages/test-utils/src/error-wrapper.js +++ b/packages/test-utils/src/error-wrapper.js @@ -1,47 +1,73 @@ // @flow import { throwError } from 'shared/util' +import { REF_SELECTOR } from 'shared/consts' +import { getSelectorType } from './get-selector' + +const buildSelectorString = (selector: Selector) => { + if (getSelectorType(selector) === REF_SELECTOR) { + return `ref="${selector.value.ref}"` + } + + if (typeof selector === 'string') { + return selector + } + + return 'Component' +} export default class ErrorWrapper implements BaseWrapper { - selector: string + selector: Selector - constructor(selector: string) { + constructor(selector: Selector) { this.selector = selector } at(): void { throwError( - `find did not return ${this.selector}, cannot call at() on empty Wrapper` + `find did not return ${buildSelectorString( + this.selector + )}, cannot call at() on empty Wrapper` ) } attributes(): void { throwError( - `find did not return ${this.selector}, cannot call attributes() on empty Wrapper` + `find did not return ${buildSelectorString( + this.selector + )}, cannot call attributes() on empty Wrapper` ) } classes(): void { throwError( - `find did not return ${this.selector}, cannot call classes() on empty Wrapper` + `find did not return ${buildSelectorString( + this.selector + )}, cannot call classes() on empty Wrapper` ) } contains(): void { throwError( - `find did not return ${this.selector}, cannot call contains() on empty Wrapper` + `find did not return ${buildSelectorString( + this.selector + )}, cannot call contains() on empty Wrapper` ) } emitted(): void { throwError( - `find did not return ${this.selector}, cannot call emitted() on empty Wrapper` + `find did not return ${buildSelectorString( + this.selector + )}, cannot call emitted() on empty Wrapper` ) } emittedByOrder(): void { throwError( - `find did not return ${this.selector}, cannot call emittedByOrder() on empty Wrapper` + `find did not return ${buildSelectorString( + this.selector + )}, cannot call emittedByOrder() on empty Wrapper` ) } @@ -51,151 +77,201 @@ export default class ErrorWrapper implements BaseWrapper { filter(): void { throwError( - `find did not return ${this.selector}, cannot call filter() on empty Wrapper` + `find did not return ${buildSelectorString( + this.selector + )}, cannot call filter() on empty Wrapper` ) } visible(): void { throwError( - `find did not return ${this.selector}, cannot call visible() on empty Wrapper` + `find did not return ${buildSelectorString( + this.selector + )}, cannot call visible() on empty Wrapper` ) } hasAttribute(): void { throwError( - `find did not return ${this.selector}, cannot call hasAttribute() on empty Wrapper` + `find did not return ${buildSelectorString( + this.selector + )}, cannot call hasAttribute() on empty Wrapper` ) } hasClass(): void { throwError( - `find did not return ${this.selector}, cannot call hasClass() on empty Wrapper` + `find did not return ${buildSelectorString( + this.selector + )}, cannot call hasClass() on empty Wrapper` ) } hasProp(): void { throwError( - `find did not return ${this.selector}, cannot call hasProp() on empty Wrapper` + `find did not return ${buildSelectorString( + this.selector + )}, cannot call hasProp() on empty Wrapper` ) } hasStyle(): void { throwError( - `find did not return ${this.selector}, cannot call hasStyle() on empty Wrapper` + `find did not return ${buildSelectorString( + this.selector + )}, cannot call hasStyle() on empty Wrapper` ) } findAll(): void { throwError( - `find did not return ${this.selector}, cannot call findAll() on empty Wrapper` + `find did not return ${buildSelectorString( + this.selector + )}, cannot call findAll() on empty Wrapper` ) } find(): void { throwError( - `find did not return ${this.selector}, cannot call find() on empty Wrapper` + `find did not return ${buildSelectorString( + this.selector + )}, cannot call find() on empty Wrapper` ) } html(): void { throwError( - `find did not return ${this.selector}, cannot call html() on empty Wrapper` + `find did not return ${buildSelectorString( + this.selector + )}, cannot call html() on empty Wrapper` ) } is(): void { throwError( - `find did not return ${this.selector}, cannot call is() on empty Wrapper` + `find did not return ${buildSelectorString( + this.selector + )}, cannot call is() on empty Wrapper` ) } isEmpty(): void { throwError( - `find did not return ${this.selector}, cannot call isEmpty() on empty Wrapper` + `find did not return ${buildSelectorString( + this.selector + )}, cannot call isEmpty() on empty Wrapper` ) } isVisible(): void { throwError( - `find did not return ${this.selector}, cannot call isVisible() on empty Wrapper` + `find did not return ${buildSelectorString( + this.selector + )}, cannot call isVisible() on empty Wrapper` ) } isVueInstance(): void { throwError( - `find did not return ${this.selector}, cannot call isVueInstance() on empty Wrapper` + `find did not return ${buildSelectorString( + this.selector + )}, cannot call isVueInstance() on empty Wrapper` ) } name(): void { throwError( - `find did not return ${this.selector}, cannot call name() on empty Wrapper` + `find did not return ${buildSelectorString( + this.selector + )}, cannot call name() on empty Wrapper` ) } props(): void { throwError( - `find did not return ${this.selector}, cannot call props() on empty Wrapper` + `find did not return ${buildSelectorString( + this.selector + )}, cannot call props() on empty Wrapper` ) } text(): void { throwError( - `find did not return ${this.selector}, cannot call text() on empty Wrapper` + `find did not return ${buildSelectorString( + this.selector + )}, cannot call text() on empty Wrapper` ) } setComputed(): void { throwError( - `find did not return ${this.selector}, cannot call setComputed() on empty Wrapper` + `find did not return ${buildSelectorString( + this.selector + )}, cannot call setComputed() on empty Wrapper` ) } setData(): void { throwError( - `find did not return ${this.selector}, cannot call setData() on empty Wrapper` + `find did not return ${buildSelectorString( + this.selector + )}, cannot call setData() on empty Wrapper` ) } setMethods(): void { throwError( - `find did not return ${this.selector}, cannot call setMethods() on empty Wrapper` + `find did not return ${buildSelectorString( + this.selector + )}, cannot call setMethods() on empty Wrapper` ) } setProps(): void { throwError( - `find did not return ${this.selector}, cannot call setProps() on empty Wrapper` + `find did not return ${buildSelectorString( + this.selector + )}, cannot call setProps() on empty Wrapper` ) } setValue(): void { throwError( - `find did not return ${this.selector}, cannot call setValue() on empty Wrapper` + `find did not return ${buildSelectorString( + this.selector + )}, cannot call setValue() on empty Wrapper` ) } setChecked(): void { throwError( - `find did not return ${this.selector}, cannot call setChecked() on empty Wrapper` + `find did not return ${buildSelectorString( + this.selector + )}, cannot call setChecked() on empty Wrapper` ) } setSelected(): void { throwError( - `find did not return ${this.selector}, cannot call setSelected() on empty Wrapper` + `find did not return ${buildSelectorString( + this.selector + )}, cannot call setSelected() on empty Wrapper` ) } trigger(): void { throwError( - `find did not return ${this.selector}, cannot call trigger() on empty Wrapper` + `find did not return ${buildSelectorString( + this.selector + )}, cannot call trigger() on empty Wrapper` ) } destroy(): void { throwError( - `find did not return ${this.selector}, cannot call destroy() on empty Wrapper` + `find did not return ${buildSelectorString( + this.selector + )}, cannot call destroy() on empty Wrapper` ) } } diff --git a/packages/test-utils/src/get-selector.js b/packages/test-utils/src/get-selector.js index 33fbcc7db..6941ea002 100644 --- a/packages/test-utils/src/get-selector.js +++ b/packages/test-utils/src/get-selector.js @@ -15,7 +15,7 @@ import { INVALID_SELECTOR } from 'shared/consts' -function getSelectorType(selector: Selector): string { +export function getSelectorType(selector: Selector): string { if (isDomSelector(selector)) return DOM_SELECTOR if (isVueComponent(selector)) return COMPONENT_SELECTOR if (isNameSelector(selector)) return NAME_SELECTOR diff --git a/packages/test-utils/src/wrapper-array.js b/packages/test-utils/src/wrapper-array.js index 83458fb9c..7f2fda938 100644 --- a/packages/test-utils/src/wrapper-array.js +++ b/packages/test-utils/src/wrapper-array.js @@ -7,6 +7,7 @@ import { throwError } from 'shared/util' export default class WrapperArray implements BaseWrapper { +wrappers: Array +length: number + selector: Selector | void constructor(wrappers: Array) { const length = wrappers.length diff --git a/packages/test-utils/src/wrapper.js b/packages/test-utils/src/wrapper.js index 2a7326d8c..4810e75da 100644 --- a/packages/test-utils/src/wrapper.js +++ b/packages/test-utils/src/wrapper.js @@ -24,6 +24,7 @@ export default class Wrapper implements BaseWrapper { +options: WrapperOptions isFunctionalComponent: boolean rootNode: VNode | Element + selector: Selector | void constructor( node: VNode | Element, @@ -193,15 +194,12 @@ export default class Wrapper implements BaseWrapper { const node = find(this.rootNode, this.vm, selector)[0] if (!node) { - if (selector.type === REF_SELECTOR) { - return new ErrorWrapper(`ref="${selector.value.ref}"`) - } - return new ErrorWrapper( - typeof selector.value === 'string' ? selector.value : 'Component' - ) + return new ErrorWrapper(rawSelector) } - return createWrapper(node, this.options) + const wrapper = createWrapper(node, this.options) + wrapper.selector = rawSelector + return wrapper } /** @@ -214,9 +212,14 @@ export default class Wrapper implements BaseWrapper { const wrappers = nodes.map(node => { // Using CSS Selector, returns a VueWrapper instance if the root element // binds a Vue instance. - return createWrapper(node, this.options) + const wrapper = createWrapper(node, this.options) + wrapper.selector = rawSelector + return wrapper }) - return new WrapperArray(wrappers) + + const wrapperArray = new WrapperArray(wrappers) + wrapperArray.selector = rawSelector + return wrapperArray } /** diff --git a/packages/test-utils/types/index.d.ts b/packages/test-utils/types/index.d.ts index e1cdcfd64..28d0153b6 100644 --- a/packages/test-utils/types/index.d.ts +++ b/packages/test-utils/types/index.d.ts @@ -69,6 +69,7 @@ interface BaseWrapper { trigger (eventName: string, options?: object): void destroy (): void + selector: Selector | void } export interface Wrapper extends BaseWrapper { diff --git a/packages/test-utils/types/test/wrapper.ts b/packages/test-utils/types/test/wrapper.ts index 7aa2b538d..9e331c729 100644 --- a/packages/test-utils/types/test/wrapper.ts +++ b/packages/test-utils/types/test/wrapper.ts @@ -1,4 +1,4 @@ -import { mount, createWrapper } from '../' +import { mount, createWrapper, Selector } from '../' import { normalOptions, functionalOptions, ClassComponent } from './resources' import Vue from 'vue' @@ -44,19 +44,33 @@ wrapper.vm.$emit('event', 'arg') let el: HTMLElement = wrapper.element +let selector: Selector | void + let found = wrapper.find('.foo') +selector = found.selector found = wrapper.find(normalOptions) +selector = found.selector found = wrapper.find(functionalOptions) +selector = found.selector found = wrapper.find(ClassComponent) +selector = found.selector found = wrapper.find({ ref: 'myButton' }) +selector = found.selector found = wrapper.find({ name: 'my-button' }) +selector = found.selector let array = wrapper.findAll('.bar') +selector = array.selector array = wrapper.findAll(normalOptions) +selector = array.selector array = wrapper.findAll(functionalOptions) +selector = array.selector array = wrapper.findAll(ClassComponent) +selector = array.selector array = wrapper.findAll({ ref: 'myButton' }) +selector = array.selector array = wrapper.findAll({ name: 'my-button' }) +selector = array.selector wrapper.setChecked() wrapper.setChecked(true) diff --git a/test/specs/wrapper/find.spec.js b/test/specs/wrapper/find.spec.js index e8c4b4500..9d974d8d4 100644 --- a/test/specs/wrapper/find.spec.js +++ b/test/specs/wrapper/find.spec.js @@ -370,7 +370,7 @@ describeWithShallowAndMount('find', mountingMethod => { const wrapper = mountingMethod(Component) const error = wrapper.find(ComponentWithChild) expect(error.exists()).to.equal(false) - expect(error.selector).to.equal('Component') + expect(error.selector).to.equal(ComponentWithChild) }) it('returns Wrapper of elements matching the ref in options object', () => { @@ -458,9 +458,10 @@ describeWithShallowAndMount('find', mountingMethod => { it('returns empty Wrapper with error if no nodes are found via ref in options object', () => { const wrapper = mountingMethod(Component) - const error = wrapper.find({ ref: 'foo' }) + const selector = { ref: 'foo' } + const error = wrapper.find(selector) expect(error.exists()).to.equal(false) - expect(error.selector).to.equal('ref="foo"') + expect(error.selector).to.equal(selector) }) it('returns Wrapper matching component that has no name property', () => { @@ -542,4 +543,34 @@ describeWithShallowAndMount('find', mountingMethod => { expect(wrapper.find('p').vm.$options.name).to.equal('bar') } ) + + it('stores CSS selector', () => { + const compiled = compileToFunctions('

') + const wrapper = mountingMethod(compiled) + const selector = 'p' + const result = wrapper.find(selector) + expect(result.selector).to.equal(selector) + }) + + it('stores ref selector', () => { + const compiled = compileToFunctions('

') + const wrapper = mountingMethod(compiled) + const selector = { ref: 'foo' } + const result = wrapper.find(selector) + expect(result.selector).to.equal(selector) + }) + + it('stores component selector', () => { + const wrapper = mountingMethod(ComponentWithChild) + const selector = Component + const result = wrapper.find(selector) + expect(result.selector).to.equal(selector) + }) + + it('stores name selector', () => { + const wrapper = mountingMethod(ComponentWithChild) + const selector = { name: 'test-component' } + const result = wrapper.find(selector) + expect(result.selector).to.equal(selector) + }) }) diff --git a/test/specs/wrapper/findAll.spec.js b/test/specs/wrapper/findAll.spec.js index f02888730..c0ac72a5f 100644 --- a/test/specs/wrapper/findAll.spec.js +++ b/test/specs/wrapper/findAll.spec.js @@ -343,4 +343,38 @@ describeWithShallowAndMount('findAll', mountingMethod => { expect(wrappers.at(2).vm.$options.name).to.equal('bar') } ) + + it('stores CSS selector', () => { + const compiled = compileToFunctions('

') + const wrapper = mountingMethod(compiled) + const selector = 'p' + const result = wrapper.findAll('p') + expect(result.selector).to.equal(selector) + expect(result.at(0).selector).to.equal(selector) + }) + + it('stores ref selector', () => { + const compiled = compileToFunctions('
') + const wrapper = mountingMethod(compiled) + const selector = { ref: 'foo' } + const result = wrapper.findAll(selector) + expect(result.selector).to.equal(selector) + expect(result.at(0).selector).to.equal(selector) + }) + + it('stores component selector', () => { + const wrapper = mountingMethod(ComponentWithChild) + const selector = Component + const result = wrapper.findAll(selector) + expect(result.selector).to.equal(selector) + expect(result.at(0).selector).to.equal(selector) + }) + + it('stores name selector', () => { + const wrapper = mountingMethod(ComponentWithChild) + const selector = { name: 'test-component' } + const result = wrapper.findAll(selector) + expect(result.selector).to.equal(selector) + expect(result.at(0).selector).to.equal(selector) + }) })