In: Genel


Bir geliştirici olarak deneyim kazandıkça ve gereksinimler daha karmaşık hale geldikçe, testler ileriye doğru sağlam adımlar atmamız için bize güçlü bir araç sağlar. Ayrıca, kodumuzda değişiklik yaptıktan sonra tüm testlerin hala geçtiğini doğrulayabildiğimiz zaman bize güvenlik sağlar.

Bu gönderide, bazı temel kavramları gözden geçirmek için bir alıştırma olarak basit bir test gerçekleştireceğiz ve pratik bir örnekle, bileşenimizin kullanarak yeni bir sekme açmayı gerektirmesi durumunda test yardımcı programlarından nasıl yararlanılacağını anlayacağız. window.open işlev.

Kodu bu depoda bulabilirsiniz –> github

Feragatname: Bu yazı TDD ile ilgili değil. Ben sadece, birisi uygulamadan yeni kavramlar öğrenmeye çalıştığında ne olduğunu adım adım açıklamaya çalışıyorum ve ayrıca size bunu genellikle nasıl yaptığımı gösteriyorum.


Projemizi kurmak

Vite ile yeni bir proje oluşturmaya başlayalım. adını koyacağız vue-alay-pencere-nesnesi.

yarn create vite
Tam ekran moduna girinTam ekran modundan çık

Vue ve TypeScript’i seçin

görüntü açıklaması

görüntü açıklaması

Vite, bağımlılıkları yüklemez, bu yüzden yapmak zorunda kalacağız.

cd vue-mocking-window-object
yarn install
Tam ekran moduna girinTam ekran modundan çık

Artık projemizde kullanılacak vitest, @vue/test-utils ve typescript türlerini eklememiz gerekiyor.

yarn add -D vitest @vue/test-utils @types/jest
Tam ekran moduna girinTam ekran modundan çık

Not: -D, kitaplıkları yalnızca geliştirme bağımlılığı olarak kurmak içindir

Sonraki adım, bunları iplik ile kullanabilmemiz için package.json’a komut dosyaları eklemektir. Sadece package.json’u düzenleyin ve bunu ekleyin

"scripts": {
    "test": "vitest",
    "coverage": "vitest run --coverage"
}
Tam ekran moduna girinTam ekran modundan çık

Test yapılandırması eklemek için vite’ın yapılandırmasını değiştirmeliyiz.

import { defineConfig, UserConfigExport } from 'vitest/config'
import vue from '@vitejs/plugin-vue'


const config: UserConfigExport =
{
 plugins: [vue()],
 test: {
   globals: true,
   environment: 'jsdom',
 }
}
export default defineConfig(config)
Tam ekran moduna girinTam ekran modundan çık

Globalleri true olarak ayarlayarak, içeri aktarmaya gerek kalmadan testlere jest enjekte edecektir.
ortamı, testlerimiz için tarayıcı benzeri bir env ayarlamak üzere vitest’i yapılandırmak için kullanılıyor, aksi takdirde bir node.js env ve benzeri bir global nesne olacaktır. document bu durumda mevcut olmayacaktır.

Ve hepsi bu! Her şeyin beklendiği gibi çalışıp çalışmadığını doğrulamak için basit bir test oluşturalım.


İlk testimizi oluşturuyoruz

App.vue dosyasını değiştirin (aşağıya bakın) ve HelloComponent.vue dosyasını bileşenler klasöründen silin.

<template>
  <div>Welcome to Vue + Vitest</div>
</template>
Tam ekran moduna girinTam ekran modundan çık

Ardından, geliştirme sunucusuna başlarsak yarn dev ve url ile bir tarayıcı açın http://localhost:5173 bu sayfayı almalıyız.

görüntü açıklaması

Şimdi App.vue ile aynı klasörde App.spec.ts adında bir dosya oluşturun ve aşağıdaki kodu yazın:

import { mount } from '@vue/test-utils';
import App from './App.vue';

describe('Testing APP component', () => {
  it('render component', async () => {
    const wrapper = mount(App);

    expect(wrapper.text()).toContain('Welcome to Vue + Vitest');
  })
})
Tam ekran moduna girinTam ekran modundan çık

Bir terminalde çalıştırın yarn test ve…

görüntü açıklaması

Evet!!! Bu kolaydı değil mi?
vue test-utils yardımıyla bileşeni bir değişkene dönüştürebilir ve doğrulamalarımızı oluşturmak için jest kullanabiliriz. Bu testte, ‘Vue + Vitest’e Hoş Geldiniz’ dizesinin bileşen tarafından oluşturulduğunu doğrulayabiliriz.

