Skip to content

Commit

Permalink
feat: add enableAutoUnmount feature
Browse files Browse the repository at this point in the history
- port enableAutoDestroy feature from VTU v1
  • Loading branch information
xanf committed Oct 5, 2021
1 parent 192cdc6 commit 1bc2260
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 4 deletions.
22 changes: 22 additions & 0 deletions docs/api/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -1829,6 +1829,28 @@ function shallowMount(Component, options?: MountingOptions): VueWrapper
`shallowMount` behaves exactly like `mount`, but it stubs all child components by default. Essentially, `shallowMount(Component)` is an alias of `mount(Component, { shallow: true })`.
## enableAutoUnmount
**Signature:**
```ts
enableAutoUnmount(hook: Function));
disableAutoUnmount(): void;
```
**Details:**
`enableAutoUnmount` allows to automatically destroy Vue wrappers. Destroy logic is passed as callback to `hook` Function.
Common usage is to use `enableAutoUnmount` with teardown helper functions provided by your test framework, such as `afterEach`:
```ts
import { enableAutoUnmount } from '@vue/test-utils'

enableAutoUnmount(afterEach)
```
`disableAutoUnmount` might be useful if you want this behavior only in specific subset of your test suite and you want to explicitly disable this behavior
## flushPromises
**Signature:**
Expand Down
3 changes: 3 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@ import { DOMWrapper } from './domWrapper'
import { createWrapperError } from './errorWrapper'
import { config } from './config'
import { flushPromises } from './utils/flushPromises'
import { enableAutoUnmount, disableAutoUnmount } from './utils/autoUnmount'

export {
mount,
shallowMount,
enableAutoUnmount,
disableAutoUnmount,
RouterLinkStub,
VueWrapper,
DOMWrapper,
Expand Down
13 changes: 9 additions & 4 deletions src/mount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import {
isLegacyFunctionalComponent,
unwrapLegacyVueExtendComponent
} from './utils/vueCompatSupport'
import { trackInstance } from './utils/autoUnmount'

// NOTE this should come from `vue`
type PublicProps = VNodeProps & AllowedComponentProps & ComponentCustomProps
Expand Down Expand Up @@ -165,9 +166,11 @@ export function mount<
Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
EE extends string = string,
Props extends Readonly<{ [key in PropNames]?: any }> = Readonly<{
[key in PropNames]?: any
}>
Props extends Readonly<{ [key in PropNames]?: any }> = Readonly<
{
[key in PropNames]?: any
}
>
>(
componentOptions: ComponentOptionsWithArrayProps<
PropNames,
Expand Down Expand Up @@ -452,7 +455,9 @@ export function mount(
return Reflect.has(appRef, property)
}
console.warn = warnSave
return createWrapper(app, appRef, setProps)
const wrapper = createWrapper(app, $vm, setProps)
trackInstance(wrapper)
return wrapper
}

export const shallowMount: typeof mount = (component: any, options?: any) => {
Expand Down
32 changes: 32 additions & 0 deletions src/utils/autoUnmount.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { ComponentPublicInstance } from 'vue'
import type { VueWrapper } from '../vueWrapper'

let isEnabled = false
const wrapperInstances: VueWrapper<ComponentPublicInstance>[] = []

export function disableAutoUnmount() {
isEnabled = false
wrapperInstances.length = 0
}

export function enableAutoUnmount(hook: Function) {
if (isEnabled) {
throw new Error('enableAutoUnmount cannot be called more than once')
}

isEnabled = true

hook(() => {
wrapperInstances.forEach((wrapper: VueWrapper<ComponentPublicInstance>) => {
wrapper.unmount()
})

wrapperInstances.length = 0
})
}

export function trackInstance(wrapper: VueWrapper<ComponentPublicInstance>) {
if (!isEnabled) return

wrapperInstances.push(wrapper)
}
37 changes: 37 additions & 0 deletions tests/autoUnmount.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { mount, enableAutoUnmount, disableAutoUnmount } from '../src'

describe('enableAutoUnmount', () => {
beforeEach(() => {
disableAutoUnmount()
})

it('calls the hook function', () => {
const hookMock = jest.fn()

enableAutoUnmount(hookMock)

expect(hookMock).toHaveBeenCalledWith(expect.any(Function))
})

it('uses the hook function to unmount wrappers', () => {
const hookMock = jest.fn()

enableAutoUnmount(hookMock)
const [unmountFn] = hookMock.mock.calls[0]

const wrapper = mount({ template: '<p>test</p>' })
jest.spyOn(wrapper, 'unmount')

unmountFn()

expect(wrapper.unmount).toHaveBeenCalledTimes(1)
})

it('cannot be called twice', () => {
const noop = () => {}

enableAutoUnmount(noop)

expect(() => enableAutoUnmount(noop)).toThrow()
})
})

0 comments on commit 1bc2260

Please sign in to comment.