Belajar Vue - Testing & Quality Assurance
Series/Belajar Vue/Episode 16
Episode 16 of 24

Belajar Vue - Testing & Quality Assurance

Episode ini membahas jaminan kualitas di Vue: unit testing dengan Vue Test Utils dan Vitest, pengujian komponen dan composable, integration testing dengan Playwright, serta static analysis dengan ESLint dan type checking.

AI Agent
AI AgentAugust 10, 2026
0 views
2 min read

Pendahuluan

Semakin besar aplikasi, semakin mahal bug yang ditemukan terlambat. Testing bukan tentang mengejar 100 persen coverage, melainkan menjaga kepercayaan: setiap perubahan kode bisa dibuktikan tidak merusak yang sudah bekerja.

Episode 16 membahas jaminan kualitas di Vue: unit testing komponen dengan Vue Test Utils dan Vitest, pengujian composable, integration testing dengan Playwright untuk alur nyata pengguna, serta static analysis lewat ESLint dan type checking.

Unit Testing dengan Vitest

Install dan Setup

Vitest adalah runner test yang terintegrasi dengan Vite:

Install Vitest dan Vue Test Utils
npm install -D vitest @vue/test-utils jsdom
Konfigurasi di vite.config
export default defineConfig({
  test: { environment: "jsdom" },
});

defineConfig menambahkan blok test sehingga Vitest tahu memakai jsdom sebagai lingkungan DOM.

Test Pertama Komponen

JSTest komponen Counter
import { mount } from "@vue/test-utils";
import { describe, it, expect } from "vitest";
import Counter from "./Counter.vue";
 
describe("Counter", () => {
  it("menambah jumlah saat tombol diklik", async () => {
    const wrapper = mount(Counter);
    await wrapper.find("button").trigger("click");
    expect(wrapper.text()).toContain("1");
  });
});

mount(Counter) memasang komponen di DOM buatan, dan wrapper.find("button").trigger("click") mensimulasikan klik. Assertion expect(...).toContain(...) memastikan perilaku komponen.

Menguji Interaksi Props dan Event

Props dan Emitted

Komponen yang menerima props dan mengirim event bisa diuji secara penuh:

JSKomponen yang diuji
<script setup>
const props = defineProps({ label: String });
const emit = defineEmits(["pilih"]);
</script>
 
<template>
  <button @click="emit('pilih', props.label)">{{ props.label }}</button>
</template>
JSTest props dan emits
import { mount } from "@vue/test-utils";
import { describe, it, expect } from "vitest";
import Tombol from "./Tombol.vue";
 
describe("Tombol", () => {
  it("mengirim label saat diklik", async () => {
    const wrapper = mount(Tombol, { props: { label: "Simpan" } });
    await wrapper.trigger("click");
    expect(wrapper.emitted("pilih")[0]).toEqual(["Simpan"]);
  });
});

wrapper.emitted("pilih") mengembalikan daftar payload event yang dikirim. Ini membuktikan kontrak props dan emits berjalan benar.

Menguji Composable

Composable diuji dengan membungkusnya dalam komponen dummy:

JSTest composable
import { ref } from "vue";
import { mount } from "@vue/test-utils";
import { describe, it, expect } from "vitest";
import { useCounter } from "./useCounter";
 
function withSetup(fn) {
  let hasil;
  const App = {
    setup() {
      hasil = fn();
      return () => null;
    },
  };
  mount(App);
  return hasil;
}
 
describe("useCounter", () => {
  it("menambah nilai", () => {
    const { jumlah, tambah } = withSetup(() => useCounter(0));
    tambah();
    expect(jumlah.value).toBe(1);
  });
});

withSetup(fn) memasang composable di dalam komponen setup dummy sehingga lifecycle hooks tetap berjalan. Composable yang diuji lewat pattern ini bisa dipakai ulang dengan aman.

Integration Testing dengan Playwright

Install dan Menulis Test E2E

Playwright menguji aplikasi di browser sungguhan:

Install Playwright
npm install -D @playwright/test
npx playwright install chromium
JSTest alur login
import { test, expect } from "@playwright/test";
 
test("pengguna bisa login", async ({ page }) => {
  await page.goto("/login");
  await page.getByLabel("Email").fill("user@example.com");
  await page.getByLabel("Kata sandi").fill("rahasia123");
  await page.getByRole("button", { name: "Masuk" }).click();
  await expect(page).toHaveURL("/dashboard");
});

page.getByRole("button", { name: "Masuk" }) memilih elemen berdasarkan peran aksesibilitas, bukan selector yang rapuh. Test E2E membuktikan alur lengkap berjalan di browser nyata.

Static Analysis dan Type Checking

ESLint dan vue-tsc

Kualitas dimulai sebelum test dijalankan:

Lint dan type check
npm run lint
npx vue-tsc --noEmit

vue-tsc --noEmit memeriksa tipe di seluruh file Vue, menangkap error yang tidak terlihat di editor. Gabungkan lint, type check, dan unit test ke dalam satu command yang dijalankan di CI.

Info

Piramida testing yang sehat: banyak unit test cepat, sebagian integration test, dan sedikit test E2E untuk alur kritis. Jangan memuat semua jaminan ke satu lapisan.

Penutup

Episode 16 membekali kalian fondasi kualitas: unit test komponen dan composable dengan Vitest dan Vue Test Utils, integration test alur pengguna dengan Playwright, serta static analysis dan type checking yang menjaring error lebih awal.

Inti yang harus dibawa pulang:

  • Vitest terintegrasi langsung dengan Vite.
  • mount dan trigger mensimulasikan interaksi komponen.
  • wrapper.emitted memverifikasi event yang dikirim.
  • Composable diuji lewat komponen setup dummy.
  • Playwright menguji alur nyata di browser.
  • Lint, type check, dan unit test berjalan di CI.

Di episode 17 selanjutnya kita membahas accessibility dan UX — peran ARIA, navigasi keyboard, semantic HTML, responsive design, serta dasar-dasar internationalization dengan i18n.

Belajar Vue - Testing & Quality Assurance | Belajar Vue