Episode ini membahas pengujian aplikasi Remix: unit testing komponen React dengan Vitest, integration testing untuk loader dan action, E2E testing dengan Playwright, serta accessibility testing dan audit kualitas menyeluruh.

Aplikasi yang berfungsi hari ini bisa rusak besok — karena perubahan kode, dependency yang naik versi, atau skenario yang tidak terpikirkan saat menulis. Episode 16 adalah jaring pengaman kalian: testing dan quality.
Kabar baiknya, arsitektur Remix membuat testing lebih mudah daripada SPA. Loader dan action adalah fungsi murni yang menerima request dan mengembalikan respons — sangat mudah diuji tanpa browser. Komponen React diuji dengan Testing Library seperti biasa. Dan untuk alur end-to-end, Playwright menyelesaikan sisanya.
Episode 16 akan membangun piramida testing: unit, integration, E2E, lalu accessibility testing sebagai audit kualitas.
Vitest adalah test runner yang sejalan dengan Vite — pilihan paling alami untuk Remix v3. Install dan konfigurasi di vite.config.ts:
npm install -D vitest @testing-library/react @testing-library/jest-dom jsdomKonfigurasi Vitest ditambahkan di vite.config.ts memakai block test dengan environment jsdom. Setelah itu, file test bisa langsung ditulis.
Unit test memverifikasi satu komponen dengan satu perilaku. Testing Library menekankan pengujian dari sudut pandang pengguna:
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { describe, expect, it } from "vitest";
import { TombolSuka } from "./TombolSuka";
describe("TombolSuka", () => {
it("menampilkan status awal", () => {
render(<TombolSuka sudahSuka={false} />);
expect(screen.getByRole("button")).toHaveTextContent("Suka");
});
it("mengganti teks saat diklik", async () => {
const user = userEvent.setup();
render(<TombolSuka sudahSuka={false} />);
await user.click(screen.getByRole("button"));
expect(screen.getByRole("button")).toHaveTextContent("Batal suka");
});
});screen.getByRole mencari elemen lewat peran aksesibilitas, bukan teks apa pun. Ini membuat test sekaligus menegakkan aksesibilitas — tombol yang tidak bisa ditemukan via peran biasanya juga sulit diakses screen reader.
Uji perilaku yang bisa dilihat pengguna: render, interaksi, dan state. Jangan menguji detail implementasi seperti nama function internal atau struktur DOM yang rapuh. Test yang bagus tidak akan patah saat implementasi di-refactor.
Loader adalah fungsi biasa yang menerima context dan mengembalikan data. Uji langsung dengan memanggilnya dan memeriksa hasilnya — tidak perlu browser:
import { describe, expect, it } from "vitest";
import { loader } from "./app/routes/posts._index";
describe("loader posts", () => {
it("mengembalikan daftar posting", async () => {
const hasil = await loader({ request: new Request("http://lokal/") });
const data = await hasil.json();
expect(Array.isArray(data.posts)).toBe(true);
});
});Loader diuji dengan Request buatan, lalu hasilnya dibaca sebagai JSON. Pendekatan ini cepat dan tidak membutuhkan infrastruktur.
Untuk test yang deterministik, mock service database atau gunakan database test terpisah. Prisma bisa di-mock atau diarahkan ke database test memakai env var DATABASE_URL. Kunci determinisme: setiap test harus bisa diulang tanpa tergantung state test lain.
E2E menguji alur lengkap seperti pengguna sungguhan: buka browser, klik, isi form, dan periksa hasil. Playwright adalah pilihan yang stabil untuk ini.
npm init playwright@latest
npx playwright testnpx playwright test menjalankan seluruh skenario dari folder e2e. Konfigurasi webServer di playwright.config bisa memulai dev server otomatis sebelum test.
Pilih alur kritis: registrasi lalu login, membuat posting, dan check-out. Playwright menunggu elemen secara otomatis, sehingga test meniru perilaku pengguna yang realistis. Mulai dari alur utama saja; detail bisa menyusul.
Aksesibilitas adalah bagian dari kualitas, bukan fitur bonus. @axe-core/playwright bisa menyisipkan pemeriksaan otomatis ke dalam test E2E:
npm install -D @axe-core/playwrightAx memeriksa puluhan aturan WCAG secara otomatis dan melaporkan pelanggaran. Jalankan ini pada setiap halaman utama.
Alat otomatis tidak menangkap semuanya. Lakukan audit manual rutin: navigasi keyboard tanpa mouse, kontras warna, dan struktur heading yang logis. Kombinasi otomatis dan manual menjaga standar aksesibilitas dalam jangka panjang.
Episode 16 membangun piramida kualitas: unit test komponen dengan Vitest, integration test loader dan action, E2E dengan Playwright, plus accessibility testing otomatis dan manual. Aplikasi kalian kini bisa tumbuh tanpa takut rusak diam-diam.
Inti yang harus dibawa pulang:
Di episode 17 selanjutnya kita akan membahas error handling dan UX — error boundary dan fallback UI, halaman error yang ramah pengguna, state pending dan error pada level request, serta pelaporan error yang benar. Test memastikan hal-hal yang diketahui; error handling menjaga hal-hal yang tidak diketahui.