Super useful counter: {{ counter }}
``` ```javascript import { ref } from 'vue' import { useCounter } from '~/composables/useCounter' jest.mock('~/composables/useCounter') describe('MyComponent', () => { const increaseMock = jest.fn() const counter = ref(1) beforeEach(() => { useCounter.mockReturnValue({ increase: increaseMock, counter }) }) describe('When the counter is 2', () => { beforeEach(() => { counter.value = 2 createComponent() }) it('...', () => {}) }) it('should default to 1', () => { createComponent() expect(findSuperUsefulCounter().text()).toBe(1) // failure }) }) ``` Note in the above example that we are creating both a mock of the function that is returned by the composable and the `counter` ref - however a very important step is missing the example. The `counter` constant is a `ref`, which means that on every test when we modify it the value we assign to it will be retained. In the example the second `it` block will fail as the `counter` will retain the value assigned in some of our previous tests. The solution and best practice is to _always_ reset your `ref`s on the top most level `beforeEach` block. ```javascript import { ref } from 'vue' import { useCounter } from '~/composables/useCounter' jest.mock('~/composables/useCounter') describe('MyComponent', () => { const increaseMock = jest.fn() // We can initialize to `undefined` to be extra careful const counter = ref(undefined) beforeEach(() => { counter.value = 1 useCounter.mockReturnValue({ increase: increaseMock, counter }) }) describe('When the counter is 2', () => { beforeEach(() => { counter.value = 2 createComponent() }) it('...', () => {}) }) it('should default to 1', () => { createComponent() expect(findSuperUsefulCounter().text()).toBe(1) // pass }) }) ``` ### Vue router If you are testing a Vue Router configuration using a real (not mocked) `VueRouter` object, read the following [guidelines](https://test-utils.vuejs.org/guide/advanced/vue-router.html#Using-a-Real-Router). A source of failure is that Vue Router 4 handles routing asynchronously, therefore we should `await` for the routing operations to be completed. You can use the `waitForPromises` utility to wait until all promises are flushed. In the following example, a test asserts that VueRouter navigated to a page after clicking a button. If `waitForPromises` is not invoked after clicking the button, the assertion would fail because the router's state hasn't transitioned to the target page. ```javascript it('navigates to /create when clicking New workspace button', async () => { expect(findWorkspacesListPage().exists()).toBe(true); await findNewWorkspaceButton().trigger('click'); await waitForPromises(); expect(findCreateWorkspacePage().exists()).toBe(true); }); ``` ### Vue Apollo troubleshooting You might encounter some unit test failures on components that execute Apollo mutations and update the in-memory query cache, for example: ```shell ApolloError: 'get' on proxy: property '[property]' is a read-only and non-configurable data property on the proxy target but the proxy did not return its actual value (expected '#