new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Vue · Guide · all subjects

testing

29 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

Why test Vue applications

Automated tests help you and your team build complex Vue applications quickly and confidently by preventing regressions and encouraging you to break apart your application into testable functions, modules, classes, and components.

When to start testing

Start testing early. You should begin writing tests as soon as you can. The longer you wait to add tests to your application, the more dependencies your application will have, and the harder it will be to start.

Three testing types for Vue applications

Unit tests check that inputs to a given function, class, or composable are producing the expected output or side effects. Component tests check that your component mounts, renders, can be interacted with, and behaves as expected. End-to-end tests check features that span multiple pages and make real network requests against your production-built Vue application.

Unit testing focus and scope

Unit tests verify that small, isolated units of code are working as expected. They usually cover a single function, class, composable, or module. Unit tests focus on logical correctness and only concern themselves with a small portion of the application's overall functionality. They may mock large parts of your application's environment such as initial state, complex classes, third party modules, and network requests.

Two approaches to unit testing components

Whitebox unit testing is aware of the implementation details and dependencies of a component and is focused on isolating the component under test. It usually involves mocking some or all of a component's children and setting up plugin state and dependencies. Blackbox component testing is unaware of the implementation details of a component, mocks as little as possible to test the integration of your component and the entire system, and usually renders all child components.

Vitest recommended for unit testing Vue applications

Vitest is the recommended unit testing framework for Vue applications created with create-vue. Since the official setup is based on Vite, Vitest is designed specifically to leverage the same configuration and transform pipeline directly from Vite. It integrates with Vite-based projects with minimal effort and is blazing fast. Vitest is created and maintained by Vue and Vite team members.

When to use Jest instead of Vitest

Jest is only recommended if you have an existing Jest test suite that needs to be migrated over to a Vite-based project. Vitest offers more seamless integration and better performance than Jest for Vite-based projects.

Component testing granularity and scope

Component testing sits somewhere above unit testing and can be considered a form of integration testing. Components are the natural unit of isolation when validating your application's behavior. Much of your Vue application should be covered by component tests and each Vue component should have its own spec file. Component tests should catch issues relating to your component's props, events, slots, styles, classes, lifecycle hooks, and more.

Component testing best practices: do's

For visual logic, assert correct render output based on inputted props and slots. For behavioral logic, assert correct render updates or emitted events in response to user input events. Test what a component does, not how it does it. Component tests should focus on the component's public interfaces rather than internal implementation details. The public interface is limited to events emitted, props, and slots.

Component testing best practices: don'ts

Do not assert the private state of a component instance or test the private methods of a component. Testing implementation details makes tests brittle because they are more likely to break and require updates when the implementation changes. The component's ultimate job is rendering the correct DOM output, so tests focusing on the DOM output provide the same level of correctness assurance while being more robust and resilient to change. Do not rely exclusively on snapshot tests because asserting HTML strings does not describe correctness. Write tests with intentionality.

Component testing tools recommendation

Vitest is recommended for components or composables that render headlessly, used with @vue/test-utils for components and DOM testing. Cypress Component Testing is recommended for components whose expected behavior depends on properly rendering styles or triggering native DOM events, and can be used with Testing Library via @testing-library/cypress.

Speed and execution context tradeoff in component testing

Browser-based runners like Cypress can catch issues that node-based runners like Vitest cannot, such as style issues, real native DOM events, cookies, local storage, and network failures. However, browser-based runners are orders of magnitude slower than Vitest because they open a browser, compile stylesheets, and perform other operations.

@vue/test-utils for component testing

@vue/test-utils is the official low-level component testing library that provides users access to Vue-specific APIs. It is the lower-level library that @testing-library/vue is built on top of. It is recommended for testing components in applications.

@testing-library/vue for component testing

@testing-library/vue is a Vue testing library focused on testing components without relying on implementation details. Its guiding principle is that the more tests resemble the way software is used, the more confidence they can provide. However, it has issues with testing asynchronous components with Suspense and should be used with caution.

End-to-end testing scope and coverage

End-to-end tests provide coverage on what is arguably the most important aspect of an application: what happens when users actually use your applications. They focus on multi-page application behavior that makes network requests against your production-built Vue application. They often involve standing up a database or other backend and may be run against a live staging environment. E2E tests do not import any of your Vue application's code but instead rely completely on testing your application by navigating through entire pages in a real browser.

