Playwright Component Testing in Vue: Using routing for states
In the previous post we explored how to set up Playwright with component testing in a Vue application, as well as wrote our first few component tests. In this post, we will expand further in testing the components that use Vue Router to synchronize their states with the URL params
Table of content
- Table of content
- Pre-requisites
- Create and map ItemsView with the right route
- Save search term with Route URL query params
- Test the sync between search term and URL query
- Debugging Playwright tests
- Summary
Pre-requisites
This post assumes you have a Vue project set up wit Vue Router and Playwright component testing. If you haven't done so, please refer to the previous post to set up Playwright with component testing for your Vue project.
Create and map ItemsView with the right route
We will create a new component ItemsView
that contains a search input and a list of items. The search input will filter the items based on the search term, with the following code:
<template>
<div class="items-view--container">
<div>
<input
v-model="searchTerm" placeholder="Search for an item" data-testid="search-input" id="searchbox"
/>
</div>
<ul>
<li v-for="item in searchResults" :key="item.id">
<h2>{{item}}</h2>
</li>
</ul>
</div>
</template>
And our script setup
is as follows:
import { useItems } from "../composables/useItems";
import PizzaCard from "../components/PizzaCard.vue";
import { useSearch } from "../composables/useSearch";
const props = defineProps({
intialSearchTerm: {
type: String,
default: "",
},
});
const { items } = useItems();
const { search, searchResults } = useSearch({
items: items,
defaultSearch: props.intialSearchTerm,
});
We will map the ItemsView
to the path /items
, by editing the routes
inside router/index.js
file:
export const routes = [
//...
{
path: "/items",
component: ItemsView,
name: 'items',
}
];
//...
Upon running and redirecting to /items
, the browser will display the view with a search input and the initial list of items, as seen in the below screenshot.
Next we will save the search term to the URL and test this functionality.
Save search term with Route URL query params
Within ItemsView.vue
, we will import useRouter()
from the vue-router
package, and update the URL query params whenever the search term changes using watch()
:
/**ItemsView.vue */
import { watch } from "vue";
import { useRouter } from "vue-router";
const router = useRouter();
watch(search, (value, prevValue) => {
if (value === prevValue) return;
router.replace({ query: { search: value } });
});
We also receive the component's initial search state from the URL, by adding the following code to the router/index.js
and map the route's query params with the props of the ItemsView
component:
export const routes = [
//...
{
path: "/items",
//...
props: (route) => ({
intialSearchTerm: route.query?.search || "",
}),
}
];
At this point whenever the user changes the search term and refreshes the browser, the component will remain in the same state, and won't reset the results to the default list.
Let's test it next.
Test the sync between search term and URL query
For this test scenario, we need to enable and wrap the component with routing, before mounting it. To do so, we add the following code in /playwright/index.js
:
import { beforeMount } from '@playwright/experimental-ct-vue/hooks';
import router from '../src/router'
beforeMount(async ({ app }) => {
app.use(router);
});
Playwright provides an app
instance that we can hook a mock router to it. In our demo, for simplicity we will use the same router instance from router/index.js
.
Note: This set up with beforeMount()
will apply to all E2E tests in the project. At the time of writing this post, Playwright team hasn't provided the option to configure beforeMount
per test yet.
Once done, we can add the check for the URL reflects the new search term to our should update the search term
test case:
test("should update the search term", async ({ mount, page }) => {
//...
await expect(page.url()).toContain('/?search=hello')
})
That's it! We have successfully tested the sync between the search term and the URL query params.
Debugging Playwright tests
You can debug your tests by add the --debug
flag the test command (yarn test-ct --debug
). With this flag, Playwright will open the browser's DevTools, pause the tests, and allow you to inspect the component's DOM while running the tests.
Summary
At this point, you should have a basic understanding of how to test a component that uses Vue Router to synchronize its states with the URL params, using Playwright. It will be more challenging to validate the query params synchronization in the same test scenario with Vue Test Utils, due to the limitation non browser's environment.
So when should you use Playwright for component testing? And when should you use traditional unit testing frameworks like Vue Test Utils or Testing Library? That depends on the complexity of your codebase, each component's nature and your test goals!
๐ Learn about Vue 3 and TypeScript with my new book Learning Vue!
๐ If you'd like to catch up with me sometimes, follow me on X | LinkedIn.
Like this post or find it helpful? Share it ๐๐ผ ๐