@testing-library/vue: mounting components
Mount Vue components with @testing-library/vue, provide props and global plugins, simulate user events, and assert on the rendered template.
@testing-library/vue: mounting components is a free Frontend Academy lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Frontend Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Testing Library for Vue
@testing-library/vue provides the same user-centric testing approach for Vue 3 components. The API mirrors the React version: render(), screen queries, userEvent, and jest-dom matchers.
Installing
Install the testing library packages for Vue.
npm install -D @testing-library/vue @testing-library/user-event @testing-library/jest-dom
# Also install vitest for a Vite project:
npm install -D vitest jsdomrender() for Vue
render(Component, options) mounts a Vue component. Use the options object to pass props, global plugins, and setup options.
import { render, screen } from '@testing-library/vue';
import Button from './Button.vue';
test('renders button label', () => {
render(Button, { props: { label: 'Submit' } });
expect(screen.getByRole('button', { name: 'Submit' })).toBeInTheDocument();
});Passing Props
Pass props in the options object. TypeScript will check prop types if you use defineProps
render(UserCard, {
props: {
user: { id: 1, name: 'Alice', email: 'alice@example.com' }
}
});Providing Global Plugins
Pass global configuration (plugins, components, provide values) in the global option.
import { createPinia } from 'pinia';
import router from './router';
render(App, {
global: {
plugins: [createPinia(), router],
provide: { theme: 'dark' }
}
});Reusable renderWithPlugins Helper
Create a custom render wrapper that includes all plugins needed for testing to avoid repeating setup in every test.
// test-utils.ts
import { render } from '@testing-library/vue';
import { createPinia } from 'pinia';
export function renderWithSetup(component: any, options = {}) {
return render(component, {
global: { plugins: [createPinia()] },
...options
});
}Testing Events
Use userEvent to interact with the component, then assert on what the user sees or that emitted events occurred.
import userEvent from '@testing-library/user-event';
test('emits submit on form submit', async () => {
const user = userEvent.setup();
const { emitted } = render(LoginForm);
await user.type(screen.getByLabelText('Email'), 'alice@example.com');
await user.click(screen.getByRole('button', { name: /login/i }));
expect(emitted().submit[0]).toEqual([{ email: 'alice@example.com' }]);
});Testing Slots
Pass slot content as a string or component in render options.
render(Card, {
slots: {
default: '<p>Card body content</p>',
header: '<h2>My Card Title</h2>'
}
});
expect(screen.getByText('Card body content')).toBeInTheDocument();Testing v-model Behaviour
Fill inputs with userEvent and verify the emitted events or the displayed output matches the expected updated state.
Testing Pinia Stores
Create a fresh Pinia instance for each test. Modify store state directly for setup, then assert on the rendered output.
const pinia = createPinia();
render(Counter, { global: { plugins: [pinia] } });
const store = useCounterStore();
store.count = 5; // set initial state
await nextTick();
expect(screen.getByText('5')).toBeInTheDocument();Finding Elements After Async Updates
Vue updates the DOM asynchronously. Use await nextTick() or findBy* queries after triggering an event that causes async state changes.
import { nextTick } from 'vue';
await user.click(button);
await nextTick();
expect(screen.getByText('Updated!')).toBeInTheDocument();Quick Check
How do you pass Pinia or Vue Router to a component being tested with @testing-library/vue?
Recap: @testing-library/vue
render(Component, options) mounts Vue components. Pass props in options.props. Provide plugins in global.plugins. Use emitted() to check custom events. Pass slots in options.slots. await nextTick() for Vue async updates. Create a custom renderWithSetup() wrapper for shared plugin setup.
Frequently asked questions
Is the “@testing-library/vue: mounting components” lesson free?
Yes — the full text of “@testing-library/vue: mounting components” is free to read here on the web, and the Frontend Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Frontend Academy course, upgrade to CoddyKit PRO.
What will I learn in “@testing-library/vue: mounting components”?
Mount Vue components with @testing-library/vue, provide props and global plugins, simulate user events, and assert on the rendered template. You practise Frontend Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Frontend Academy?
No prior experience is required. Frontend Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “@testing-library/vue: mounting components” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Frontend Academy lesson?
Yes. Every Frontend Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Jest Setup and Basic Tests
- @testing-library/react: render userEvent
- @testing-library/vue: mounting components
- Mocking Modules and API Calls