From 61ee2c9700d81fd4c7d0a1a200abc0edf3c50d92 Mon Sep 17 00:00:00 2001 From: root Date: Sat, 28 Mar 2020 19:42:51 +0100 Subject: [PATCH 1/6] feat(test-utils): add 'overview' function close #1461 --- docs/api/wrapper/overview.md | 43 +++ flow/wrapper.flow.js | 1 + packages/test-utils/src/wrapper-array.js | 9 + packages/test-utils/src/wrapper.js | 47 +++ test/specs/wrapper-array/overview.spec.js | 24 ++ test/specs/wrapper/overview.spec.js | 334 ++++++++++++++++++++++ 6 files changed, 458 insertions(+) create mode 100644 docs/api/wrapper/overview.md create mode 100644 test/specs/wrapper-array/overview.spec.js create mode 100644 test/specs/wrapper/overview.spec.js diff --git a/docs/api/wrapper/overview.md b/docs/api/wrapper/overview.md new file mode 100644 index 000000000..2130b6e46 --- /dev/null +++ b/docs/api/wrapper/overview.md @@ -0,0 +1,43 @@ +## overview + +Prints a simple overview of the `Wrapper`. + +- **Example:** + +```js +import { mount } from '@vue/test-utils' +import Component from './Component.vue' + +const wrapper = mount(Component) +wrapper.overview() + +// Console output +/* +Wrapper (Visible): + +Html: +
+

My name is Tess Ting