Tamam, biraz daha karmaşık bir şey deneyelim.


Temel bileşen oluştur

Bir ethereum cüzdan adresi oluşturan bir bileşen istiyoruz ve üzerine tıklayarak o cüzdanın etherscan’ını gösteren yeni bir sekme açmamıza izin verin. Etherscan.io, transfer, sözleşme etkileşimi vb. gibi Ethereum işlemlerini arayabileceğiniz ve izleyebileceğiniz halka açık bir sitedir.

Bunu yapmak için (ve bu gönderiyi basit tutmak için) component klasöründe EthereumAddress.vue adlı bir dosya oluşturun ve şu kodu yazın:


<script setup lang="ts">
type Props = {
 address: string;
};
defineProps<Props>();
</script>

<template>
 <div class="ethereum-address">{{ address }}</div>
</template>

<style>
.ethereum-address {
 font-family: "Courier New";
}
</style>
Tam ekran moduna girinTam ekran modundan çık

Bu bileşeni içe aktarmak ve takmak için App.vue’yi düzenleyin ve tarayıcıda ne olduğunu kontrol edin

<script setup lang="ts">
import EthereumAddress from "./components/EthereumAddress.vue";
</script>

<template>
  <div>Welcome to Vue + Vitest</div>
  <EthereumAddress address="0x839Be166ee5Ac99309C0A0796867942822a5E8BE" />
</template>
Tam ekran moduna girinTam ekran modundan çık

Ve şimdi bunu görüyoruz

görüntü açıklaması

Tamam, harika, işe yarıyor. Bileşenimiz için bir test oluşturmanın tam zamanı.

EthereumAddress.spec.ts adlı bir dosya oluşturun ve şu kodu yazın:

import { mount } from '@vue/test-utils';
import EthereumAddress from './EthereumAddress.vue';

// Testing purpose ethereum address
const testingAddress = '0x839Be166ee5Ac99309C0A0796867942822a5E8BE';

describe('EthereumAddress Component', () => {
  it('render address passed as prop', async () => {
    // Render component
    const wrapper = mount(EthereumAddress, {
      props: {
        address: testingAddress
      }
    });

    // Verify
    expect(wrapper.text()).toBe(testingAddress);
  })
})
Tam ekran moduna girinTam ekran modundan çık

koşmak yarn test tekrar ve tüm testlerin geçtiğini doğrulayın
görüntü açıklaması


İşlevsellik ekle

Bir kullanıcı tıkladığında etherscan’i açmak istiyoruz. Bunu yapmak için kullanarak yeni bir sekme açacağız. window.open işlev.

Etherscan’ın temel url’sine ihtiyacımız var ve iyi bir uygulama olarak, tüm global sabitlerin .env dosyasından içe aktarılmasını sağlıyoruz çünkü muhtemelen her ortam için farklı temel url’lere ihtiyacınız olacak (geliştirme, test, üretim, vb…)

Bir .env dosyası oluşturun ve bunu yazın

VITE_APP_ETHERSCAN_URL=https://etherscan.io/address/
Tam ekran moduna girinTam ekran modundan çık

Şimdi bu değişkeni .env’den içe aktarmak için sabitler.ts adlı bir dosya oluşturun. Tüm sabitleri tanımlamak için tek bir dosya kullanmak, uygulamanın her yerinde .env’den içe aktarmaktan kaçınmak için de iyi bir uygulamadır. Bir şey değiştiğinde size daha fazla esneklik sağlar ve bunun gibi fazladan bir doğrulama katmanı ekler.

export const ETHERSCAN_URL = process.env.VITE_APP_ETHERSCAN_URL;
if (!ETHERSCAN_URL) {
 throw new Error('VITE_APP_ETHERSCAN_URL must be set on .env');
};
Tam ekran moduna girinTam ekran modundan çık

EthereumAddress.vue dosyasını değiştirin ve şu kodu yazın:

<script setup lang="ts">
import { ETHERSCAN_URL } from "../constants";
type Props = {
  address: string;
};

const props = defineProps<Props>();

const handleEtherscan = () => {
  window.open(`${ETHERSCAN_URL}${props.address}`, "_blank");
};
</script>

<template>
  <div
    class="ethereum-address"
    @click="handleEtherscan"
    data-testid="ethereumAddress"
  >
    {{ address }}
  </div>
</template>

