Receber por email
← Voltar para o catálogo

web-testing-vue-test-utils

Vue Test Utils patterns - mount, shallowMount, wrapper API, trigger, setValue, flushPromises, testing composables, Pinia store mocking

11estrelas
Atualizado há 7 meses

Ver no GitHub ↗ Licença: MIT

Como adicionar

/plugin marketplace add agents-inc/skills

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/web-testing-vue-test-utils/svg)](https://www.skillteca.com.br/skills/web-testing-vue-test-utils)

Skills relacionadas

Ver todas de Desenvolvimento →

Alerta por categoria

Receba novas skills de Desenvolvimento toda segunda

1 email curto, só com as skills novas de Desenvolvimento. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

Vue Test Utils Patterns

Quick Guide: Test Vue components with mount() for full rendering or shallowMount() for isolation. Use wrapper.find() with data-test attributes, await trigger() for events, await setValue() for inputs. Use flushPromises() for async operations. Mock Pinia stores with createTestingPinia().

<critical_requirements>

CRITICAL: Before Using This Skill

All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering, import type, named constants)

(You MUST await all DOM-updating methods: trigger(), setValue(), setProps(), setData())

(You MUST use flushPromises() after async operations that Vue doesn't track (API calls, timers))

(You MUST use mount() by default - only use shallowMount() for performance issues or complex isolation)

(You MUST use data-test attributes for selectors, NOT classes or IDs)

(You MUST use createTestingPinia() for Pinia stores, NOT manual mocking)

</critical_requirements>

Auto-detection: Vue Test Utils, @vue/test-utils, mount, shallowMount, wrapper, VueWrapper, DOMWrapper, trigger, setValue, setProps, setData, flushPromises, findComponent, findAllComponents, createTestingPinia, @pinia/testing

When to use:

  • Testing Vue 3 components with Composition API
  • Testing component behavior through user interactions
  • Testing components with Pinia stores
  • Testing components with Vue Router
  • Testing composables in isolation
  • Mocking child components for isolation

When NOT to use:

  • E2E testing spanning multiple pages (use your E2E solution)
  • Testing pure utility functions without Vue (use unit tests directly)
  • Visual regression testing (use visual testing tools)
  • Test runner configuration (separate concern from component testing)

Key patterns covered:

  • Mounting components (mount vs shallowMount)
  • Wrapper API (find, findAll, trigger, setValue)
  • Async testing (flushPromises, nextTick)
  • Testing composables
  • Pinia store mocking with createTestingPinia
  • Vue Router mocking
  • Stubbing child components

Detailed Resources:

  • For code examples, see examples/ folder:
  • [examples/core.md](examples/core.md) - Mounting, wrapper API, queries
  • [examples/async.md](examples/async.md) - flushPromises, nextTick, async setup
  • [examples/composables.md](examples/composables.md) - Testing composables
  • [examples/mocking.md](examples/mocking.md) - Pinia stores, Vue Router, stubs
  • For decision frameworks and anti-patterns, see [reference.md](reference.md)

<philosophy>

Philosophy

Vue Test Utils provides utilities to mount Vue components in isolation and interact with them through the wrapper API. The guiding principle: "The more your tests resemble the way your software is used, the more confidence they can give you."

Core Principles:

  1. Test User Behavior, Not Implementation: Test what users see and interact with, not internal component state
  2. Prefer Full Rendering: Use mount() by default for realistic testing; shallowMount() only when needed
  3. Use Accessible Selectors: Prefer data-test attributes over classes or IDs that may change
  4. Await Async Operations: Vue updates the DOM asynchronously - always await DOM-updating methods
  5. Minimize Stubbing: More stubs reduce test fidelity; stub only what's necessary

When to use Vue Test Utils:

  • Component integration testing with child components
  • Testing user interaction flows (clicks, input, form submission)
  • Testing reactive state and computed properties
  • Testing component lifecycle and watchers
  • Testing components with Pinia or Vue Router

When NOT to use:

  • Full user journey testing (use E2E tests)
  • Testing visual appearance (use visual regression tools)
  • Testing API endpoints directly (test component behavior with mocked responses)
  • Testing third-party library behavior (trust the library's tests)

</philosophy>

<patterns>

Core Patterns

Pattern 1: Mounting Components

Use mount() for full rendering with child components. Use shallowMount() only when you need isolation or have performance issues.

mount vs shallowMount

import { mount, shallowMount } from "@vue/test-utils";
import { TodoList } from "./todo-list.vue";

// GOOD: mount() for realistic testing
const wrapper = mount(TodoList, {
  props: {
    todos: [{ id: 1, text: "Test", done: false }],
  },
});

// Use when: You need to test component with its children
// Child components render normally, slots work, events bubble up

// shallowMount() for isolation (use sparingly)
const shallowWrapper = shallowMount(TodoList, {
  props: {
    todos: [{ id: 1, text: "Test", done: false }],
  },
});

// Use when: Component has many heavy children, or you need complete isolation
// All child components are replaced with stubs

Why mount by default: shallowMount makes the component behave differently from production. Child components don't render, slots may not work correctly, and you lose integration coverage.

See [examples/core.md](examples/core.md) for complete mounting examples.

Pattern 2: Wrapper API for Querying

Use get() when element must exist (throws on failure). Use find() when element may not exist (returns empty wrapper). Use findAll() for multiple elements.

Querying Elements

import { mount } from "@vue/test-utils";
import { SearchForm } from "./search-form.vue";

const DATA_TEST_INPUT = '[data-test="search-input"]';
const DATA_TEST_BUTTON = '[data-test="search-button"]';
const DATA_TEST_RESULT = '[data-test="search-result"]';

test("renders search form elements", () => {
  const wrapper = mount(SearchForm);

  // get() - throws if not found (use for required elements)
  const input = wrapper.get(DATA_TEST_INPUT);
  const button = wrapper.get(DATA_TEST_BUTTON);

  expect(input.exists()).toBe(true);
  expect(button.text()).toBe("Search");
});

test("shows results after search", async () => {
  const wrapper = mount(SearchForm);

  // find() - returns empty wrapper if not found (use for conditional elements)
  expect(wrapper.find(DATA_TEST_RESULT).exists()).toBe(false);

  // After triggering search...
  await wrapper.get(DATA_TEST_INPUT).setValue("test");
  await wrapper.get(DATA_TEST_BUTTON).trigger("click");

  // findAll() - returns array of wrappers
  const results = wrapper.findAll(DATA_TEST_RESULT);
  expect(results.length).toBeGreaterThan(0);
});

Why data-test attributes: CSS classes and IDs change during styling updates. data-test attributes are explicit testing contracts that don't affect production styling.

Pattern 3: User Interactions with trigger and setValue

Always await DOM-updating methods. They return a Promise that resolves after Vue updates the DOM.

Form Interactions

import { mount } from "@vue/test-utils";
import { LoginForm } from "./login-form.vue";

const DATA_TEST_EMAIL = '[data-test="email-input"]';
const DATA_TEST_PASSWORD = '[data-test="password-input"]';
const DATA_TEST_FORM = '[data-test="login-form"]';
const DATA_TEST_ERROR = '[data-test="error-message"]';

const VALID_EMAIL = "test@example.com";
const VALID_PASSWORD = "password123";

test("submits login form", async () => {
  const wrapper = mount(LoginForm);

  // setValue() for input values - MUST await
  await wrapper.get(DATA_TEST_EMAIL).setValue(VALID_EMAIL);
  await wrapper.get(DATA_TEST_PASSWORD).setValue(VALID_PASSWORD);

  // trigger() for events - MUST await
  await wrapper.get(DATA_TEST_FORM).trigger("submit.prevent");

  // Assert emitted events
  expect(wrapper.emitted("submit")).toBeTruthy();
  expect(wrapper.emitted("submit")![0]).toEqual([
    { email: VALID_EMAIL, password: VALID_PASSWORD },
  ]);
});

test("shows validation errors", async () => {
  const wrapper = mount(LoginForm);

  // Submit empty form
  await wrapper.get(DATA_TEST_FORM).trigger("submit.prevent");

  // Check
Compartilhar X LinkedIn