recorded decision · public · no signup
Summary
What was chosen
- The library is rewritten completely in TypeScript to provide much improved type hints for developers.adr ↗
- The `sync` mode is removed, making all `wrapper` methods that induce a mutation return a `Promise` from `nextTick()`.adr ↗
- The `find` method is split into `find` for DOM elements and `findComponent` for Vue component instances.adr ↗
- The `setProps` method will only work on the directly mounted component.adr ↗
- A simple plugin system is introduced to allow extending `VueWrapper` and `DOMWrapper` with custom methods.adr ↗
- `shallowMount` will now stub default slots of stubbed components by default.adr ↗
What was ruled out· 2
Constraints
- VueTestUtils 2.x is designed to support Vue 3's Component APIs.adr ↗
Consequences
- Existing test snapshots will need to be updated due to the API changes.adr ↗
The recorded why
- Start Date: 19.04.2020
- Target Major Version: 2.x
- Reference Issues: (fill in existing related issues, if any)
- Implementation PR: (leave this empty)
Summary
VueTestUtils 2.x, which targets Vue 3, will introduce a few new methods and remove some less used ones.
- Breaking:
syncmode removed. Allwrappermethods return aPromisefromnextTick(). - Breaking:
findis now split intofindandfindComponent. - Breaking: Removal of some wrapper properties and methods, as they induce bad testing habits or are obsolete.
- Breaking:
shallowMountstubs defaults slots - Breaking:
setPropsonly works for the mounted component.
Note: The API for VueTestUtils 1.x will stay the same and will support Vue 2.x.
Motivation
- Support Vue 3's Component APIs.
- Provide a smaller and easier to understand API
- Allow adding custom functionality via plugin system. [TODO]
- Remove methods that are bloat or lead to bad testing habits.
- Generally improve VTU Docs and Guides.
Detailed design
createLocalVueis removed. Vue now exposescreateApp, which creates an isolated app instance. VTU does that under the hood.- Fully
async, each method that induces a mutation returns aPromisefromnextTick(). Methods likesetValueandtriggercan be awaited, ensuring the DOM is re-rendered before each assertion. - Rewritten completely in TypeScript, giving much improved type hints when writing tests.
shallowMountwill stub default slots of stubbed components. There will be an opt-in configuration to enable rendering slots for stubbed components in a similar manner to VTU beta. There is a limitation that scoped slots will not be able to provide data in such cases.- Simple plugin system to allow extending VTU with your own methods. See Plugins
§ API changes
We will only list the changes and deprecations. Please check the temporary documentation for a full API listing.
mountOptions
props
Link - Renamed from propsData to match component props field.
global
Link - The global namespace is used to pass configuration to the createApp instance. Things like global components, directives and so on.
These settings can also be globally set via the exported config object - config.global.mocks.$t = jest.fn().
- global.components - register global components
- global.directives - register a global directive
- global.mixins - register a global mixin
- global.plugins - install a plugin
- global.stubs - see bellow
- global.mocks - see bellow
- global.provide - see bellow
stubs
Link - Moved to global.stubs.
- New - Stubs will no longer render the slots of a component. This can be enabled by a global flag
config.renderStubSlots = true.
mocks
Link - Moved to global.mocks
provide
Link - Moved to global.provide.
Methods
classes
- New - throw error for multiple root nodes.
unmount
- New replaces
destroyto match Vue 3 API
find
- Breaking - Returns only
DOMWrapper. Cannot find Component instances. see findComponent - Breaking - Accepts query selector only.
- New - Can now return instance root element, or a fragment of the root.
findAll
- Breaking - Returns only array of
DOMWrapper. - Breaking - No longer returns
WrapperArray. - Breaking - Accepts query selector only.
findComponent
findComponent can search for component instances, nested any level in your component tree. This method is most useful for edge case assertions, that are not reflected directly in the DOM
or when using shallowMount and asserting props on a stub.
In most cases, users will use find for asserting DOM properties and content. In cases where a Vue component instance is a really needed, use findComponent.
- New - finds a Vue Component instance by
ref,name,queryor Component definition. ReturnsVueWrapper. - New - Only available on
VueWrapper- cannot chain offfind.
findAllComponents
- New - finds all Vue Components that match
name,queryor Component Definition. Returns array ofVueWrapper. - New - Only available on
VueWrapper.
setProps
- Breaking - Only works on the mounted component.
- New - Returns
nextTick
setValue
- Breaking - Only works on
DOMWrapper(for now). - New - Unifies
setCheckedandsetSelected. - New - Returns
nextTick
Plugin System
A simple plugin system is currently being discussed and prototyped here - POC: VTU Plugin interface.
Thi should allow users to add extra methods to the VueWrapper and DOMWrapper classes, giving them more freedom in setting up their test suite.
const plugin = (wrapper) => {
return {
width: 200,
findByTestId: (query) => wrapper.find(`[data-testid=${query}]`)
}
}
config.plugins.VueWrapper.install(plugin)
// later
expect(mount(Component).findByTestId('foo').exists()).toBe(true)
§ Deprecated
Methods
emittedByOrder
Link - Rarely used, use emitted instead.
expect(wrapper.emitted('change')[0]).toEqual(['param1', 'param2'])
is
Link - Use element.tagName or the classes() method. Could be added as a plugin method later.
expect(wrapper.element.tagName).toEqual('div')
expect(wrapper.classes()).toContain('Foo')
isEmpty
Link - Use custom matcher like jest-dom#tobeempty on the element.
expect(wrapper.element).toBeEmpty()
isVisible
Link - Use custom matcher like jest-dom#tobevisible
expect(wrapper.element).toBeVisible()
isVueInstance
Link - No longer necessary, find always returns an DOMWrapper and findComponent returns a VueWrapper. Both return ErrorWrapper if failed.
setMethods
Link - Anti-pattern. Vue does not support arbitrarily replacement of methods, nor should VTU. If you need to stub out an action, extract the hard parts away. Then you can unit test them as well.
// Component.vue
import { asyncAction } from 'actions'
const Component = {
...,
methods: {
async someAsyncMethod() {
this.result = await asyncAction()
}
}
}
// spec.js
import { asyncAction } from 'actions'
jest.mock('actions')
asyncAction.mockResolvedValue({ foo: 'bar' })
// rest of your test
setChecked and setSelected
Merged with setValue
destroy
Now named unmount to match Vue 3 API
name
Link - Removed from core. Could be added as part of extended plugin.
Classes and properties
- WrapperArray - Link -
findandfindComponentwill just return an array ofVueWrapperorDOMWrapperrespectively. - config.methods - Link - Will no longer be able to replace methods.
- config.silent - Link - not needed.
- Wrapper.options - Link - not needed.
§ Not yet implemented
- Wrapper.selector Link
- Wrapper.contains - Link
- shallowMount - Link - Stubs work, so its halfway there.
- render - Link
- renderToString - Link
- createWrapper - Link
- enableAutoDestroy - Link
- scopedSlots - ScopedSlots are not ready yet. They will most probably be merged with normal ones, and will be a function with data, similar to VTU Beta.
Drawbacks
- People will have to separate
findintofindComponentandfind. We hope this would make tests easier to read and reason with. - Snapshots would have to be updated.
- Some deprecated methods and functionality would have to be most likely installed via an extra plugin.
Adoption strategy
- Rewrite docs from ground up.
- Code-mod where possible (
find->findComponentfor most cases,destroy->unmount) - Add deprecation warnings to beta before v1 release
- Add dedicated guides on how to write better and more maintainable tests for popular tools like Vuex, Router etc..
- Work with popular Vue ecosystem libraries and frameworks, like Quasar, Nuxt and Vuetify for better understanding of user needs.
- Deprecation build with warnings.
Unresolved questions
- Stubs is still in development. It has many issues in VTU beta and we want to do it right this time. Will probably post a new RFC entirely for it.
Source: active-rfcs/0039-vtu-api.md ↗