Vitest ile Component Testi
Uygulamaları yazmak kadar teslim etmeden önce development slef testleri de oldukça önemli bir yer tutuyor. Self teslerimizi manual yapabileceğimiz gibi vitest, jest gibi toolları kullanarak da yapabiliriz.
Hadi gelin birlikte proje kuralım

Ben genelde projelerimi npm ile kuruyorum ama tabiki aynı işlemleri yarn ve pnpm kullanarak da yapabilirsiniz.

Projemizde seçmemiz gereken özellikler bu şekilde şimdi gelin birlikte proje içindeki yapıyı inceleyelim.

package.json dosyalarında bulunan scripts kısmı bize projede hangi komutun ne iş yaptığını söyler. Bu kısımda tanımlanan “dev,build,test:unit” gibi ifadeler değiştirilebilir kısımlardır. Örneğin test:unit ifadesi uzun olduğundan ben bu kısmı yalnızca test yapıp devam edeceğim. npm run test dediğimde artık .spec.js/.test.js uzantılı dosyalarımı test edebileceğim.


Componentten bağımsız test mantığında hangi kısım neyi temsil eder özet geçtim bu kod parçacığıyla.Çalıştırdığımızda göreceğimiz sonuç aşağıda. npm run test dediğimizde iki dosyayı çalıştırdı ve sonuçlarını yazdı.

Birlikte bir component oluşturup olası test senaryolarını hazırlayalım.

Yazdığımız component’in temel işlemleri şunlar
1 — Status’ün değerine göre class’ı değiştirmek.
2 — Mesaj içeriğini değiştirebilmek ve mesaj varsa “notification-slide” classını eklemek.
3- Close işlemini gerçekleştirmek.
App.vue dosyamızda componenti şu şekilde çağırıyoruz:

Şimdi componentimizde test edebileceğimiz temel senaryolar nedir?
- Status değerine göre sahip olması gereken classname’e sahip mi?
- Message propsunda değer varken sahip olması gereken class var mı?
- Close butonuna click ettiğimizde mesaj içeriği boşa çekilip elementi görmediğimiz duruma geçiyor mu?

Adım adım burada ne yaptığımı anlatayım.
1- Öncelikle componentimiz bir kopyasını oluşturacağım için “@vue/test-utils” kütüphanesini “npm install @vue/test-utils — save-dev” komutunu çalıştırarak projeme ekledim.
2- Test için kullanacağım “describe,expect,it” değişkenlerini importladım.
3- Test edeceğim componenti importladım. Mount alırken bunu kullanacağız.
4- Describe’a neyi test ettiğimi yazdım.
5- statusWrapper’ı bu şekilde tanımlama sebebim kod tekrarını önlemek. Statusu check ederken “error,info,success” için ayrı ayrı test senaryoları yazdım bunların her birinde tekrar tekrar aynı componenti mount etmektense sabit bir değişken olarak tanımlayıp kullanmayı tercih ettim.(aynı işlemi message prop’u için de gerçekleştirdim)
6- Error status’ü için yazdığım testi açıklayayım
- Bir wrapper objesi oluşturdum const wrapper = statusWrapper(‘error’) şeklinde burada aslına bakarsanız componentin bir kopyasını oluşturuyorsunuz. Eğer çıktı olarak ne verdiğini görmek isterseniz wrapper.html() komutunu çalıştırabilirsiniz.
- Beklediğim sonuç ne “notification-error” classına sahip olması. Burada wrapper.classes() size root objenin classlarını bir dizi olarak dönüyor ve siz dönen dizide aradığınız classın olup olmadığını check ediyorsunuz. Diğer statusler için de aynı durum geçerli.
7- Message propsunda bir değer yazmadığı durumda element render olmayacak bunu nasıl test ettiğimi inceleyelim.
- En başta message propsunu içeren farklı bir wrapper referansı oluşturmuştum.
- Bu test case içinde yeni bir wrapper oluşturuyorum ve değişkenimi boş string olarak gönderiyorum.
- Root elementimizde “notification-slide” diye bir class dönmemeli o yüzden toBe(false) bekliyoruz. True olduğu senaryo için bir test case daha yazabilirsiniz dilerseniz aynı şekilde yeni bir it tanımlayıp bu sefer message yerine bir string girersiniz ve bu kez toBe(true) beklersiniz
8- Click button trigger
it('emits event when close button is clicked', async () => {
const wrapper = mount(NotificationToast, {
data() {
return {
clicked: false
}
}
})
const closeButton = wrapper.find('button') // wrapper içerisinde button elementi arar ve bulunan elementi closeButtona atadı.
await closeButton.trigger('click') //buttona click oldu bu işlem için await gerektiğinden burada fonksiyonu asenkron olarak yazdık.
expect(wrapper.emitted())//işlem sırasında tetiklenen eventlerin listesini döndü
expect(wrapper.emitted()).toHaveProperty('clear-notification') //butona tıklandıktan sonra gerçekleşen eventler arasında bu emit'in gerçekleşip gerçekleşmediğini check ettik.
})