From 351d80d038b1d7cf609f3ea66e2dce6b5ddb316f Mon Sep 17 00:00:00 2001 From: eddyerburgh Date: Sat, 27 Jan 2018 10:36:36 +0000 Subject: [PATCH] feat: add filter method to WrapperArray --- docs/en/SUMMARY.md | 1 + docs/en/api/wrapper-array/filter.md | 23 +++++++++++++++++++ flow/wrapper.flow.js | 1 + src/wrappers/error-wrapper.js | 4 ++++ src/wrappers/wrapper-array.js | 4 ++++ src/wrappers/wrapper.js | 4 ++++ test/unit/specs/mount/Wrapper/filter.spec.js | 12 ++++++++++ .../unit/specs/wrappers/error-wrapper.spec.js | 2 +- .../unit/specs/wrappers/wrapper-array.spec.js | 9 +++++++- types/index.d.ts | 1 + types/test/wrapper.ts | 1 + 11 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 docs/en/api/wrapper-array/filter.md create mode 100644 test/unit/specs/mount/Wrapper/filter.spec.js diff --git a/docs/en/SUMMARY.md b/docs/en/SUMMARY.md index b527547c2..b3910f9fd 100644 --- a/docs/en/SUMMARY.md +++ b/docs/en/SUMMARY.md @@ -53,6 +53,7 @@ * [contains](api/wrapper-array/contains.md) * [exists](api/wrapper/exists.md) * [destroy](api/wrapper-array/destroy.md) + * [filter](api/wrapper-array/filter.md) * [is](api/wrapper-array/is.md) * [isEmpty](api/wrapper-array/isEmpty.md) * [isVueInstance](api/wrapper-array/isVueInstance.md) diff --git a/docs/en/api/wrapper-array/filter.md b/docs/en/api/wrapper-array/filter.md new file mode 100644 index 000000000..3b02c4e31 --- /dev/null +++ b/docs/en/api/wrapper-array/filter.md @@ -0,0 +1,23 @@ +# filter(predicate) + +Filter `WrapperArray` with a predicate function on `Wrapper` objects. + +Behavior of this method is similar to [Array.prototype.filter](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Array/filter) + +- **Arguments:** + - `{function} predicate` + +- **Returns:** `{WrapperArray}` + +A new `WrapperArray` instance containing `Wrapper` instances that returns true for the predicate function. + +- **Example:** + +```js +import { shallow } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' + +const wrapper = shallow(Foo) +const filteredDivArray = wrapper.findAll('div', (w) => !w.hasClass('filtered')) +``` diff --git a/flow/wrapper.flow.js b/flow/wrapper.flow.js index 786e44334..0298d6ce2 100644 --- a/flow/wrapper.flow.js +++ b/flow/wrapper.flow.js @@ -13,6 +13,7 @@ declare interface BaseWrapper { // eslint-disable-line no-undef emitted(event?: string): { [name: string]: Array> } | Array> | void, emittedByOrder(): Array<{ name: string; args: Array }> | void, exists(): boolean, + filter(predicate: Function): WrapperArray | void, visible(): boolean | void, hasAttribute(attribute: string, value: string): boolean | void, hasClass(className: string): boolean | void, diff --git a/src/wrappers/error-wrapper.js b/src/wrappers/error-wrapper.js index 535faf27f..c163fe577 100644 --- a/src/wrappers/error-wrapper.js +++ b/src/wrappers/error-wrapper.js @@ -36,6 +36,10 @@ export default class ErrorWrapper implements BaseWrapper { return false } + filter (): void { + throwError(`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`) } diff --git a/src/wrappers/wrapper-array.js b/src/wrappers/wrapper-array.js index 5a2f26ba1..81e1e1b0a 100644 --- a/src/wrappers/wrapper-array.js +++ b/src/wrappers/wrapper-array.js @@ -42,6 +42,10 @@ export default class WrapperArray implements BaseWrapper { return this.length > 0 && this.wrappers.every(wrapper => wrapper.exists()) } + filter (predicate: Function): WrapperArray { + return new WrapperArray(this.wrappers.filter(predicate)) + } + visible (): boolean { this.throwErrorIfWrappersIsEmpty('visible') diff --git a/src/wrappers/wrapper.js b/src/wrappers/wrapper.js index d9c4b9246..efc9fc730 100644 --- a/src/wrappers/wrapper.js +++ b/src/wrappers/wrapper.js @@ -125,6 +125,10 @@ export default class Wrapper implements BaseWrapper { return true } + filter () { + throwError('filter() must be called on a WrapperArray') + } + /** * Utility to check wrapper is visible. Returns false if a parent element has display: none or visibility: hidden style. */ diff --git a/test/unit/specs/mount/Wrapper/filter.spec.js b/test/unit/specs/mount/Wrapper/filter.spec.js new file mode 100644 index 000000000..4d6c409f5 --- /dev/null +++ b/test/unit/specs/mount/Wrapper/filter.spec.js @@ -0,0 +1,12 @@ +import { compileToFunctions } from 'vue-template-compiler' +import { mount } from '~vue-test-utils' + +describe('filter', () => { + it('throws an error', () => { + const compiled = compileToFunctions('
') + const wrapper = mount(compiled) + const message = '[vue-test-utils]: filter() must be called on a WrapperArray' + const fn = () => wrapper.filter() + expect(fn).to.throw().with.property('message', message) + }) +}) diff --git a/test/unit/specs/wrappers/error-wrapper.spec.js b/test/unit/specs/wrappers/error-wrapper.spec.js index fae47e1c7..9981cb2b3 100644 --- a/test/unit/specs/wrappers/error-wrapper.spec.js +++ b/test/unit/specs/wrappers/error-wrapper.spec.js @@ -3,7 +3,7 @@ import { compileToFunctions } from 'vue-template-compiler' describe('ErrorWrapper', () => { const methods = ['at', 'attributes', 'classes', 'contains', 'emitted', 'emittedByOrder', 'hasAttribute', - 'hasClass', 'hasProp', 'hasStyle', 'find', 'findAll', 'html', 'text', 'is', 'isEmpty', 'isVueInstance', + 'hasClass', 'hasProp', 'hasStyle', 'find', 'findAll', 'filter', 'html', 'text', 'is', 'isEmpty', 'isVueInstance', 'name', 'props', 'setComputed', 'setMethods', 'setData', 'setProps', 'trigger', 'update', 'destroy'] methods.forEach((method) => { it(`${method} throws error when called`, () => { diff --git a/test/unit/specs/wrappers/wrapper-array.spec.js b/test/unit/specs/wrappers/wrapper-array.spec.js index bf3bbe4b1..6c2caccbf 100644 --- a/test/unit/specs/wrappers/wrapper-array.spec.js +++ b/test/unit/specs/wrappers/wrapper-array.spec.js @@ -14,7 +14,7 @@ describe('WrapperArray', () => { return wrapperArray } - it('returns class with length equal to lenght of wrappers passed in constructor', () => { + it('returns class with length equal to length of wrappers passed in constructor', () => { const wrapperArray = getWrapperArray() expect(wrapperArray.length).to.equal(3) }) @@ -24,6 +24,13 @@ describe('WrapperArray', () => { expect(wrapperArray.at(0).text()).to.equal('1') }) + it('returns filtered wrapper when filter is called', () => { + const wrapperArray = getWrapperArray() + expect(wrapperArray.filter(w => { + return w.text() !== '2' + }).length).to.equal(2) + }) + const methods = ['at', 'attributes', 'classes', 'contains', 'emitted', 'emittedByOrder', 'hasAttribute', 'hasClass', 'hasProp', 'hasStyle', 'find', 'findAll', 'html', 'text', 'is', 'isEmpty', 'isVueInstance', 'name', 'props', 'setComputed', 'setMethods', 'setData', 'setProps', 'trigger', 'update', 'destroy'] diff --git a/types/index.d.ts b/types/index.d.ts index 1e8b51d01..295f3df98 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -99,6 +99,7 @@ interface WrapperArray extends BaseWrapper { readonly wrappers: Array> at (index: number): Wrapper + filter (predicate: Function): WrapperArray } interface WrapperOptions { diff --git a/types/test/wrapper.ts b/types/test/wrapper.ts index 5ecf7465d..f92d79632 100644 --- a/types/test/wrapper.ts +++ b/types/test/wrapper.ts @@ -67,3 +67,4 @@ str = wrapper.name() */ let num: number = array.length found = array.at(1) +array = array.filter((a: any) => a === true)