Skip to content

Commit 2784cd3

Browse files
authored
Merge pull request #1245 from winniehell/winniehell-autodestroy
feat: Introduce enableAutoDestroy() helper function
2 parents 5569325 + d17fc1f commit 2784cd3

File tree

6 files changed

+114
-4
lines changed

6 files changed

+114
-4
lines changed

Diff for: docs/api/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@
88
!!!include(docs/api/createLocalVue.md)!!!
99
!!!include(docs/api/createWrapper.md)!!!
1010
!!!include(docs/api/config.md)!!!
11+
!!!include(docs/api/enableAutoDestroy.md)!!!

Diff for: docs/api/enableAutoDestroy.md

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
## enableAutoDestroy(hook)
2+
3+
- **Arguments:**
4+
5+
- `{Function} hook`
6+
7+
- **Usage:**
8+
9+
`enableAutoDestroy` will destroy all created `Wrapper` instances using the passed hook function (for example [`afterEach`](https://jestjs.io/docs/en/api#aftereachfn-timeout)). After calling the method, you can revert to the default behavior by calling the `resetAutoDestroyState` method.
10+
11+
```js
12+
import { enableAutoDestroy, mount } from '@vue/test-utils'
13+
import Foo from './Foo.vue'
14+
15+
// calls wrapper.destroy() after each test
16+
enableAutoDestroy(afterEach)
17+
18+
describe('Foo', () => {
19+
it('renders a div', () => {
20+
const wrapper = mount(Foo)
21+
expect(wrapper.contains('div')).toBe(true)
22+
// no need to call wrapper.destroy() here
23+
})
24+
})
25+
```

Diff for: packages/test-utils/src/auto-destroy.js

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// @flow
2+
3+
import { throwError } from 'shared/util'
4+
import Wrapper from './wrapper'
5+
6+
let isEnabled = false
7+
const wrapperInstances = []
8+
9+
export function resetAutoDestroyState() {
10+
isEnabled = false
11+
wrapperInstances.length = 0
12+
}
13+
14+
export function enableAutoDestroy(hook: (() => void) => void) {
15+
if (isEnabled) {
16+
throwError('enableAutoDestroy cannot be called more than once')
17+
}
18+
19+
isEnabled = true
20+
21+
hook(() => {
22+
wrapperInstances.forEach((wrapper: Wrapper) => {
23+
// skip child wrappers created by wrapper.find()
24+
if (wrapper.selector) return
25+
26+
wrapper.destroy()
27+
})
28+
29+
wrapperInstances.length = 0
30+
})
31+
}
32+
33+
export function trackInstance(wrapper: Wrapper) {
34+
if (!isEnabled) return
35+
36+
wrapperInstances.push(wrapper)
37+
}

Diff for: packages/test-utils/src/create-wrapper.js

+10-4
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,22 @@
33
import Vue from 'vue'
44
import Wrapper from './wrapper'
55
import VueWrapper from './vue-wrapper'
6+
import { trackInstance } from './auto-destroy'
67

78
export default function createWrapper(
89
node: VNode | Component,
910
options: WrapperOptions = {}
1011
): VueWrapper | Wrapper {
1112
const componentInstance = node.child
1213
if (componentInstance) {
13-
return new VueWrapper(componentInstance, options)
14+
const wrapper = new VueWrapper(componentInstance, options)
15+
trackInstance(wrapper)
16+
return wrapper
1417
}
15-
return node instanceof Vue
16-
? new VueWrapper(node, options)
17-
: new Wrapper(node, options)
18+
const wrapper =
19+
node instanceof Vue
20+
? new VueWrapper(node, options)
21+
: new Wrapper(node, options)
22+
trackInstance(wrapper)
23+
return wrapper
1824
}

Diff for: packages/test-utils/src/index.js

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import shallowMount from './shallow-mount'
22
import mount from './mount'
3+
import { enableAutoDestroy, resetAutoDestroyState } from './auto-destroy'
34
import createLocalVue from './create-local-vue'
45
import RouterLinkStub from './components/RouterLinkStub'
56
import createWrapper from './create-wrapper'
@@ -20,7 +21,9 @@ export {
2021
createLocalVue,
2122
createWrapper,
2223
config,
24+
enableAutoDestroy,
2325
mount,
26+
resetAutoDestroyState,
2427
shallow,
2528
shallowMount,
2629
RouterLinkStub,

Diff for: test/specs/wrapper.spec.js

+38
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { describeWithShallowAndMount } from '~resources/utils'
2+
import { enableAutoDestroy, resetAutoDestroyState } from '~vue/test-utils'
23

34
describeWithShallowAndMount('Wrapper', mountingMethod => {
45
;['vnode', 'element', 'vm', 'options'].forEach(property => {
@@ -15,4 +16,41 @@ describeWithShallowAndMount('Wrapper', mountingMethod => {
1516
.with.property('message', message)
1617
})
1718
})
19+
20+
describe('enableAutoDestroy', () => {
21+
const sandbox = sinon.createSandbox()
22+
23+
beforeEach(() => {
24+
resetAutoDestroyState()
25+
})
26+
27+
it('calls the hook function', () => {
28+
const hookSpy = sandbox.spy()
29+
30+
enableAutoDestroy(hookSpy)
31+
32+
expect(hookSpy).calledOnce
33+
})
34+
35+
it('uses the hook function to destroy wrappers', () => {
36+
let hookCallback
37+
enableAutoDestroy(callback => {
38+
hookCallback = callback
39+
})
40+
const wrapper = mountingMethod({ template: '<p>con tent</p>' })
41+
sandbox.spy(wrapper, 'destroy')
42+
43+
hookCallback()
44+
45+
expect(wrapper.destroy).calledOnce
46+
})
47+
48+
it('cannot be called twice', () => {
49+
const noop = () => {}
50+
51+
enableAutoDestroy(noop)
52+
53+
expect(() => enableAutoDestroy(noop)).to.throw()
54+
})
55+
})
1856
})

0 commit comments

Comments
 (0)