encyklopedia.space

Vue Test Utils

Vue Test Utils (znane także jako @vue/test-utils) to oficjalny zestaw narzędzi do testowania komponentów w frameworku Vue.js. Biblioteka zapewnia API ułatwiające renderowanie, symulowanie zdarzeń i asercje w testach jednostkowych oraz integracyjnych, a jej celem jest uproszczenie procesu weryfikacji zachowania komponentów UI.

Historia

Projekt powstał w 2016 roku jako odpowiedź na rosnącą popularność testów w ekosystemie JavaScript i potrzebę spójnego narzędzia dedykowanego Vue.js. Pierwsza stabilna wersja v1.x została wydana w 2017, a w 2019 pojawiła się wersja v2.x przystosowana do Vue 3. Najnowsza majorowa wersja, v3.x, została opublikowana w 2022 i wprowadziła pełną obsługę TypeScriptu oraz integrację z Jest i Mocha.

Główne cele i założenia

  • Umożliwienie testowania komponentów w izolacji (shallow rendering) oraz w pełnym kontekście (mount).
  • Zapewnienie API przyjaznego zarówno dla programistów preferujących Jest, jak i Mocha oraz Chai.
  • Wsparcie dla nowoczesnych funkcji języka ECMAScript 6 oraz modułów bundlujących (Webpack, Vite).
  • Łatwe podłączanie do Node.js i środowisk CI/CD.

Podstawowe pojęcia

shallowMount
Funkcja renderująca komponent z zamockowanymi dziećmi, co przyspiesza testy i eliminuje zależności.
mount
Pełne renderowanie komponentu wraz z wszystkimi podkomponentami, umożliwiające testowanie interakcji pomiędzy nimi.
wrapper
Obiekt zwrócony przez shallowMount lub mount, zawierający metody do przeszukiwania drzewa, symulacji zdarzeń i asercji.
stubs
Mechanizm zastępowania wybranych podkomponentów prostymi atrapy, co pozwala kontrolować zachowanie testowanego komponentu.
props
Dane wejściowe przekazywane do komponentu; w testach najczęściej definiuje się je jako obiekt JavaScriptowy.

Podstawowe API

Poniżej przedstawiono najważniejsze metody dostępne w Vue Test Utils:

  • shallowMount(component, options?) – renderowanie komponentu w trybie płytkim.
  • mount(component, options?) – pełne renderowanie komponentu.
  • wrapper.find(selector) – wyszukiwanie pierwszego elementu pasującego do selektora CSS.
  • wrapper.findAll(selector) – zwraca kolekcję wszystkich pasujących elementów.
  • wrapper.setProps(newProps) – aktualizacja właściwości komponentu podczas testu.
  • wrapper.setData(newData) – aktualizacja lokalnego stanu (data) w komponentach opartych na Options API.
  • wrapper.trigger(event, options?) – symulacja zdarzeń DOM, takich jak click, input czy keydown.
  • wrapper.emitted([eventName]) – dostęp do zdarzeń emitowanych przy pomocy $emit.
  • wrapper.html() – zwraca dostępny w testach markup komponentu.
  • wrapper.isVisible() – sprawdza, czy element jest widoczny w DOM.

Przykładowe środowisko testowe

Typowa konfiguracja testowa wykorzystuje Jest jako runner oraz Vue.js 3. Poniżej znajduje się minimalny przykład pliku MyButton.spec.js:


// MyButton.spec.js
import { shallowMount } from '@vue/test-utils'
import MyButton from '@/components/MyButton.vue' // ścieżka wewnętrzna projektu

describe('MyButton', () => {
  it('renderuje tekst przekazany w props', () => {
    const wrapper = shallowMount(MyButton, {
      props: { label: 'Kliknij mnie' }
    })
    expect(wrapper.text()).toBe('Kliknij mnie')
  })

  it('emituje zdarzenie click po kliknięciu', async () => {
    const wrapper = shallowMount(MyButton)
    await wrapper.trigger('click')
    expect(wrapper.emitted()).toHaveProperty('click')
  })
})

Integracja z popularnymi frameworkami testowymi

Choć Vue Test Utils nie narzuca konkretnego runnera, najczęściej stosowane są:

Testowanie komponentów z Composition API

W komponentach wykorzystujących Composition API testy mogą odwoływać się do zwracanych funkcji i reaktywnych obiektów. Przykład:


import { mount } from '@vue/test-utils'
import { useCounter } from '@/composables/useCounter'

const TestComponent = {
  template: '',
  setup() {
    const { count, increment } = useCounter()
    return { count, increment }
  }
}

test('licznik zwiększa się po kliknięciu', async () => {
  const wrapper = mount(TestComponent)
  expect(wrapper.text()).toBe('0')
  await wrapper.trigger('click')
  expect(wrapper.text()).toBe('1')
})

Strategie testowania

W praktyce przyjmuje się kilka podejść:

  1. Testy jednostkowe – koncentrują się na małych fragmentach logiki (np. pojedyncze metody, computed i watchers).
  2. Testy integracyjne – sprawdzają współdziałanie kilku komponentów, najczęściej przy użyciu mount i rzeczywistych podkomponentów.
  3. Testy e2e (Cypress, Playwright) – obejmują cały stos od UI po backend, ale nie korzystają bezpośrednio z Vue Test Utils.

Najczęstsze problemy i ich rozwiązania

  • „Cannot read property ‘$emit’ of undefined” – zazwyczaj wynika z niewłaściwego użycia shallowMount bez podania wymaganych props lub stubów.
  • Problemy z asynchronicznością – po wywołaniu metod zmieniających stan należy używać await wrapper.vm.$nextTick() lub await flushPromises() (pakiet flush-promises).
  • Style i CSS – przy testach jednostkowych nie ma znaczenia renderowanie styli, ale w testach integracyjnych można dodać global: { stubs: { transition: false } } aby uniknąć opóźnień związanych z animacjami.

Przyszłość i roadmapa

Na GitHubie projektu (repozytorium wewnętrzne encyklopedii) utrzymywany jest publiczny roadmap, w którym planowane są:

  • Rozszerzenie wsparcia dla Vue 2 w wersji legacy.
  • Lepsza integracja z frameworkiem Vite i szybkie tryby hot module replacement w testach.
  • Rozbudowane typy TypeScript generowane automatycznie.

Powiązane pojęcia

Warto zapoznać się także z następującymi artykułami encyklopedycznymi: