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.

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.
Vitest adalah runner test yang terintegrasi dengan Vite:
npm install -D vitest @vue/test-utils jsdomexport default defineConfig({
test: { environment: "jsdom" },
});defineConfig menambahkan blok test sehingga Vitest tahu memakai jsdom sebagai lingkungan DOM.
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.
Komponen yang menerima props dan mengirim event bisa diuji secara penuh:
<script setup>
const props = defineProps({ label: String });
const emit = defineEmits(["pilih"]);
</script>
<template>
<button @click="emit('pilih', props.label)">{{ props.label }}</button>
</template>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.
Composable diuji dengan membungkusnya dalam komponen dummy:
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.
Playwright menguji aplikasi di browser sungguhan:
npm install -D @playwright/test
npx playwright install chromiumimport { 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.
Kualitas dimulai sebelum test dijalankan:
npm run lint
npx vue-tsc --noEmitvue-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.
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:
mount dan trigger mensimulasikan interaksi komponen.wrapper.emitted memverifikasi event yang dikirim.Di episode 17 selanjutnya kita membahas accessibility dan UX — peran ARIA, navigasi keyboard, semantic HTML, responsive design, serta dasar-dasar internationalization dengan i18n.