Learn SvelteKit - Testing & Quality
Episode 16 of 24

Learn SvelteKit - Testing & Quality

This episode covers code quality through testing: unit testing with Vitest and Svelte Testing Library, integration testing for API routes, E2E testing with Playwright, plus static analysis and type checking.

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

Introduction

The larger an application grows, the more expensive an error discovered only in production becomes. Episode 16 covers testing and quality in SvelteKit: unit testing with Vitest and Svelte Testing Library, integration testing for API routes, E2E testing with Playwright, plus static analysis and type checking.

Testing is not just about running code — it builds the confidence to change code without fear of breaking what already works. A good test layer works like a safety net: unit tests for the smallest logic, integration tests between modules, and E2E tests for real user flows.

After this episode, you have a complete testing setup that runs in CI and gives fast feedback on every change.

Unit Testing with Vitest

Configuring Vitest in Vite

Vitest runs on top of Vite, so it reuses the same project configuration as SvelteKit. To test components, add the jsdom environment and the testing library plugin.

JSVitest configuration
import { defineConfig } from "vitest/config";
import { svelte } from "@sveltejs/vite-plugin-svelte";
import { svelteTesting } from "@testing-library/svelte/vite";
 
export default defineConfig({
    plugins: [svelte(), svelteTesting()],
    test: {
        environment: "jsdom",
        include: ["src/**/*.test.ts"]
    }
});

Writing Component Tests

Svelte Testing Library lets you render components and interact with them like a user would. Assertions focus on observable results, not internal implementation details.

Component unit test
import { render, screen } from "@testing-library/svelte";
import { describe, it, expect } from "vitest";
import Tombol from "./Tombol.svelte";
 
describe("Tombol", () => {
    it("menampilkan label dan merespons klik", async () => {
        render(Tombol, { props: { label: "Kirim" } });
        const tombol = screen.getByText("Kirim");
        expect(tombol).toBeTruthy();
    });
});

Integration Testing and API Route Tests

Testing Server Actions and Load Functions

Server logic such as server actions and load functions can be tested directly without a browser: call the handler with a mock event object and inspect the result. This is far faster than E2E for validating business rules.

Server action test
import { describe, it, expect } from "vitest";
import { actions } from "./+page.server.js";
 
describe("action simpan", () => {
    it("menolak nama yang terlalu pendek", async () => {
        const form = new FormData();
        form.set("nama", "ab");
 
        const hasil = await actions.simpan({
            request: new Request("http://localhost", { method: "POST", body: form })
        });
 
        expect(hasil.status).toBe(400);
    });
});

Verifying Endpoints with Real Requests

For a +server.js endpoint, create real Request and URL objects and call the handler method. This way the paths for query parsing, headers, and response building are tested end-to-end at the code level, without needing to run a server.

E2E Testing with Playwright

Setting Up Playwright

Playwright tests the application as it actually runs in a browser. The default configuration already covers Chromium, Firefox, and WebKit, so cross-browser compatibility is tested.

Install and run Playwright
npm install -D @playwright/test
npx playwright install --with-deps
npx playwright test

Writing Real-Flow Tests

E2E mimics user behavior: visiting pages, filling forms, and checking results. Because it runs in a real browser, it catches issues that unit tests miss, such as hydration and cross-component interactions.

Login flow test
import { test, expect } from "@playwright/test";
 
test("login berhasil membawa ke dashboard", async ({ page }) => {
    await page.goto("/login");
    await page.getByLabel("Email").fill("user@example.com");
    await page.getByLabel("Password").fill("rahasia");
    await page.getByRole("button", { name: "Masuk" }).click();
 
    await expect(page).toHaveURL("/dashboard");
});

Static Analysis and Type Checking

Type Checking with svelte-check

Certain kinds of errors — wrong props, incorrect route options, mismatched data types — do not surface at runtime but can be detected by a type checker. svelte-check analyzes the entire project, including .svelte files.

Run type checking
npx svelte-kit sync
npx svelte-check --tsconfig ./tsconfig.json

Making Quality Automatic

Combine all quality tools into a single command in package.json, for example npm run check which runs svelte-kit sync then svelte-check, and npm run lint for ESLint. Run both in CI before the build so code that does not meet standards never reaches production.

Closing

Key takeaways:

  • Vitest shares configuration with Vite and tests components with jsdom.
  • Svelte Testing Library emphasizes interaction from the user's point of view.
  • Server actions and load functions can be tested directly without a browser.
  • Playwright tests real flows in an actual browser.
  • svelte-check catches type errors across the whole project.
  • Run lint, check, and tests in CI to keep quality standards.

In the next episode we get into accessibility & UX: ARIA roles, keyboard navigation and focus management, semantic HTML and accessible forms, responsive layout and inclusive design, plus the fundamentals of internationalization and localization.

Learn SvelteKit - Testing & Quality | Learn SvelteKit