From ea39a3fa862fc25fcbf65054eee5ca5ad3cbff6c Mon Sep 17 00:00:00 2001 From: Tomas Bjerre Date: Sun, 8 Sep 2019 09:28:05 +0200 Subject: [PATCH 1/6] Adding get method to Wrapper #1298 To have it fail with a clear error message when selector does not match an existing element. --- packages/test-utils/src/wrapper.js | 12 ++++++++++++ packages/test-utils/types/index.d.ts | 7 +++++++ packages/test-utils/types/test/wrapper.ts | 7 +++++++ test/specs/wrapper/get.spec.js | 20 ++++++++++++++++++++ 4 files changed, 46 insertions(+) create mode 100644 test/specs/wrapper/get.spec.js diff --git a/packages/test-utils/src/wrapper.js b/packages/test-utils/src/wrapper.js index 956227a8b..79e01a560 100644 --- a/packages/test-utils/src/wrapper.js +++ b/packages/test-utils/src/wrapper.js @@ -184,6 +184,18 @@ export default class Wrapper implements BaseWrapper { throwError('filter() must be called on a WrapperArray') } + /** + * Gets first node in tree of the current wrapper that + * matches the provided selector. + */ + get(rawSelector: Selector): Wrapper { + const found = this.find(rawSelector) + if (found instanceof ErrorWrapper) { + throw new Error(`Unable to find ${rawSelector} within: ${this.html()}`) + } + return found + } + /** * Finds first node in tree of the current wrapper that * matches the provided selector. diff --git a/packages/test-utils/types/index.d.ts b/packages/test-utils/types/index.d.ts index 4ba612c90..b1f22a077 100644 --- a/packages/test-utils/types/index.d.ts +++ b/packages/test-utils/types/index.d.ts @@ -76,6 +76,13 @@ export interface Wrapper extends BaseWrapper { readonly element: HTMLElement readonly options: WrapperOptions + get (selector: VueClass): Wrapper + get (selector: ComponentOptions): Wrapper + get (selector: FunctionalComponentOptions): Wrapper + get (selector: string): Wrapper + get (selector: RefSelector): Wrapper + get (selector: NameSelector): Wrapper + find (selector: VueClass): Wrapper find (selector: ComponentOptions): Wrapper find (selector: FunctionalComponentOptions): Wrapper diff --git a/packages/test-utils/types/test/wrapper.ts b/packages/test-utils/types/test/wrapper.ts index 7aa2b538d..1ef259bbb 100644 --- a/packages/test-utils/types/test/wrapper.ts +++ b/packages/test-utils/types/test/wrapper.ts @@ -58,6 +58,13 @@ array = wrapper.findAll(ClassComponent) array = wrapper.findAll({ ref: 'myButton' }) array = wrapper.findAll({ name: 'my-button' }) +let gotten = wrapper.get('.foo') +gotten = wrapper.get(normalOptions) +gotten = wrapper.get(functionalOptions) +gotten = wrapper.get(ClassComponent) +gotten = wrapper.get({ ref: 'myButton' }) +gotten = wrapper.get({ name: 'my-button' }) + wrapper.setChecked() wrapper.setChecked(true) wrapper.setValue('some string') diff --git a/test/specs/wrapper/get.spec.js b/test/specs/wrapper/get.spec.js new file mode 100644 index 000000000..5afba8e9b --- /dev/null +++ b/test/specs/wrapper/get.spec.js @@ -0,0 +1,20 @@ +import { compileToFunctions } from 'vue-template-compiler' +import { describeWithShallowAndMount } from '~resources/utils' + +describeWithShallowAndMount('get', mountingMethod => { + it('throws describing error when element not found', () => { + const compiled = compileToFunctions('
') + const wrapper = mountingMethod(compiled) + expect(() => wrapper.get('.does-not-exist')) + .to.throw() + .with.property( + 'message', + 'Unable to find .does-not-exist within:
' + ) + }) + it('gets the element when element is found', () => { + const compiled = compileToFunctions('
') + const wrapper = mountingMethod(compiled) + expect(wrapper.get('.does-exist')).to.be.an('object') + }) +}) From 7e3f2273bb4857f3d1df899d49c48b19b89d823a Mon Sep 17 00:00:00 2001 From: Tomas Bjerre Date: Tue, 3 Dec 2019 18:58:03 +0100 Subject: [PATCH 2/6] Documenting get method on wrapper #1298 --- docs/README.md | 1 + docs/api/wrapper/README.md | 1 + docs/api/wrapper/get.md | 19 +++++++++++++++++++ 3 files changed, 21 insertions(+) create mode 100644 docs/api/wrapper/get.md diff --git a/docs/README.md b/docs/README.md index c5baa3ff7..502e329be 100644 --- a/docs/README.md +++ b/docs/README.md @@ -44,6 +44,7 @@ Vue Test Utils is the official unit testing utility library for Vue.js. - [destroy](api/wrapper/destroy.md) - [find](api/wrapper/find.md) - [findAll](api/wrapper/findAll.md) + - [get](api/wrapper/get.md) - [html](api/wrapper/html.md) - [is](api/wrapper/is.md) - [isEmpty](api/wrapper/isEmpty.md) diff --git a/docs/api/wrapper/README.md b/docs/api/wrapper/README.md index a77421a90..d84d67b44 100644 --- a/docs/api/wrapper/README.md +++ b/docs/api/wrapper/README.md @@ -36,6 +36,7 @@ A `Wrapper` is an object that contains a mounted component or vnode and methods !!!include(docs/api/wrapper/find.md)!!! !!!include(docs/api/wrapper/findAll.md)!!! !!!include(docs/api/wrapper/html.md)!!! +!!!include(docs/api/wrapper/get.md)!!! !!!include(docs/api/wrapper/is.md)!!! !!!include(docs/api/wrapper/isEmpty.md)!!! !!!include(docs/api/wrapper/isVisible.md)!!! diff --git a/docs/api/wrapper/get.md b/docs/api/wrapper/get.md new file mode 100644 index 000000000..368c545c9 --- /dev/null +++ b/docs/api/wrapper/get.md @@ -0,0 +1,19 @@ +## get + +Works just like [find](../find.md) but will throw an error if selector not +matching anything. You should use `find` when searching for an element that +may not exist. You should use this method when getting an element that should +exist and it will provide a nice error message if that is not the case. + +```js +import { mount } from '@vue/test-utils' + +const wrapper = mount(Foo) + +expect(() => wrapper.get('.does-not-exist')) + .to.throw() + .with.property( + 'message', + 'Unable to find .does-not-exist within:
the actual DOM here...
' + ) +``` From b41b9514cf0375cb537bac6b162d626de368ab56 Mon Sep 17 00:00:00 2001 From: Tomas Bjerre Date: Wed, 4 Dec 2019 14:01:29 +0100 Subject: [PATCH 3/6] Adjusting docs on get method on wrapper #1298 --- docs/api/wrapper/get.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/api/wrapper/get.md b/docs/api/wrapper/get.md index 368c545c9..077330ac9 100644 --- a/docs/api/wrapper/get.md +++ b/docs/api/wrapper/get.md @@ -1,8 +1,8 @@ ## get -Works just like [find](../find.md) but will throw an error if selector not -matching anything. You should use `find` when searching for an element that -may not exist. You should use this method when getting an element that should +Works just like [find](../find.md) but will throw an error if nothing matching +the given selector is found. You should use `find` when searching for an element +that may not exist. You should use this method when getting an element that should exist and it will provide a nice error message if that is not the case. ```js From 726262c10077ad7e38cf1382513b74ea99b33742 Mon Sep 17 00:00:00 2001 From: Lachlan Miller Date: Thu, 16 Jan 2020 23:17:25 +1000 Subject: [PATCH 4/6] docs: update --- docs/api/wrapper/find.md | 2 + docs/api/wrapper/get.md | 4 + packages/test-utils/src/error-wrapper.js | 116 ++++++----------------- 3 files changed, 35 insertions(+), 87 deletions(-) diff --git a/docs/api/wrapper/find.md b/docs/api/wrapper/find.md index 98b69c399..04c6c282e 100644 --- a/docs/api/wrapper/find.md +++ b/docs/api/wrapper/find.md @@ -31,3 +31,5 @@ expect(barByName.is(Bar)).toBe(true) const fooRef = wrapper.find({ ref: 'foo' }) expect(fooRef.is(Foo)).toBe(true) ``` + +See also: [get](../get.md). diff --git a/docs/api/wrapper/get.md b/docs/api/wrapper/get.md index 077330ac9..abc34e9c7 100644 --- a/docs/api/wrapper/get.md +++ b/docs/api/wrapper/get.md @@ -10,6 +10,10 @@ import { mount } from '@vue/test-utils' const wrapper = mount(Foo) +// similar to `wrapper.find`. +`get` will throw an error if an element is not found. `find` will do nothing. +expect(wrapper.get('.does-exist')) + expect(() => wrapper.get('.does-not-exist')) .to.throw() .with.property( diff --git a/packages/test-utils/src/error-wrapper.js b/packages/test-utils/src/error-wrapper.js index c7da711db..6b65d3d47 100644 --- a/packages/test-utils/src/error-wrapper.js +++ b/packages/test-utils/src/error-wrapper.js @@ -17,41 +17,31 @@ export default class ErrorWrapper implements BaseWrapper { attributes(): void { throwError( - `find did not return ${ - this.selector - }, cannot call attributes() on empty Wrapper` + `find did not return ${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 ${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 ${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 ${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 ${this.selector}, cannot call emittedByOrder() on empty Wrapper` ) } @@ -61,73 +51,55 @@ 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 ${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 ${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 ${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 ${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 ${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 ${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 ${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 ${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 ${this.selector}, cannot call html() on empty Wrapper` ) } @@ -139,121 +111,91 @@ export default class ErrorWrapper implements BaseWrapper { isEmpty(): void { throwError( - `find did not return ${ - this.selector - }, cannot call isEmpty() on empty Wrapper` + `find did not return ${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 ${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 ${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 ${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 ${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 ${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 ${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 ${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 ${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 ${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 ${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 ${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 ${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 ${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 ${this.selector}, cannot call destroy() on empty Wrapper` ) } } From a34e5b129c3b5ee8aa9a10b6c21ced124f617bb2 Mon Sep 17 00:00:00 2001 From: Lachlan Miller Date: Thu, 16 Jan 2020 23:25:37 +1000 Subject: [PATCH 5/6] chore: resolve conflict --- packages/test-utils/src/error-wrapper.js | 34 +++++++----------------- 1 file changed, 9 insertions(+), 25 deletions(-) diff --git a/packages/test-utils/src/error-wrapper.js b/packages/test-utils/src/error-wrapper.js index e6db9715d..3365e1017 100644 --- a/packages/test-utils/src/error-wrapper.js +++ b/packages/test-utils/src/error-wrapper.js @@ -56,10 +56,11 @@ export default class ErrorWrapper implements BaseWrapper { } emitted(): void { + throwError( `find did not return ${buildSelectorString( this.selector )}, cannot call emitted() on empty Wrapper` -) + ) } emittedByOrder(): void { @@ -71,14 +72,15 @@ export default class ErrorWrapper implements BaseWrapper { } exists(): boolean { -) + return false } filter(): void { + throwError( `find did not return ${buildSelectorString( this.selector )}, cannot call filter() on empty Wrapper` -) + ) } visible(): void { @@ -90,22 +92,23 @@ export default class ErrorWrapper implements BaseWrapper { } hasAttribute(): void { + throwError( `find did not return ${buildSelectorString( this.selector )}, cannot call hasAttribute() on empty Wrapper` -) + ) } hasClass(): void { + throwError( `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` @@ -114,7 +117,6 @@ export default class ErrorWrapper implements BaseWrapper { 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` @@ -123,7 +125,6 @@ export default class ErrorWrapper implements BaseWrapper { 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` @@ -132,7 +133,6 @@ export default class ErrorWrapper implements BaseWrapper { 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` @@ -141,7 +141,6 @@ export default class ErrorWrapper implements BaseWrapper { 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` @@ -158,7 +157,6 @@ export default class ErrorWrapper implements BaseWrapper { 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` @@ -167,7 +165,6 @@ export default class ErrorWrapper implements BaseWrapper { 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` @@ -176,7 +173,6 @@ export default class ErrorWrapper implements BaseWrapper { 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` @@ -185,7 +181,6 @@ export default class ErrorWrapper implements BaseWrapper { 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` @@ -194,7 +189,6 @@ export default class ErrorWrapper implements BaseWrapper { 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` @@ -203,7 +197,6 @@ export default class ErrorWrapper implements BaseWrapper { 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` @@ -212,7 +205,6 @@ export default class ErrorWrapper implements BaseWrapper { 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` @@ -221,7 +213,6 @@ export default class ErrorWrapper implements BaseWrapper { 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` @@ -230,7 +221,6 @@ export default class ErrorWrapper implements BaseWrapper { 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` @@ -239,7 +229,6 @@ export default class ErrorWrapper implements BaseWrapper { 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` @@ -248,7 +237,6 @@ export default class ErrorWrapper implements BaseWrapper { 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` @@ -257,7 +245,6 @@ export default class ErrorWrapper implements BaseWrapper { 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` @@ -266,7 +253,6 @@ export default class ErrorWrapper implements BaseWrapper { 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` @@ -275,7 +261,6 @@ export default class ErrorWrapper implements BaseWrapper { 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` @@ -284,7 +269,6 @@ export default class ErrorWrapper implements BaseWrapper { 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` From 5ee369ce8f0276ad4cf5a8f5666ec8eb792c5bd3 Mon Sep 17 00:00:00 2001 From: Lachlan Miller Date: Thu, 16 Jan 2020 23:49:42 +1000 Subject: [PATCH 6/6] docs: linting --- docs/api/wrapper/get.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/wrapper/get.md b/docs/api/wrapper/get.md index abc34e9c7..d1ebd7d13 100644 --- a/docs/api/wrapper/get.md +++ b/docs/api/wrapper/get.md @@ -11,7 +11,7 @@ import { mount } from '@vue/test-utils' const wrapper = mount(Foo) // similar to `wrapper.find`. -`get` will throw an error if an element is not found. `find` will do nothing. +// `get` will throw an error if an element is not found. `find` will do nothing. expect(wrapper.get('.does-exist')) expect(() => wrapper.get('.does-not-exist'))