What end-to-end tests catch

End-to-end tests will often catch issues with your router, state management library, top-level components like an App or Layout, public assets, or any request handling. They catch critical issues that may be impossible to catch with unit tests or component tests. They validate many of the layers in your application by testing how user actions impact your application.

Playwright recommended for E2E testing

Playwright is a great E2E testing solution that supports Chromium, WebKit, and Firefox. Test on Windows, Linux, and macOS locally or on CI, in headless or headed mode with native mobile emulation of Google Chrome for Android and Mobile Safari. It has an informative UI, excellent debuggability, built-in assertions, parallelization, traces and is designed to eliminate flaky tests. Support for component testing is available but marked experimental. Playwright is open source and maintained by Microsoft.

Cypress for E2E testing

Cypress has an informative graphical interface, excellent debuggability, built-in assertions, stubs, flake-resistance, and snapshots. It provides stable support for component testing. Cypress supports Chromium-based browsers, Firefox, and Electron. WebKit support is available but marked experimental. Cypress is MIT-licensed, but some features like parallelization require a subscription to Cypress Cloud.

Cross-browser testing trade-offs

While it may seem desirable to have 100% cross-browser coverage, cross browser testing has diminishing returns on a team's resources due to the additional time and machine power required to run them consistently. It is important to be mindful of this trade-off when choosing the amount of cross-browser testing your application needs.

E2E testing feedback loops improvements

Modern E2E testing frameworks have helped solve the problem of long test suite execution times by adding features like parallelization, which allows CI/CD pipelines to often run magnitudes faster than before. When developing locally, the ability to selectively run a single test for the page you are working on while providing hot reloading of tests can help boost a developer's workflow and productivity.

Setting up Vitest in a Vite-based Vue project

Run: npm install -D vitest happy-dom @testing-library/vue Then update the Vite configuration to add the test option block: import { defineConfig } from 'vite' export default defineConfig({ // ... test: { globals: true, environment: 'happy-dom' } }) If using TypeScript, add 'vitest/globals' to the types field in tsconfig.json.

Creating test files with Vitest

Create a file ending in *.test.js in your project. You can place all test files in a test directory in the project root or in test directories next to your source files. Vitest will automatically search for them using the naming convention.

Running Vitest tests

Update package.json to add the test script: "scripts": { "test": "vitest" }. Then run tests with: npm test

Testing composables without lifecycle hooks or provide/inject

If a composable only uses Reactivity APIs and does not rely on lifecycle hooks or provide/inject, it can be tested by directly invoking it and asserting its returned state and methods. Example: import { ref } from 'vue' export function useCounter() { const count = ref(0) const increment = () => count.value++ return { count, increment } } test('useCounter', () => { const { count, increment } = useCounter() expect(count.value).toBe(0) increment() expect(count.value).toBe(1) })

Testing composables with lifecycle hooks or provide/inject

A composable that relies on lifecycle hooks or provide/inject needs to be wrapped in a host component to be tested. Create a helper function like: import { createApp } from 'vue' export function withSetup(composable) { let result const app = createApp({ setup() { result = composable() return () => {} } }) app.mount(document.createElement('div')) return [result, app] } Then in your test: import { withSetup } from './test-utils' import { useFoo } from './foo' test('useFoo', () => { const [result, app] = withSetup(() => useFoo(123)) app.provide(...) expect(result.foo.value).toBe(1) app.unmount() })

Alternative approach to testing complex composables

For more complex composables, it can be easier to test them by writing tests against the wrapper component using component testing techniques rather than unit testing the composable directly.

Cypress for E2E tests

Cypress is recommended for E2E tests and can also be used for component testing for Vue SFCs via the Cypress Component Test Runner.

Vitest for unit and component testing

Vitest is a test runner created by Vue/Vite team members that focuses on speed and is specifically designed for Vite-based applications to provide instant feedback loop for unit and component testing.

Jest with Vite setup

Jest can be made to work with Vite via vite-jest. However, this is only recommended if you have existing Jest-based test suites to migrate to a Vite-based setup, as Vitest provides similar functionalities with more efficient integration.

Give your agent this brain