+
+ +Data: { + firstName: Tess, + lastName: Ting +} + +Computed: { + fullName: Tess Ting' +} + +Emitted: {', + foo: [', + 0: [ hello, world ], + 1: [ bye, world ]' + ], + bar: [ + 0: [ hey ]' + ] +} + +*/ +``` diff --git a/flow/wrapper.flow.js b/flow/wrapper.flow.js index 8bc2d2bf2..e37c3d558 100644 --- a/flow/wrapper.flow.js +++ b/flow/wrapper.flow.js @@ -26,6 +26,7 @@ declare interface BaseWrapper { isVisible(): boolean | void; isVueInstance(): boolean | void; name(): string | void; + overview(): void; props(key?: string): { [name: string]: any } | any | void; text(): string | void; selector: Selector | void; diff --git a/packages/test-utils/src/wrapper-array.js b/packages/test-utils/src/wrapper-array.js index 6a15bcb6d..12ca36844 100644 --- a/packages/test-utils/src/wrapper-array.js +++ b/packages/test-utils/src/wrapper-array.js @@ -143,6 +143,15 @@ export default class WrapperArray implements BaseWrapper { ) } + overview(): void { + this.throwErrorIfWrappersIsEmpty('overview()') + + throwError( + `overview() must be called on a single wrapper, use at(i) ` + + `to access a wrapper` + ) + } + props(): void { this.throwErrorIfWrappersIsEmpty('props') diff --git a/packages/test-utils/src/wrapper.js b/packages/test-utils/src/wrapper.js index ea31cf192..192603a08 100644 --- a/packages/test-utils/src/wrapper.js +++ b/packages/test-utils/src/wrapper.js @@ -324,6 +324,53 @@ export default class Wrapper implements BaseWrapper { return this.vnode.tag } + /** + * Prints a simple overview of the wrapper current state + * with useful information for debugging + */ + overview(): void { + if (!this.isVueInstance()) { + throwError(`wrapper.overview() can only be called on a Vue instance`) + } + const identation = 4 + const formatJSON = (json: string, replacer: Function = null) => + JSON.stringify(json, replacer, identation).replace(/"/g, '') + + const visibility = this.isVisible() ? 'Visible' : 'Not visible' + + const html = this.html() + ? this.html().replace(/^(?!\s*$)/gm, ' '.repeat(identation)) + '\n' + : '' + + const data = formatJSON(this.vm.$data) + + const computed = this.vm._computedWatchers + ? formatJSON( + ...Object.keys(this.vm._computedWatchers).map(computedKey => ({ + [computedKey]: this.vm[computedKey] + })) + ) + : '{}' + + const emittedJSONReplacer = (key, value) => + value instanceof Array + ? value.map( + (calledWith, index) => `${index}: [ ${calledWith.join(', ')} ]` + ) + : value + + const emitted = formatJSON(this.emitted(), emittedJSONReplacer) + + console.log( + '\n' + + `Wrapper (${visibility}):\n\n` + + `Html:\n${html}\n` + + `Data: ${data}\n\n` + + `Computed: ${computed}\n\n` + + `Emitted: ${emitted}\n` + ) + } + /** * Returns an Object containing the prop name/value pairs on the element */ diff --git a/test/specs/wrapper-array/overview.spec.js b/test/specs/wrapper-array/overview.spec.js new file mode 100644 index 000000000..5bdb37a8e --- /dev/null +++ b/test/specs/wrapper-array/overview.spec.js @@ -0,0 +1,24 @@ +import { describeWithShallowAndMount } from '~resources/utils' +import { compileToFunctions } from 'vue-template-compiler' +import '@vue/test-utils' + +describeWithShallowAndMount('overview', mountingMethod => { + it('throws error if wrapper array contains no items', () => { + const wrapper = mountingMethod(compileToFunctions('
')) + const message = '[vue-test-utils]: overview() cannot be called on 0 items' + + expect(() => wrapper.findAll('p').overview()) + .to.throw() + .with.property('message', message) + }) + + it('throws error when called on a WrapperArray', () => { + const wrapper = mountingMethod(compileToFunctions('
')) + const message = + '[vue-test-utils]: overview() must be called on a single wrapper, use at(i) to access a wrapper' + + expect(() => wrapper.findAll('div').overview()) + .to.throw() + .with.property('message', message) + }) +}) diff --git a/test/specs/wrapper/overview.spec.js b/test/specs/wrapper/overview.spec.js new file mode 100644 index 000000000..92aa61093 --- /dev/null +++ b/test/specs/wrapper/overview.spec.js @@ -0,0 +1,334 @@ +import { describeWithShallowAndMount } from '~resources/utils' + +describeWithShallowAndMount('overview', mountingMethod => { + const originalLog = console.log + let consoleOutput = [] + const consoleLogMock = (...output) => + consoleOutput.push(...output.join(' ').split('\n')) + + beforeEach(() => { + consoleOutput = [] + console.log = consoleLogMock + }) + afterEach(() => (console.log = originalLog)) + + it('prints a simple overview of the Wrapper', () => { + const wrapper = mountingMethod({ + template: + '

My name is {{ firstName }} {{ lastName }}

', + data() { + return { + firstName: 'Tess', + lastName: 'Ting' + } + }, + computed: { + onePlusOne: () => 1 + 1 + } + }) + wrapper.vm.$emit('foo', 'hello', 'world') + wrapper.vm.$emit('foo', 'bye', 'world') + wrapper.vm.$emit('bar', 'hey') + + const expectedConsoleOutput = [ + '', + 'Wrapper (Visible):', + '', + 'Html:', + '
', + '

My name is Tess Ting

', + '
', + '', + 'Data: {', + ' firstName: Tess,', + ' lastName: Ting', + '}', + '', + 'Computed: {', + ' onePlusOne: 2', + '}', + '', + 'Emitted: {', + ' foo: [', + ' 0: [ hello, world ],', + ' 1: [ bye, world ]', + ' ],', + ' bar: [', + ' 0: [ hey ]', + ' ]', + '}', + '' + ] + wrapper.overview() + expect(consoleOutput).to.have.ordered.members(expectedConsoleOutput) + }) + + it('throws error when called on non VueWrapper', () => { + const wrapper = mountingMethod({ template: '

' }) + const nonVueWrapper = wrapper.find('p') + const message = + '[vue-test-utils]: wrapper.overview() can only be called on a Vue instance' + + expect(() => nonVueWrapper.overview()) + .to.throw() + .with.property('message', message) + }) + + describe('vibility', () => { + it('prints "Visible" when the wrapper is visible', () => { + const wrapper = mountingMethod({ template: '
' }) + + const expectedConsoleOutput = [ + '', + 'Wrapper (Visible):', + '', + 'Html:', + '
', + '', + 'Data: {}', + '', + 'Computed: {}', + '', + 'Emitted: {}', + '' + ] + + wrapper.isVisible = () => true + wrapper.overview() + expect(consoleOutput).to.have.ordered.members(expectedConsoleOutput) + }) + + it('prints "Not Visible" when the wrapper is not visible', () => { + const wrapper = mountingMethod({ template: '
' }) + + const expectedConsoleOutput = [ + '', + 'Wrapper (Not visible):', + '', + 'Html:', + '
', + '', + 'Data: {}', + '', + 'Computed: {}', + '', + 'Emitted: {}', + '' + ] + + wrapper.isVisible = () => false + wrapper.overview() + expect(consoleOutput).to.have.ordered.members(expectedConsoleOutput) + }) + }) + + describe('html', () => { + it('prints Html as empty when html is not defined', () => { + const wrapper = mountingMethod({ template: '' }) + + const expectedConsoleOutput = [ + '', + 'Wrapper (Visible):', + '', + 'Html:', + '', + 'Data: {}', + '', + 'Computed: {}', + '', + 'Emitted: {}', + '' + ] + + wrapper.overview() + expect(consoleOutput).to.have.ordered.members(expectedConsoleOutput) + }) + }) + + describe('data', () => { + it('prints Data as {} when data is empty', () => { + const wrapper = mountingMethod({ + template: '
', + computed: { + onePlusOne: () => 1 + 1 + } + }) + wrapper.vm.$emit('foo', 'hello', 'world') + wrapper.vm.$emit('foo', 'bye', 'world') + wrapper.vm.$emit('bar', 'hey') + + const expectedConsoleOutput = [ + '', + 'Wrapper (Visible):', + '', + 'Html:', + '
', + '', + 'Data: {}', + '', + 'Computed: {', + ' onePlusOne: 2', + '}', + '', + 'Emitted: {', + ' foo: [', + ' 0: [ hello, world ],', + ' 1: [ bye, world ]', + ' ],', + ' bar: [', + ' 0: [ hey ]', + ' ]', + '}', + '' + ] + wrapper.overview() + expect(consoleOutput).to.have.ordered.members(expectedConsoleOutput) + }) + }) + + describe('computed', () => { + it('prints Computed as {} when data is empty', () => { + const wrapper = mountingMethod({ + template: '
' + }) + wrapper.vm.$emit('foo', 'hello', 'world') + wrapper.vm.$emit('foo', 'bye', 'world') + wrapper.vm.$emit('bar', 'hey') + + const expectedConsoleOutput = [ + '', + 'Wrapper (Visible):', + '', + 'Html:', + '
', + '', + 'Data: {}', + '', + 'Computed: {}', + '', + 'Emitted: {', + ' foo: [', + ' 0: [ hello, world ],', + ' 1: [ bye, world ]', + ' ],', + ' bar: [', + ' 0: [ hey ]', + ' ]', + '}', + '' + ] + wrapper.overview() + expect(consoleOutput).to.have.ordered.members(expectedConsoleOutput) + }) + }) + + describe('emitted events', () => { + it('prints Emitted as {} when no events have been emitted', () => { + const wrapper = mountingMethod({ + template: '
' + }) + + const expectedConsoleOutput = [ + '', + 'Wrapper (Visible):', + '', + 'Html:', + '
', + '', + 'Data: {}', + '', + 'Computed: {}', + '', + 'Emitted: {}', + '' + ] + wrapper.overview() + expect(consoleOutput).to.have.ordered.members(expectedConsoleOutput) + }) + }) + + describe('child components', () => { + it('prints children compenents HTML', () => { + if (mountingMethod.name === 'shallowMount') return + const wrapper = mountingMethod({ + template: `
1
`, + components: { + tester: { + template: `
test
` + } + } + }) + + const expectedConsoleOutput = [ + '', + 'Wrapper (Visible):', + '', + 'Html:', + '
1
test
', + '
', + '', + 'Data: {}', + '', + 'Computed: {}', + '', + 'Emitted: {}', + '' + ] + + wrapper.isVisible = () => true + wrapper.overview() + expect(consoleOutput).to.have.ordered.members(expectedConsoleOutput) + }) + + it('does not print child component data or computed', () => { + if (mountingMethod.name === 'shallowMount') return + const wrapper = mountingMethod({ + template: `
1
`, + data() { + return { + fathersMessage: 'I am your father' + } + }, + computed: { + onePlusOne: () => 1 + 1 + }, + components: { + tester: { + template: `
test
`, + data() { + return { + something: 'hiden' + } + }, + computed: { + twoPlusTwo: () => 2 + 2 + } + } + } + }) + + const expectedConsoleOutput = [ + '', + 'Wrapper (Visible):', + '', + 'Html:', + '
1
test
', + '
', + '', + 'Data: {', + ' fathersMessage: I am your father', + '}', + '', + 'Computed: {', + ' onePlusOne: 2', + '}', + '', + 'Emitted: {}', + '' + ] + + wrapper.overview() + expect(consoleOutput).to.have.ordered.members(expectedConsoleOutput) + }) + }) +}) From 5cc698a3f2979f0887bcc712aefb1dfc745b5c71 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 29 Mar 2020 03:01:24 +0200 Subject: [PATCH 2/6] feat(test-utils): add error wrapper overview --- packages/test-utils/src/error-wrapper.js | 8 ++++++++ packages/test-utils/src/wrapper.js | 2 +- test/specs/error-wrapper.spec.js | 1 + 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/test-utils/src/error-wrapper.js b/packages/test-utils/src/error-wrapper.js index 3365e1017..5937c1c25 100644 --- a/packages/test-utils/src/error-wrapper.js +++ b/packages/test-utils/src/error-wrapper.js @@ -187,6 +187,14 @@ export default class ErrorWrapper implements BaseWrapper { ) } + overview(): void { + throwError( + `find did not return ${buildSelectorString( + this.selector + )}, cannot call overview() on empty Wrapper` + ) + } + props(): void { throwError( `find did not return ${buildSelectorString( diff --git a/packages/test-utils/src/wrapper.js b/packages/test-utils/src/wrapper.js index 192603a08..28772ac31 100644 --- a/packages/test-utils/src/wrapper.js +++ b/packages/test-utils/src/wrapper.js @@ -333,7 +333,7 @@ export default class Wrapper implements BaseWrapper { throwError(`wrapper.overview() can only be called on a Vue instance`) } const identation = 4 - const formatJSON = (json: string, replacer: Function = null) => + const formatJSON = (json: any, replacer: Function = null) => JSON.stringify(json, replacer, identation).replace(/"/g, '') const visibility = this.isVisible() ? 'Visible' : 'Not visible' diff --git a/test/specs/error-wrapper.spec.js b/test/specs/error-wrapper.spec.js index 0eb610696..3357194c9 100644 --- a/test/specs/error-wrapper.spec.js +++ b/test/specs/error-wrapper.spec.js @@ -22,6 +22,7 @@ describeWithShallowAndMount('ErrorWrapper', mountingMethod => { 'isVisible', 'isVueInstance', 'name', + 'overview', 'props', 'setComputed', 'setMethods', From b9039929ff0310bf9cdd405b0f425a4fc1f403a0 Mon Sep 17 00:00:00 2001 From: SergiCL Date: Sun, 29 Mar 2020 03:41:41 +0200 Subject: [PATCH 3/6] fix(test-utils): fix flow errors --- packages/test-utils/src/wrapper.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/test-utils/src/wrapper.js b/packages/test-utils/src/wrapper.js index 28772ac31..8109c72bd 100644 --- a/packages/test-utils/src/wrapper.js +++ b/packages/test-utils/src/wrapper.js @@ -333,7 +333,7 @@ export default class Wrapper implements BaseWrapper { throwError(`wrapper.overview() can only be called on a Vue instance`) } const identation = 4 - const formatJSON = (json: any, replacer: Function = null) => + const formatJSON = (json: any, replacer: Function | null = null) => JSON.stringify(json, replacer, identation).replace(/"/g, '') const visibility = this.isVisible() ? 'Visible' : 'Not visible' @@ -342,11 +342,15 @@ export default class Wrapper implements BaseWrapper { ? this.html().replace(/^(?!\s*$)/gm, ' '.repeat(identation)) + '\n' : '' + // $FlowIgnore const data = formatJSON(this.vm.$data) + // $FlowIgnore const computed = this.vm._computedWatchers ? formatJSON( + // $FlowIgnore ...Object.keys(this.vm._computedWatchers).map(computedKey => ({ + // $FlowIgnore [computedKey]: this.vm[computedKey] })) ) From 19c1434dab9a06a099b2c910b59c408f077ec04c Mon Sep 17 00:00:00 2001 From: root Date: Tue, 31 Mar 2020 00:36:34 +0200 Subject: [PATCH 4/6] fix(test-utils): compatibility with older versions --- packages/test-utils/src/wrapper.js | 11 + test/specs/wrapper/overview.spec.js | 510 ++++++++++++++-------------- 2 files changed, 267 insertions(+), 254 deletions(-) diff --git a/packages/test-utils/src/wrapper.js b/packages/test-utils/src/wrapper.js index 8109c72bd..ff330af9b 100644 --- a/packages/test-utils/src/wrapper.js +++ b/packages/test-utils/src/wrapper.js @@ -332,6 +332,7 @@ export default class Wrapper implements BaseWrapper { if (!this.isVueInstance()) { throwError(`wrapper.overview() can only be called on a Vue instance`) } + const identation = 4 const formatJSON = (json: any, replacer: Function | null = null) => JSON.stringify(json, replacer, identation).replace(/"/g, '') @@ -345,6 +346,7 @@ export default class Wrapper implements BaseWrapper { // $FlowIgnore const data = formatJSON(this.vm.$data) + /* eslint-disable operator-linebreak */ // $FlowIgnore const computed = this.vm._computedWatchers ? formatJSON( @@ -354,7 +356,16 @@ export default class Wrapper implements BaseWrapper { [computedKey]: this.vm[computedKey] })) ) + : // $FlowIgnore + this.vm.$options.computed + ? formatJSON( + // $FlowIgnore + ...Object.entries(this.vm.$options.computed).map(([key, value]) => ({ + [key]: value() + })) + ) : '{}' + /* eslint-enable operator-linebreak */ const emittedJSONReplacer = (key, value) => value instanceof Array diff --git a/test/specs/wrapper/overview.spec.js b/test/specs/wrapper/overview.spec.js index 92aa61093..1b7d7caee 100644 --- a/test/specs/wrapper/overview.spec.js +++ b/test/specs/wrapper/overview.spec.js @@ -1,4 +1,4 @@ -import { describeWithShallowAndMount } from '~resources/utils' +import { describeWithShallowAndMount, vueVersion } from '~resources/utils' describeWithShallowAndMount('overview', mountingMethod => { const originalLog = console.log @@ -12,57 +12,6 @@ describeWithShallowAndMount('overview', mountingMethod => { }) afterEach(() => (console.log = originalLog)) - it('prints a simple overview of the Wrapper', () => { - const wrapper = mountingMethod({ - template: - '

My name is {{ firstName }} {{ lastName }}

', - data() { - return { - firstName: 'Tess', - lastName: 'Ting' - } - }, - computed: { - onePlusOne: () => 1 + 1 - } - }) - wrapper.vm.$emit('foo', 'hello', 'world') - wrapper.vm.$emit('foo', 'bye', 'world') - wrapper.vm.$emit('bar', 'hey') - - const expectedConsoleOutput = [ - '', - 'Wrapper (Visible):', - '', - 'Html:', - '
', - '

My name is Tess Ting

', - '
', - '', - 'Data: {', - ' firstName: Tess,', - ' lastName: Ting', - '}', - '', - 'Computed: {', - ' onePlusOne: 2', - '}', - '', - 'Emitted: {', - ' foo: [', - ' 0: [ hello, world ],', - ' 1: [ bye, world ]', - ' ],', - ' bar: [', - ' 0: [ hey ]', - ' ]', - '}', - '' - ] - wrapper.overview() - expect(consoleOutput).to.have.ordered.members(expectedConsoleOutput) - }) - it('throws error when called on non VueWrapper', () => { const wrapper = mountingMethod({ template: '

' }) const nonVueWrapper = wrapper.find('p') @@ -74,81 +23,17 @@ describeWithShallowAndMount('overview', mountingMethod => { .with.property('message', message) }) - describe('vibility', () => { - it('prints "Visible" when the wrapper is visible', () => { - const wrapper = mountingMethod({ template: '
' }) - - const expectedConsoleOutput = [ - '', - 'Wrapper (Visible):', - '', - 'Html:', - '
', - '', - 'Data: {}', - '', - 'Computed: {}', - '', - 'Emitted: {}', - '' - ] - - wrapper.isVisible = () => true - wrapper.overview() - expect(consoleOutput).to.have.ordered.members(expectedConsoleOutput) - }) - - it('prints "Not Visible" when the wrapper is not visible', () => { - const wrapper = mountingMethod({ template: '
' }) - - const expectedConsoleOutput = [ - '', - 'Wrapper (Not visible):', - '', - 'Html:', - '
', - '', - 'Data: {}', - '', - 'Computed: {}', - '', - 'Emitted: {}', - '' - ] - - wrapper.isVisible = () => false - wrapper.overview() - expect(consoleOutput).to.have.ordered.members(expectedConsoleOutput) - }) - }) - - describe('html', () => { - it('prints Html as empty when html is not defined', () => { - const wrapper = mountingMethod({ template: '' }) - - const expectedConsoleOutput = [ - '', - 'Wrapper (Visible):', - '', - 'Html:', - '', - 'Data: {}', - '', - 'Computed: {}', - '', - 'Emitted: {}', - '' - ] - - wrapper.overview() - expect(consoleOutput).to.have.ordered.members(expectedConsoleOutput) - }) - }) - - describe('data', () => { - it('prints Data as {} when data is empty', () => { + if (vueVersion > 2) { + it('prints a simple overview of the Wrapper', () => { const wrapper = mountingMethod({ - template: '
', + template: + '

My name is {{ firstName }} {{ lastName }}

', + data() { + return { + firstName: 'Tess', + lastName: 'Ting' + } + }, computed: { onePlusOne: () => 1 + 1 } @@ -162,9 +47,14 @@ describeWithShallowAndMount('overview', mountingMethod => { 'Wrapper (Visible):', '', 'Html:', - '
', + '
', + '

My name is Tess Ting

', + '
', '', - 'Data: {}', + 'Data: {', + ' firstName: Tess,', + ' lastName: Ting', + '}', '', 'Computed: {', ' onePlusOne: 2', @@ -184,151 +74,263 @@ describeWithShallowAndMount('overview', mountingMethod => { wrapper.overview() expect(consoleOutput).to.have.ordered.members(expectedConsoleOutput) }) - }) - describe('computed', () => { - it('prints Computed as {} when data is empty', () => { - const wrapper = mountingMethod({ - template: '
' + describe('vibility', () => { + it('prints "Visible" when the wrapper is visible', () => { + const wrapper = mountingMethod({ template: '
' }) + + const expectedConsoleOutput = [ + '', + 'Wrapper (Visible):', + '', + 'Html:', + '
', + '', + 'Data: {}', + '', + 'Computed: {}', + '', + 'Emitted: {}', + '' + ] + + wrapper.isVisible = () => true + wrapper.overview() + expect(consoleOutput).to.have.ordered.members(expectedConsoleOutput) }) - wrapper.vm.$emit('foo', 'hello', 'world') - wrapper.vm.$emit('foo', 'bye', 'world') - wrapper.vm.$emit('bar', 'hey') - const expectedConsoleOutput = [ - '', - 'Wrapper (Visible):', - '', - 'Html:', - '
', - '', - 'Data: {}', - '', - 'Computed: {}', - '', - 'Emitted: {', - ' foo: [', - ' 0: [ hello, world ],', - ' 1: [ bye, world ]', - ' ],', - ' bar: [', - ' 0: [ hey ]', - ' ]', - '}', - '' - ] - wrapper.overview() - expect(consoleOutput).to.have.ordered.members(expectedConsoleOutput) - }) - }) + it('prints "Not Visible" when the wrapper is not visible', () => { + const wrapper = mountingMethod({ template: '
' }) - describe('emitted events', () => { - it('prints Emitted as {} when no events have been emitted', () => { - const wrapper = mountingMethod({ - template: '
' + const expectedConsoleOutput = [ + '', + 'Wrapper (Not visible):', + '', + 'Html:', + '
', + '', + 'Data: {}', + '', + 'Computed: {}', + '', + 'Emitted: {}', + '' + ] + + wrapper.isVisible = () => false + wrapper.overview() + expect(consoleOutput).to.have.ordered.members(expectedConsoleOutput) }) + }) - const expectedConsoleOutput = [ - '', - 'Wrapper (Visible):', - '', - 'Html:', - '
', - '', - 'Data: {}', - '', - 'Computed: {}', - '', - 'Emitted: {}', - '' - ] - wrapper.overview() - expect(consoleOutput).to.have.ordered.members(expectedConsoleOutput) + describe('html', () => { + it('prints Html as empty when html is not defined', () => { + const wrapper = mountingMethod({ template: '' }) + + const expectedConsoleOutput = [ + '', + 'Wrapper (Visible):', + '', + 'Html:', + '', + 'Data: {}', + '', + 'Computed: {}', + '', + 'Emitted: {}', + '' + ] + + wrapper.overview() + expect(consoleOutput).to.have.ordered.members(expectedConsoleOutput) + }) }) - }) - describe('child components', () => { - it('prints children compenents HTML', () => { - if (mountingMethod.name === 'shallowMount') return - const wrapper = mountingMethod({ - template: `
1
`, - components: { - tester: { - template: `
test
` + describe('data', () => { + it('prints Data as {} when data is empty', () => { + const wrapper = mountingMethod({ + template: '
', + computed: { + onePlusOne: () => 1 + 1 } - } + }) + wrapper.vm.$emit('foo', 'hello', 'world') + wrapper.vm.$emit('foo', 'bye', 'world') + wrapper.vm.$emit('bar', 'hey') + + const expectedConsoleOutput = [ + '', + 'Wrapper (Visible):', + '', + 'Html:', + '
', + '', + 'Data: {}', + '', + 'Computed: {', + ' onePlusOne: 2', + '}', + '', + 'Emitted: {', + ' foo: [', + ' 0: [ hello, world ],', + ' 1: [ bye, world ]', + ' ],', + ' bar: [', + ' 0: [ hey ]', + ' ]', + '}', + '' + ] + wrapper.overview() + expect(consoleOutput).to.have.ordered.members(expectedConsoleOutput) }) + }) - const expectedConsoleOutput = [ - '', - 'Wrapper (Visible):', - '', - 'Html:', - '
1
test
', - '
', - '', - 'Data: {}', - '', - 'Computed: {}', - '', - 'Emitted: {}', - '' - ] + describe('computed', () => { + it('prints Computed as {} when data is empty', () => { + const wrapper = mountingMethod({ + template: '
' + }) + wrapper.vm.$emit('foo', 'hello', 'world') + wrapper.vm.$emit('foo', 'bye', 'world') + wrapper.vm.$emit('bar', 'hey') - wrapper.isVisible = () => true - wrapper.overview() - expect(consoleOutput).to.have.ordered.members(expectedConsoleOutput) + const expectedConsoleOutput = [ + '', + 'Wrapper (Visible):', + '', + 'Html:', + '
', + '', + 'Data: {}', + '', + 'Computed: {}', + '', + 'Emitted: {', + ' foo: [', + ' 0: [ hello, world ],', + ' 1: [ bye, world ]', + ' ],', + ' bar: [', + ' 0: [ hey ]', + ' ]', + '}', + '' + ] + wrapper.overview() + expect(consoleOutput).to.have.ordered.members(expectedConsoleOutput) + }) }) - it('does not print child component data or computed', () => { - if (mountingMethod.name === 'shallowMount') return - const wrapper = mountingMethod({ - template: `
1
`, - data() { - return { - fathersMessage: 'I am your father' + describe('emitted events', () => { + it('prints Emitted as {} when no events have been emitted', () => { + const wrapper = mountingMethod({ + template: '
' + }) + + const expectedConsoleOutput = [ + '', + 'Wrapper (Visible):', + '', + 'Html:', + '
', + '', + 'Data: {}', + '', + 'Computed: {}', + '', + 'Emitted: {}', + '' + ] + wrapper.overview() + expect(consoleOutput).to.have.ordered.members(expectedConsoleOutput) + }) + }) + + describe('child components', () => { + it('prints children compenents HTML', () => { + if (mountingMethod.name === 'shallowMount') return + const wrapper = mountingMethod({ + template: `
1
`, + components: { + tester: { + template: `
test
` + } } - }, - computed: { - onePlusOne: () => 1 + 1 - }, - components: { - tester: { - template: `
test
`, - data() { - return { - something: 'hiden' + }) + + const expectedConsoleOutput = [ + '', + 'Wrapper (Visible):', + '', + 'Html:', + '
1
test
', + '
', + '', + 'Data: {}', + '', + 'Computed: {}', + '', + 'Emitted: {}', + '' + ] + + wrapper.isVisible = () => true + wrapper.overview() + expect(consoleOutput).to.have.ordered.members(expectedConsoleOutput) + }) + + it('does not print child component data or computed', () => { + if (mountingMethod.name === 'shallowMount') return + const wrapper = mountingMethod({ + template: `
1
`, + data() { + return { + fathersMessage: 'I am your father' + } + }, + computed: { + onePlusOne: () => 1 + 1 + }, + components: { + tester: { + template: `
test
`, + data() { + return { + something: 'hiden' + } + }, + computed: { + twoPlusTwo: () => 2 + 2 } - }, - computed: { - twoPlusTwo: () => 2 + 2 } } - } - }) + }) - const expectedConsoleOutput = [ - '', - 'Wrapper (Visible):', - '', - 'Html:', - '
1
test
', - '
', - '', - 'Data: {', - ' fathersMessage: I am your father', - '}', - '', - 'Computed: {', - ' onePlusOne: 2', - '}', - '', - 'Emitted: {}', - '' - ] + const expectedConsoleOutput = [ + '', + 'Wrapper (Visible):', + '', + 'Html:', + '
1
test
', + '
', + '', + 'Data: {', + ' fathersMessage: I am your father', + '}', + '', + 'Computed: {', + ' onePlusOne: 2', + '}', + '', + 'Emitted: {}', + '' + ] - wrapper.overview() - expect(consoleOutput).to.have.ordered.members(expectedConsoleOutput) + wrapper.overview() + expect(consoleOutput).to.have.ordered.members(expectedConsoleOutput) + }) }) - }) + } }) From 004f451837c420f2b950d2563de21d34f3b14585 Mon Sep 17 00:00:00 2001 From: SergiCL Date: Tue, 31 Mar 2020 00:51:13 +0200 Subject: [PATCH 5/6] fix(test utils): flow error --- packages/test-utils/src/wrapper.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/test-utils/src/wrapper.js b/packages/test-utils/src/wrapper.js index ff330af9b..f4a47b85f 100644 --- a/packages/test-utils/src/wrapper.js +++ b/packages/test-utils/src/wrapper.js @@ -361,6 +361,7 @@ export default class Wrapper implements BaseWrapper { ? formatJSON( // $FlowIgnore ...Object.entries(this.vm.$options.computed).map(([key, value]) => ({ + // $FlowIgnore [key]: value() })) ) From b5ecffce1207fb70a20a141977bf1b3f3168eccc Mon Sep 17 00:00:00 2001 From: SergiCL Date: Tue, 7 Apr 2020 20:01:10 +0200 Subject: [PATCH 6/6] feat: overview function PR comments --- packages/test-utils/src/wrapper.js | 14 +++-- test/specs/wrapper/overview.spec.js | 80 +++++++++++++++++++++++++++-- 2 files changed, 87 insertions(+), 7 deletions(-) diff --git a/packages/test-utils/src/wrapper.js b/packages/test-utils/src/wrapper.js index f4a47b85f..89e8d707d 100644 --- a/packages/test-utils/src/wrapper.js +++ b/packages/test-utils/src/wrapper.js @@ -370,9 +370,17 @@ export default class Wrapper implements BaseWrapper { const emittedJSONReplacer = (key, value) => value instanceof Array - ? value.map( - (calledWith, index) => `${index}: [ ${calledWith.join(', ')} ]` - ) + ? value.map((calledWith, index) => { + const callParams = calledWith.map(param => + typeof param === 'object' + ? JSON.stringify(param) + .replace(/"/g, '') + .replace(/,/g, ', ') + : param + ) + + return `${index}: [ ${callParams.join(', ')} ]` + }) : value const emitted = formatJSON(this.emitted(), emittedJSONReplacer) diff --git a/test/specs/wrapper/overview.spec.js b/test/specs/wrapper/overview.spec.js index 1b7d7caee..16c2d7965 100644 --- a/test/specs/wrapper/overview.spec.js +++ b/test/specs/wrapper/overview.spec.js @@ -246,11 +246,80 @@ describeWithShallowAndMount('overview', mountingMethod => { wrapper.overview() expect(consoleOutput).to.have.ordered.members(expectedConsoleOutput) }) + + it('prints an empty array in Emitted arrays of calls when emit was empty', () => { + const wrapper = mountingMethod({ + template: '
' + }) + + wrapper.vm.$emit('foo') + wrapper.vm.$emit('foo') + + const expectedConsoleOutput = [ + '', + 'Wrapper (Visible):', + '', + 'Html:', + '
', + '', + 'Data: {}', + '', + 'Computed: {}', + '', + 'Emitted: {', + ' foo: [', + ' 0: [ ],', + ' 1: [ ]', + ' ]', + '}', + '' + ] + wrapper.overview() + expect(consoleOutput).to.have.ordered.members(expectedConsoleOutput) + }) + + it('prints inline formated object in Emitted arrays of calls when an object has been emitted', () => { + const wrapper = mountingMethod({ + template: '
' + }) + + wrapper.vm.$emit('foo', { + title: 'How to test', + author: 'Tester', + price: 10 + }) + wrapper.vm.$emit( + 'foo', + { title: 'How to test 2', author: 'Tester Jr', price: 12 }, + 'New' + ) + + const expectedConsoleOutput = [ + '', + 'Wrapper (Visible):', + '', + 'Html:', + '
', + '', + 'Data: {}', + '', + 'Computed: {}', + '', + 'Emitted: {', + ' foo: [', + ' 0: [ {title:How to test, author:Tester, price:10} ],', + ' 1: [ {title:How to test 2, author:Tester Jr, price:12}, New ]', + ' ]', + '}', + '' + ] + wrapper.overview() + expect(consoleOutput).to.have.ordered.members(expectedConsoleOutput) + }) }) describe('child components', () => { it('prints children compenents HTML', () => { - if (mountingMethod.name === 'shallowMount') return const wrapper = mountingMethod({ template: `
1
`, components: { @@ -265,7 +334,9 @@ describeWithShallowAndMount('overview', mountingMethod => { 'Wrapper (Visible):', '', 'Html:', - '
1
test
', + mountingMethod.name === 'shallowMount' + ? '
1' + : '
1
test
', '
', '', 'Data: {}', @@ -282,7 +353,6 @@ describeWithShallowAndMount('overview', mountingMethod => { }) it('does not print child component data or computed', () => { - if (mountingMethod.name === 'shallowMount') return const wrapper = mountingMethod({ template: `
1
`, data() { @@ -313,7 +383,9 @@ describeWithShallowAndMount('overview', mountingMethod => { 'Wrapper (Visible):', '', 'Html:', - '
1
test
', + mountingMethod.name === 'shallowMount' + ? '
1' + : '
1
test
', '
', '', 'Data: {',