From 72a84954b79d6d904298995c331b8493ba3bd0c8 Mon Sep 17 00:00:00 2001 From: winniehell Date: Wed, 22 May 2019 14:34:22 +0200 Subject: [PATCH] Introduce autoDestroy config option --- docs/api/config.md | 47 ++++++++++++++++++++++++++++++ flow/config.flow.js | 3 +- packages/test-utils/src/config.js | 3 +- packages/test-utils/src/wrapper.js | 18 ++++++++++++ test/specs/config.spec.js | 41 ++++++++++++++++++++++++++ 5 files changed, 110 insertions(+), 2 deletions(-) diff --git a/docs/api/config.md b/docs/api/config.md index 23a83c784..03083cddb 100644 --- a/docs/api/config.md +++ b/docs/api/config.md @@ -89,3 +89,50 @@ import { config } from '@vue/test-utils' config.silent = false ``` + +### `autoDestroy` + +- type: `boolean | Function` +- default: `false` + +This allows you to call `wrapper.destroy()` automatically—either when creating a new wrapper or by passing a hook function. + +Please note that setting `autoDestroy: true` only destroys existing instances when a new instance is created which result in one wrapper instance remaining. +Therefore passing a hook function is usually a better idea. + +Examples: + +```js +import { config, mount } from '@vue/test-utils' + +config.autoDestroy = true + +const Component = { + template: '
come ponente
' +} + +const firstWrapper = mount(Component) +expect(firstWrapper.text()).not.toBe('come levant') + +const secondWrapper = mount(Component) // this will call firstWrapper.destroy() +expect(firstWrapper.text()).not.toBe('come sirocco') +``` + +```js +import { config, mount } from '@vue/test-utils' + +config.autoDestroy = afterEach // will call wrapper.destroy() after each test case + +const Component = { + template: '
come ponente
' +} + +describe('my component', () => { + it('is not East wind', () => { + const wrapper = mount(Component) + expect(wrapper.text()).not.toBe('levant') + + // wrapper.destroy() is called after this + }) +}) +``` diff --git a/flow/config.flow.js b/flow/config.flow.js index 3b8ca796f..f152304e2 100644 --- a/flow/config.flow.js +++ b/flow/config.flow.js @@ -3,5 +3,6 @@ declare type Config = { mocks?: Object, methods?: { [name: string]: Function }, provide?: Object, - silent?: boolean + silent?: boolean, + autoDestroy?: boolean | Function } diff --git a/packages/test-utils/src/config.js b/packages/test-utils/src/config.js index e70ea7c20..9d2a47542 100644 --- a/packages/test-utils/src/config.js +++ b/packages/test-utils/src/config.js @@ -3,5 +3,6 @@ export default { mocks: {}, methods: {}, provide: {}, - silent: true + silent: true, + autoDestroy: false } diff --git a/packages/test-utils/src/wrapper.js b/packages/test-utils/src/wrapper.js index 60346ce9a..465e1f285 100644 --- a/packages/test-utils/src/wrapper.js +++ b/packages/test-utils/src/wrapper.js @@ -15,6 +15,13 @@ import { matches } from './matches' import createDOMEvent from './create-dom-event' import { throwIfInstancesThrew } from './error' +const wrapperInstances = [] + +const destroyAllInstances = () => { + wrapperInstances.forEach(wrapper => wrapper.destroy()) + wrapperInstances.length = 0 +} + export default class Wrapper implements BaseWrapper { +vnode: VNode | null +vm: Component | void @@ -67,6 +74,17 @@ export default class Wrapper implements BaseWrapper { ) { this.isFunctionalComponent = true } + + const { autoDestroy } = config + if (autoDestroy) { + if (autoDestroy instanceof Function) { + autoDestroy(destroyAllInstances) + } else { + destroyAllInstances() + } + + wrapperInstances.push(this) + } } at(): void { diff --git a/test/specs/config.spec.js b/test/specs/config.spec.js index dc078413d..c0f8201e9 100644 --- a/test/specs/config.spec.js +++ b/test/specs/config.spec.js @@ -1,4 +1,5 @@ import { describeWithShallowAndMount } from '~resources/utils' +import Component from '~resources/components/component.vue' import ComponentWithProps from '~resources/components/component-with-props.vue' import { itDoNotRunIf } from 'conditional-specs' import { config, createLocalVue } from '~vue/test-utils' @@ -109,4 +110,44 @@ describeWithShallowAndMount('config', mountingMethod => { }) expect(console.error).calledWith(sandbox.match('[Vue warn]')) }) + + describe('autoDestroy', () => { + it('does not destroy wrapper when autoDestroy is set to false', () => { + config.autoDestroy = false + const localVue = createLocalVue() + const wrapper = mountingMethod(Component, { localVue }) + sandbox.spy(wrapper, 'destroy') + + mountingMethod(Component, { localVue }) + + expect(wrapper.destroy).not.called + }) + + it('destroys wrapper when autoDestroy is set to true', () => { + config.autoDestroy = true + const localVue = createLocalVue() + const wrapper = mountingMethod(Component, { localVue }) + sandbox.spy(wrapper, 'destroy') + + mountingMethod(Component, { localVue }) + + expect(wrapper.destroy).called + }) + + it('destroys wrapper when autoDestroy hook is called', () => { + let destroyCallback + config.autoDestroy = callback => { + destroyCallback = callback + } + const localVue = createLocalVue() + const wrapper = mountingMethod(Component, { localVue }) + sandbox.spy(wrapper, 'destroy') + + mountingMethod(Component, { localVue }) + + expect(wrapper.destroy).not.called + destroyCallback() + expect(wrapper.destroy).called + }) + }) })