From cc36d3eefeab30ab57dd6d2bbedb9175b7904420 Mon Sep 17 00:00:00 2001 From: Tim Hutchinson Date: Sat, 28 Oct 2017 21:05:44 -0400 Subject: [PATCH 1/4] Add classes wrapper method --- src/wrappers/error-wrapper.js | 4 ++++ src/wrappers/wrapper-array.js | 6 ++++++ src/wrappers/wrapper.js | 7 +++++++ test/unit/specs/mount/Wrapper/classes.spec.js | 17 +++++++++++++++++ .../specs/mount/WrapperArray/classes.spec.js | 18 ++++++++++++++++++ test/unit/specs/wrappers/error-wrapper.spec.js | 7 +++++++ test/unit/specs/wrappers/wrapper-array.spec.js | 12 ++++++++++++ 7 files changed, 71 insertions(+) create mode 100644 test/unit/specs/mount/Wrapper/classes.spec.js create mode 100644 test/unit/specs/mount/WrapperArray/classes.spec.js diff --git a/src/wrappers/error-wrapper.js b/src/wrappers/error-wrapper.js index 16fe1e8bc..21e93f94d 100644 --- a/src/wrappers/error-wrapper.js +++ b/src/wrappers/error-wrapper.js @@ -12,6 +12,10 @@ export default class ErrorWrapper implements BaseWrapper { throwError(`find did not return ${this.selector}, cannot call at() on empty Wrapper`) } + classes (): void { + throwError(`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`) } diff --git a/src/wrappers/wrapper-array.js b/src/wrappers/wrapper-array.js index 8cbddbd0d..e2b27ec40 100644 --- a/src/wrappers/wrapper-array.js +++ b/src/wrappers/wrapper-array.js @@ -20,6 +20,12 @@ export default class WrapperArray implements BaseWrapper { return this.wrappers[index] } + classes (): void { + this.throwErrorIfWrappersIsEmpty('classes') + + throwError('classes must be called on a single wrapper, use at(i) to access a wrapper') + } + contains (selector: Selector): boolean { this.throwErrorIfWrappersIsEmpty('contains') diff --git a/src/wrappers/wrapper.js b/src/wrappers/wrapper.js index 6c50e4d1f..f82c52571 100644 --- a/src/wrappers/wrapper.js +++ b/src/wrappers/wrapper.js @@ -32,6 +32,13 @@ export default class Wrapper implements BaseWrapper { throwError('at() must be called on a WrapperArray') } + /** + * Returns an Array containing all the classes on the element + */ + classes (): Array { + return [...this.element.classList] + } + /** * Checks if wrapper contains provided selector. */ diff --git a/test/unit/specs/mount/Wrapper/classes.spec.js b/test/unit/specs/mount/Wrapper/classes.spec.js new file mode 100644 index 000000000..bcfbdc63d --- /dev/null +++ b/test/unit/specs/mount/Wrapper/classes.spec.js @@ -0,0 +1,17 @@ + +import { compileToFunctions } from 'vue-template-compiler' +import mount from '~src/mount' + +describe('classes', () => { + it('returns array of class names if wrapper has class names', () => { + const compiled = compileToFunctions('
') + const wrapper = mount(compiled) + expect(wrapper.classes()).to.eql(['a-class', 'b-class']) + }) + + it('returns empty array if wrapper has no classes', () => { + const compiled = compileToFunctions('
') + const wrapper = mount(compiled) + expect(wrapper.classes()).to.eql([]) + }) +}) diff --git a/test/unit/specs/mount/WrapperArray/classes.spec.js b/test/unit/specs/mount/WrapperArray/classes.spec.js new file mode 100644 index 000000000..d900fd26f --- /dev/null +++ b/test/unit/specs/mount/WrapperArray/classes.spec.js @@ -0,0 +1,18 @@ +import { compileToFunctions } from 'vue-template-compiler' +import mount from '~src/mount' + +describe('classes', () => { + it('throws error if wrapper array contains no items', () => { + const compiled = compileToFunctions('
') + const message = '[vue-test-utils]: classes cannot be called on 0 items' + expect(() => mount(compiled).findAll('p').classes('p')).to.throw().with.property('message', message) + }) + + it('throws error when called on a WrapperArray', () => { + const compiled = compileToFunctions('
') + const wrapper = mount(compiled) + const message = '[vue-test-utils]: classes must be called on a single wrapper, use at(i) to access a wrapper' + const fn = () => wrapper.findAll('div').classes() + 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 3b78eeac4..0dc125822 100644 --- a/test/unit/specs/wrappers/error-wrapper.spec.js +++ b/test/unit/specs/wrappers/error-wrapper.spec.js @@ -8,6 +8,13 @@ describe('ErrorWrapper', () => { expect(() => error.at()).to.throw().with.property('message', message) }) + it('classes throws error when called', () => { + const selector = 'div' + const message = `[vue-test-utils]: find did not return ${selector}, cannot call classes() on empty Wrapper` + const error = new ErrorWrapper(selector) + expect(() => error.classes()).to.throw().with.property('message', message) + }) + it('contains throws error when called', () => { const selector = 'div' const message = `[vue-test-utils]: find did not return ${selector}, cannot call contains() on empty Wrapper` diff --git a/test/unit/specs/wrappers/wrapper-array.spec.js b/test/unit/specs/wrappers/wrapper-array.spec.js index cba5407e4..12880f294 100644 --- a/test/unit/specs/wrappers/wrapper-array.spec.js +++ b/test/unit/specs/wrappers/wrapper-array.spec.js @@ -59,6 +59,18 @@ describe('WrapperArray', () => { expect(() => wrapperArray.findAll()).to.throw().with.property('message', message) }) + it('classes throws error if called when there are 0 items in wrapper array', () => { + const wrapperArray = new WrapperArray() + const message = '[vue-test-utils]: classes cannot be called on 0 items' + expect(() => wrapperArray.classes()).to.throw().with.property('message', message) + }) + + it('classes throws error if called when there are items in wrapper array', () => { + const wrapperArray = new WrapperArray([1]) + const message = '[vue-test-utils]: classes must be called on a single wrapper, use at(i) to access a wrapper' + expect(() => wrapperArray.classes()).to.throw().with.property('message', message) + }) + it('contains returns true if every wrapper.contains() returns true', () => { const selector = 'selector' const contains = sinon.stub() From 6b20d30a82a1105c6f4dc9edc80a2963d59db354 Mon Sep 17 00:00:00 2001 From: Tim Hutchinson Date: Tue, 31 Oct 2017 07:19:24 -0400 Subject: [PATCH 2/4] Add support for css modules --- src/wrappers/wrapper.js | 15 ++++++++++++++- .../components/component-with-css-modules.vue | 7 ++++++- test/unit/specs/mount/Wrapper/classes.spec.js | 7 +++++++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/wrappers/wrapper.js b/src/wrappers/wrapper.js index f82c52571..9f568d728 100644 --- a/src/wrappers/wrapper.js +++ b/src/wrappers/wrapper.js @@ -36,7 +36,20 @@ export default class Wrapper implements BaseWrapper { * Returns an Array containing all the classes on the element */ classes (): Array { - return [...this.element.classList] + let classes = [...this.element.classList] + // Handle converting cssmodules identifiers back to the original class name + if (this.vm && this.vm.$style) { + const cssModuleIdentifiers = {} + let moduleIdent + Object.keys(this.vm.$style).forEach((key) => { + moduleIdent = this.vm.$style[key] + // CSS Modules may be multi-class if they extend others. Extended classes should be already present in $style. + moduleIdent = moduleIdent.split(' ')[0] + cssModuleIdentifiers[moduleIdent] = key + }) + classes = classes.map(className => cssModuleIdentifiers[className] || className) + } + return classes } /** diff --git a/test/resources/components/component-with-css-modules.vue b/test/resources/components/component-with-css-modules.vue index 946af93fe..67f25e301 100644 --- a/test/resources/components/component-with-css-modules.vue +++ b/test/resources/components/component-with-css-modules.vue @@ -1,11 +1,16 @@