Vue komponentlarini Vue Test Utils va Vitest bilan qanday test qilish mumkin?

MiddleVue.js #vue #testing

Savol

Vue Test Utils va Vitest yordamida Vue komponentlarini test qilish qanday tashkil etiladi — mount qilish, hodisalarni simulyatsiya qilish, render'ni tekshirish, shallowMount va mount o'rtasidagi farq?

Qisqa javob

Vue Test Utils — testlarda Vue komponentlarini izolyatsiyalangan muhitda mount qilish uchun rasmiy kutubxona (odatda test runner sifatida Vitest bilan). Komponent mount() orqali (barcha bola komponentlarni render qilib) yoki shallowMount() orqali (bola komponentlar stab-o'rinbosarlar bilan almashtiriladi) mount qilinadi, shundan so'ng foydalanuvchi harakatlarini simulyatsiya qilish (trigger, setValue) va yakuniy DOM yoki emit qilingan hodisalarni tekshirish mumkin.

Batafsil javob

Mount qilish. mount(Component, options) (happy-dom/jsdom orqali) virtual DOM'da render qilingan komponentning haqiqiy nusxasi atrofida "o'rov" (VueWrapper) yaratadi. options orqali props, slots, global.plugins (test muhitida Pinia, router va h.k.ni ulash uchun) uzatiladi.

mount vs shallowMount.

  • mount — komponentni barcha bola komponentlari bilan birga haqiqatan render qiladi. Butun daraxt xatti-harakati muhim bo'lgan integratsion testlar uchun mos.
  • shallowMount — faqat komponentning o'zini render qiladi, barcha bola komponentlarni esa stab-o'rinbosarlar bilan almashtiradi (bir xil nomga ega bo'sh teglar). Bu testni bola komponentlarning amalga oshirilish tafsilotlaridan izolyatsiya qiladi — faqat muayyan komponentning logikasi qiziqtirganda, uning bolalari emas (va bolalarning o'zi og'ir yoki alohida sozlashni talab qilganda) unit-testlar uchun foydali.

Hodisalarni simulyatsiya qilish. wrapper.find('button').trigger('click') DOM hodisasini emulyatsiya qiladi; kiritish maydonlari uchun — input/changeni ham ishga tushirib, v-modelni yangilaydigan wrapper.find('input').setValue('matn'). Ikkala metod ham asinxron va Vue DOM yangilanish siklini o'tkazishga ulgurishi uchun (kapot ostida await nextTick()) awaited qilinishi kerak.

Natijani tekshirish.

  • wrapper.text() / wrapper.html() — render qilingan tarkibni tekshirish.
  • wrapper.find(selector).exists() — elementning mavjudligini tekshirish.
  • wrapper.emitted('event-name') — komponent qaysi hodisalarni va qanday argumentlar bilan emit qilganini tekshirish (haqiqiy ota komponentga bog'liq bo'lmagan bola komponentlar unit-testi uchun).
  • wrapper.props() / wrapper.setProps({...}) — test doirasida komponent props'larini o'qish va o'zgartirish.

Odatda amalga oshirish tafsilotlari emas, xatti-harakat test qilinadi: X metodi chaqirilganmi emas, bosishdan keyin ekranda Y matni paydo bo'ldimi yoki mana shunday payload bilan hodisa emit qilindimi — bu testlarni komponentning ichki tuzilishini refaktoring qilishga chidamli qiladi.

Misol

<!-- Counter.vue -->
<script setup>
import { ref } from 'vue'

const props = defineProps({ initial: { type: Number, default: 0 } })
const emit = defineEmits(['limit-reached'])

const count = ref(props.initial)

function increment() {
  count.value++
  if (count.value >= 5) emit('limit-reached')
}
</script>

<template>
  <button @click="increment">Hisoblagich: {{ count }}</button>
</template>
// Counter.spec.js
import { describe, it, expect } from 'vitest'
import { mount } from '@vue/test-utils'
import Counter from './Counter.vue'

describe('Counter', () => {
  it('bosishda qiymatni oshiradi', async () => {
    const wrapper = mount(Counter, { props: { initial: 0 } })

    expect(wrapper.text()).toContain('Hisoblagich: 0')

    await wrapper.find('button').trigger('click')

    expect(wrapper.text()).toContain('Hisoblagich: 1')
  })

  it('5ga yetganda limit-reached emit qiladi', async () => {
    const wrapper = mount(Counter, { props: { initial: 4 } })

    await wrapper.find('button').trigger('click')

    expect(wrapper.emitted('limit-reached')).toHaveLength(1)
  })
})

Qo'shimcha savollar

  • mount o'rniga shallowMountni qachon tanlash kerak va komponentlar daraxtini to'liq mount qilishning qanday xavflari bor?
  • Pinia store yoki Vue Router ishlatadigan komponentni qanday test qilish mumkin?
  • wrapper.emitted() komponentning ichki holatini to'g'ridan-to'g'ri tekshirishdan nimasi bilan foydaliroq?