<style>
.ethereum-address {
  font-family: "Courier New";
  cursor: pointer;
}
</style>
Tam ekran moduna girinTam ekran modundan çık

eklediğimize dikkat edin data-testid div bileşenindeki özellik, testlerimizde bileşeni “bulmayı” kolaylaştırır

Bileşeni tıklatan bir test ekleyerek EthereumAddress.spec.ts’yi değiştirelim ve ne olduğunu görelim.

import { mount } from '@vue/test-utils';
import EthereumAddress from './EthereumAddress.vue';

// Testing purpose ethereum address
const testingAddress = '0x839Be166ee5Ac99309C0A0796867942822a5E8BE';
// testid reference tag
const referenceLabel = '[data-testid="ethereumAddress"]';

describe('EthereumAddress Component', () => {
  it('render address passed as prop', async () => {
    // Render component
    const wrapper = mount(EthereumAddress, {
      props: {
        address: testingAddress
      }
    });

    // Verify
    expect(wrapper.text()).toBe(testingAddress);
  })

  it('click address and verify if a new tab was opened', async () => {
   const wrapper = mount(EthereumAddress, {
     props: {
       address: testingAddress
     }
   });

   wrapper.find(referenceLabel).trigger('click')
  })

})
Tam ekran moduna girinTam ekran modundan çık

Muhtemelen böyle bir şey görmelisiniz…

görüntü açıklaması

Bunun anlamı, test ortamında window.open mevcut değil, çünkü uygulanmadığını söylüyor.
Tamam, şimdi ne var?
Sadece bilmek istiyoruz window.open parametre olarak etherscan url ve _blank ile çağrıldı ve bu fonksiyonun tarayıcıda ne yaptığı umurumuzda değil. Yapacağımız şey, işlevin çağrılıp çağrılmadığını doğrulamak için spy adlı bir araç kullanmak. Vitest bu işlevi sağlar!
Testi bu şekilde değiştirin

import { mount } from '@vue/test-utils';
import { vi } from 'vitest';
import EthereumAddress from './EthereumAddress.vue';

// Testing purpose ethereum address
const testingAddress = '0x839Be166ee5Ac99309C0A0796867942822a5E8BE';
// testid reference tag
const referenceLabel = '[data-testid="ethereumAddress"]';
// Etherscan url from environmend
const ETHERSCAN_URL = import.meta.env.VITE_APP_ETHERSCAN_URL;

describe('EthereumAddress Component', () => {
  it('render address passed as prop', async () => {
    // Render component
    const wrapper = mount(EthereumAddress, {
      props: {
        address: testingAddress
      }
    });

    // Verify
    expect(wrapper.text()).toBe(testingAddress);
  })

  it('click address and verify if a new tab was opened', async () => {
    // Render component
    const wrapper = mount(EthereumAddress, {
      props: {
        address: testingAddress
      }
    });
    // Create spy for testing if window.open was called
    const spy = vi.spyOn(window, 'open');

    // Act: click on the address
    wrapper.find(referenceLabel).trigger('click')

    // Verify if window.open was called
    expect(spy).toBeCalledWith(`${ETHERSCAN_URL}${testingAddress}`, '_blank');
  })
})
Tam ekran moduna girinTam ekran modundan çık

Testleri çalıştırın! şimdi iyi olmalı!

görüntü açıklaması

Eh, testlerimiz geçti ama bu ne!?!?
window.open hala hata veriyor… ummm

Burada olan şey, işlevin window.open doğru parametrelerle doğru çağrıldı, ancak işlev aslında mevcut değil!

Bu hatayı önlemek için başka bir test aracını kullanarak window.open adında global bir fonksiyon oluşturabiliriz. Bunun adı saplama. Stub, sadece test amacıyla başka bir işlevin yerine geçmek için kullanılan bir kod parçasıdır ve vitest bize bu aracı sunmaktadır.

Bu kod satırını testin başına ekleyin. describe

// Mock global window.open
vi.stubGlobal('open', vi.fn());
Tam ekran moduna girinTam ekran modundan çık

Ve şimdi her şey yolunda, testlerimiz geçti ve hiçbir hata gösterilmedi. Tebrikler!

Bir cevap yazın

Ready to Grow Your Business?

We Serve our Clients’ Best Interests with the Best Marketing Solutions. Find out More

How Can We Help You?

Need to bounce off ideas for an upcoming project or digital campaign? Looking to transform your business with the implementation of full potential digital marketing?

For any career inquiries, please visit our careers page here.
[contact-form-7 404 "Bulunamadı"]