Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Um comando direto ignora o prompt de revisão. Verifique a origem antes de executá-lo.
This skill makes the agent write Vue 3 component tests with Vue Test Utils (VTU) + Vitest that assert on rendered output and user-observable behavior, not implementation internals. Trigger it whenever you see .vue SFCs, @vue/test-utils, mount/shallowMount, Pinia/Vuex stores under test, or a Vitest config in a Vue project.
Core Principles
Prefer mount over shallowMount. Full mount renders children so you test real behavior. Reach for shallowMount only to isolate a component from an expensive/irrelevant child — and know that stubbing children hides integration bugs.
Query by accessible roles and data-testid, not by CSS classes. Classes are styling and churn constantly; find('[data-testid="submit"]') and getByRole survive refactors and assert what users actually see.
await every state change. Vue's DOM updates are asynchronous. After trigger, setValue, setProps, or a store mutation you must await wrapper.vm.$nextTick() (or await trigger(...), which returns nextTick) before asserting, or you assert against stale DOM.
Test the component's contract: props in, events/DOM out. Assert emitted events with wrapper.emitted(), assert rendered text/attributes, and pass props. Do not assert on private data/refs or call internal methods.
Use a real Pinia instance with createTestingPinia, not hand-mocked stores. It gives you real getters, auto-spied actions, and initialState — far more faithful than stubbing the store object.
Stub the network, render the component. Mock fetch/axios at the module boundary with vi.mock; never let component tests hit a live API.
// tests/withSetup.ts — runs a composable inside a real app instanceimport { createApp } from'vue';
exportfunction withSetup<T>(composable: () => T): [T, ReturnType<typeof createApp>] {
let result!: T;
const app = createApp({ setup() { result = composable(); return() => {}; } });
app.mount(document.createElement('div'));
return [result, app];
}
Best Practices
Add data-testid to elements you assert on. It decouples tests from markup/classes and makes intent explicit.
Use wrapper.get() when an element must exist (it throws a clear error if missing) and wrapper.find().exists() when checking for absence.
Prefer findComponent(ChildStub) with a name/ref over CSS selectors when asserting child props: wrapper.findComponent(ProductCard).props('price').
Reset mocks between tests with vi.clearAllMocks() in afterEach (or clearMocks: true in config) so spy call counts don't leak.
Use createTestingPinia({ stubActions: false }) when you need actions to actually run (e.g. testing a store-driven flow end to end).
Test the rendered text/role a user would perceive, then layer in emitted-event assertions for the parent contract.
Anti-Patterns
Forgetting await after a state change.wrapper.trigger('click'); expect(...) asserts before Vue re-renders and gives flaky, confusing failures. Always await the trigger/$nextTick/flushPromises.
Asserting on internal wrapper.vm data or calling private methods. Tests coupled to implementation break on every refactor. Drive via the DOM and assert via the DOM/emitted events.
Selecting by CSS class.find('.btn-primary') shatters the moment a designer renames a class. Use data-testid or roles.
Defaulting to shallowMount everywhere. Stubbing all children means you never test that the pieces actually work together; bugs slip through the seams.
Hand-rolling a fake store object. It drifts from the real store's getters/actions. Use createTestingPinia so getters compute and actions are spied for free.
Letting tests hit a real API or a real router. Mock fetch/axios with vi.mock and stub RouterLink/router-view; otherwise tests are slow, flaky, and network-dependent.
When to Trigger This Skill
"Write Vue component tests" / "test this .vue component" / "add unit tests for my Vue app"