diff --git a/src/__tests__/components/Store/VuexTest.vue b/src/__tests__/components/Store/VuexTest.vue
index 42a9b3d9..e11a014e 100644
--- a/src/__tests__/components/Store/VuexTest.vue
+++ b/src/__tests__/components/Store/VuexTest.vue
@@ -1,24 +1,20 @@
-
-
-
Counter
-
-
- {{ count }}
-
-
-
-
-
-
+
+ Counter
+
+ {{ count }}
+
+
+
+
diff --git a/src/__tests__/deprecated-options.js b/src/__tests__/deprecated-options.js
new file mode 100644
index 00000000..8e01026a
--- /dev/null
+++ b/src/__tests__/deprecated-options.js
@@ -0,0 +1,39 @@
+import {render} from '..'
+
+beforeEach(() => {
+ jest.spyOn(console, 'warn').mockImplementation(() => {})
+})
+
+afterEach(() => {
+ console.warn.mockRestore()
+})
+
+test('warns on deprecated store option', () => {
+ const Component = {template: `
`}
+
+ render(Component, {
+ store: 'anything',
+ })
+
+ expect(console.warn).toHaveBeenCalledTimes(1)
+ expect(console.warn).toHaveBeenCalledWith(
+ expect.stringContaining(
+ `Providing 'store' or 'routes' options is no longer available`,
+ ),
+ )
+})
+
+test('warns on deprecated routes option', () => {
+ const Component = {template: ``}
+
+ render(Component, {
+ routes: 'anything',
+ })
+
+ expect(console.warn).toHaveBeenCalledTimes(1)
+ expect(console.warn).toHaveBeenCalledWith(
+ expect.stringContaining(
+ `Providing 'store' or 'routes' options is no longer available`,
+ ),
+ )
+})
diff --git a/src/__tests__/plugins.js b/src/__tests__/plugins.js
deleted file mode 100644
index def1b78e..00000000
--- a/src/__tests__/plugins.js
+++ /dev/null
@@ -1,49 +0,0 @@
-import '@testing-library/jest-dom'
-import ElementPlus from 'element-plus'
-import userEvent from '@testing-library/user-event'
-import {defineComponent} from 'vue'
-import {render, screen, fireEvent, waitFor} from '..'
-import {store} from './components/Store/store'
-
-test('can set global options and custom options such as a store', async () => {
- const ComponentWithStore = defineComponent({
- template: `
-
-
-
- Hover to activate
-
-
-
- {{ $store.state.count }}
-
- `,
- })
-
- const DirectiveStub = {
- template: 'Search now
',
- }
-
- render(ComponentWithStore, {
- store,
- global: {
- plugins: [ElementPlus],
- stubs: {
- Directive: DirectiveStub,
- },
- },
- })
-
- expect(screen.getByText('Search now')).toBeInTheDocument()
-
- const button = screen.getByText('Hover to activate')
- userEvent.hover(button)
-
- await waitFor(() => expect(screen.getByText('this is content')).toBeVisible())
-
- expect(screen.getByTestId('count-value')).toHaveTextContent('0')
-
- await fireEvent.click(button)
-
- expect(screen.getByTestId('count-value')).toHaveTextContent('1')
-})
diff --git a/src/__tests__/vue-router-mocha.js b/src/__tests__/vue-router-mocha.js
deleted file mode 100644
index c7263c78..00000000
--- a/src/__tests__/vue-router-mocha.js
+++ /dev/null
@@ -1,14 +0,0 @@
-import '@testing-library/jest-dom'
-import {render} from '..'
-
-import About from './components/Router/About.vue'
-
-const routes = []
-test('uses require("vue-router").default when require("vue-router") is undefined (useful for mocha users)', () => {
- // Test for fix https://github.com/testing-library/vue-testing-library/issues/119
- jest.mock('vue-router', () => undefined)
-
- expect(() => render(About, {routes})).toThrowError(
- new TypeError("Cannot read property 'default' of undefined"),
- )
-})
diff --git a/src/__tests__/vue-router.js b/src/__tests__/vue-router.js
index 221175ab..66db0540 100644
--- a/src/__tests__/vue-router.js
+++ b/src/__tests__/vue-router.js
@@ -1,26 +1,38 @@
-// Please notice that this example is a draft example on how to test
-// the router.
-// Related issue on Vue Test Utils: https://github.com/vuejs/vue-test-utils-next/issues/152
+/* eslint-disable vue/require-prop-types */
+/* eslint-disable vue/one-component-per-file */
import '@testing-library/jest-dom'
import {waitFor} from '@testing-library/dom'
+import {defineComponent} from 'vue'
+import {createRouter, createWebHistory} from 'vue-router'
import {render, fireEvent} from '..'
import App from './components/Router/App.vue'
import Home from './components/Router/Home.vue'
import About from './components/Router/About.vue'
-const routes = [
- {path: '/', component: Home},
- {path: '/about', component: About},
-]
+test('full app rendering/navigating from base URL', async () => {
+ // Create a Router instance
+ // https://next.router.vuejs.org/api/#createrouter
+ // using a HTML5 history.
+ // https://next.router.vuejs.org/api/#createwebhistory
+ const router = createRouter({
+ history: createWebHistory(),
+ routes: [
+ {path: '/', component: Home},
+ {path: '/about', component: About},
+ ],
+ })
-test('full app rendering/navigating', async () => {
- // Notice how we pass a `routes` object to our render function.
- const {findByText, getByText, getByTestId} = render(App, {routes})
+ const {findByText, getByText, getByTestId} = render(App, {
+ global: {
+ plugins: [router],
+ },
+ })
// Vue Router navigation is async, so we need to wait until the
// initial render happens
expect(await findByText('You are home')).toBeInTheDocument()
+ expect(getByTestId('location-display')).toHaveTextContent('/')
await fireEvent.click(getByTestId('about-link'))
@@ -32,3 +44,36 @@ test('full app rendering/navigating', async () => {
expect(getByText('You are on the about page')).toBeInTheDocument()
})
+
+test('sets router initial state', async () => {
+ const Component = defineComponent({
+ props: ['to'],
+ template: `Learn More`,
+ })
+
+ const route = {
+ name: 'routeName',
+ path: '/',
+ component: defineComponent({template: ``}),
+ }
+
+ const router = createRouter({
+ history: createWebHistory(),
+ routes: [route],
+ })
+
+ const to = {name: route.name}
+
+ const {getByText} = render(Component, {
+ props: {to},
+ global: {
+ plugins: [router],
+ },
+ })
+
+ // We need to wait for router to complete the initial navigation.
+ await router.isReady()
+
+ const button = getByText('Learn More')
+ expect(button).toHaveAttribute('href', route.path)
+})
diff --git a/src/__tests__/vuex.js b/src/__tests__/vuex.js
index 7873f5bf..d0faa53a 100644
--- a/src/__tests__/vuex.js
+++ b/src/__tests__/vuex.js
@@ -1,8 +1,30 @@
import '@testing-library/jest-dom'
+import {createStore} from 'vuex'
import {render, fireEvent} from '..'
import VuexTest from './components/Store/VuexTest'
import {store} from './components/Store/store'
+test('basic test with Vuex store', async () => {
+ const storeInstance = createStore(store)
+
+ const {getByTestId, getByText} = render(VuexTest, {
+ global: {
+ plugins: [storeInstance],
+ },
+ })
+
+ expect(getByTestId('count-value')).toHaveTextContent('0')
+
+ await fireEvent.click(getByText('+'))
+ expect(getByTestId('count-value')).toHaveTextContent('1')
+
+ await fireEvent.click(getByText('+'))
+ expect(getByTestId('count-value')).toHaveTextContent('2')
+
+ await fireEvent.click(getByText('-'))
+ expect(getByTestId('count-value')).toHaveTextContent('1')
+})
+
// A common testing pattern is to create a custom renderer for a specific test
// file. This way, common operations such as registering a Vuex store can be
// abstracted out while avoiding sharing mutable state.
@@ -10,10 +32,15 @@ import {store} from './components/Store/store'
// Tests should be completely isolated from one another.
// Read this for additional context: https://kentcdodds.com/blog/test-isolation-with-react
function renderVuexTestComponent(customStore) {
- // Render the component and merge the original store and the custom one
- // provided as a parameter. This way, we can alter some behaviors of the
- // initial implementation.
- return render(VuexTest, {store: {...store, ...customStore}})
+ // Create a custom store with the original one and the one coming as a
+ // parameter. This way we can alter some of its values.
+ const mergedStoreInstance = createStore({...store, ...customStore})
+
+ return render(VuexTest, {
+ global: {
+ plugins: [mergedStoreInstance],
+ },
+ })
}
test('can render with vuex with defaults', async () => {
@@ -26,7 +53,7 @@ test('can render with vuex with defaults', async () => {
test('can render with vuex with custom initial state', async () => {
const {getByTestId, getByText} = renderVuexTestComponent({
- state: {count: 3},
+ state: () => ({count: 3}),
})
await fireEvent.click(getByText('-'))
@@ -37,17 +64,21 @@ test('can render with vuex with custom initial state', async () => {
test('can render with vuex with custom store', async () => {
// This is a silly store that can never be changed.
// eslint-disable-next-line no-shadow
- const store = {
- state: {count: 1000},
+ const store = createStore({
+ state: () => ({count: 1000}),
actions: {
increment: () => jest.fn(),
decrement: () => jest.fn(),
},
- }
+ })
// Notice how here we are not using the helper rendering method, because
// there's no need to do that here. We're passing a whole store.
- const {getByTestId, getByText} = render(VuexTest, {store})
+ const {getByTestId, getByText} = render(VuexTest, {
+ global: {
+ plugins: [store],
+ },
+ })
await fireEvent.click(getByText('+'))
expect(getByTestId('count-value')).toHaveTextContent('1000')
diff --git a/src/render.js b/src/render.js
index e5c303d8..0171441e 100644
--- a/src/render.js
+++ b/src/render.js
@@ -19,26 +19,15 @@ function render(
const baseElement = customBaseElement || customContainer || document.body
const container = customContainer || baseElement.appendChild(div)
- const plugins = mountOptions.global?.plugins || []
-
- if (store) {
- const {createStore} = require('vuex')
- plugins.push(createStore(store))
- }
-
- if (routes) {
- const requiredRouter = require('vue-router')
- const {createRouter, createWebHistory} =
- requiredRouter.default || requiredRouter
-
- const routerPlugin = createRouter({history: createWebHistory(), routes})
- plugins.push(routerPlugin)
+ if (store || routes) {
+ console.warn(`Providing 'store' or 'routes' options is no longer available.
+You need to create a router/vuex instance and provide it through 'global.plugins'.
+Check out the test examples on GitHub for further details.`)
}
const wrapper = mount(Component, {
...mountOptions,
attachTo: container,
- global: {...mountOptions.global, plugins},
})
// this removes the additional "data-v-app" div node from VTU:
diff --git a/types/index.d.ts b/types/index.d.ts
index c886447a..f479111f 100644
--- a/types/index.d.ts
+++ b/types/index.d.ts
@@ -3,8 +3,6 @@
import {EmitsOptions} from 'vue'
import {MountingOptions} from '@vue/test-utils'
-import {StoreOptions} from 'vuex'
-import {RouteRecordRaw} from 'vue-router'
import {queries, EventType, BoundFunctions} from '@testing-library/dom'
// eslint-disable-next-line import/no-extraneous-dependencies
import {OptionsReceived as PrettyFormatOptions} from 'pretty-format'
@@ -32,9 +30,15 @@ type VueTestUtilsRenderOptions = Omit<
MountingOptions>,
'attachTo' | 'shallow' | 'propsData'
>
-type VueTestingLibraryRenderOptions = {
- store?: StoreOptions<{}>
- routes?: RouteRecordRaw[]
+interface VueTestingLibraryRenderOptions {
+ /**
+ * @deprecated Add a Vuex instance through `global.plugins` array instead.
+ */
+ store?: any
+ /**
+ * @deprecated Add a Router instance through `global.plugins` array instead.
+ */
+ routes?: any
container?: Element
baseElement?: Element
}
diff --git a/types/test.ts b/types/test.ts
index aeb5df89..06aea9c4 100644
--- a/types/test.ts
+++ b/types/test.ts
@@ -77,12 +77,8 @@ export function testOptions() {
},
global: {
config: {isCustomElement: _ => true},
+ plugins: [],
},
- store: {
- state: {count: 3},
- strict: true,
- },
- routes: [{path: '/', component: () => SomeComponent, name: 'route name'}],
baseElement: document.createElement('div'),
container: document.createElement('div'),
})