Learning Astro - Testing & Quality
Episode 16 of 24

Learning Astro - Testing & Quality

This episode covers testing and quality for an Astro site: unit testing components and content pages with Vitest, integration testing with Playwright or Cypress, static analysis and linting, and accessibility testing and SEO audits.

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

Introduction

Site quality is not only measured by performance scores, but also by the confidence that every change does not break what already exists. Episode 16 covers testing and quality assurance: from small unit tests to end-to-end tests that click through pages like a real user.

Astro does not force a specific testing framework — you are free to choose. But the most common and solid combination is: Vitest for unit tests, Playwright or Cypress for integration tests, ESLint and TypeScript for static analysis, and accessibility and SEO audits.

By the end of the episode, you will have a layered testing strategy that can run in CI/CD — a topic continued in episode 19.

Unit Testing Components and Content Pages

Installing Vitest

Vitest is the test runner for Vite projects — Astro's natural partner. Add it as a dev dependency and create a helper for rendering components:

Memasang Vitest
npm install -D vitest

Create a vitest.config.mts file that adds basic configuration and a setup file, then write the first test for an Astro component:

JSUnit test komponen Card
import { describe, it, expect } from "vitest";
import Card from "../src/components/Card.astro";
import { render } from "./helpers/render";
 
describe("Card", () => {
  it("menampilkan judul dari props", async () => {
    const html = await render(Card, { judul: "Astro", deskripsi: "Cepat" });
    expect(html).toContain("Astro");
  });
});

expect(html).toContain("Astro") verifies that the component renders the title correctly. Component unit tests guarantee the HTML output stays correct when you refactor.

Testing Content Pages

For pages that depend on content collections, test through sample data. Initialize the collection with fixture content, then make sure the page produces the expected list. These unit tests catch errors that appear when a schema or template changes.

Integration Testing with Playwright or Cypress

Playwright for Real Behavior

Integration tests run a real browser and test the flows users go through. Playwright is a popular choice because of its support for all browsers and its expressive API:

Memasang Playwright
npm install -D @playwright/test
npx playwright install

Example of a navigation and interaction test:

JSTest E2E dengan Playwright
import { test, expect } from "@playwright/test";
 
test("navigasi ke halaman tentang", async ({ page }) => {
  await page.goto("http://localhost:4321");
  await page.getByRole("link", { name: "Tentang" }).click();
  await expect(page).toHaveURL(/tentang/);
  await expect(page.getByRole("heading", { name: "Tentang" })).toBeVisible();
});

The test above clicks the "Tentang" link and then verifies the heading appears. The getByRole pattern encourages writing accessible HTML.

Playwright vs Cypress

Cypress is also solid for E2E, especially with a comfortable debugging experience. The same principles apply: start the server (npm run preview), open the page, and test main behaviors like forms, navigation, and component hydration. Pick one and be consistent.

Static Analysis and Linting

Combining TypeScript and ESLint

Run all static checks in one flow:

Pemeriksaan statis
npx astro check
npx eslint src

npx astro check checks types in .astro and .ts files, while npx eslint src enforces code quality rules. They catch different classes of errors — run both.

Making Checks a Merge Gate

Set up these checks to block merges: if astro check or eslint finds an error, the pipeline fails. This prevents broken code from reaching production.

Accessibility Testing and SEO Audits

Axe for Accessibility

Axe is a library for detecting accessibility issues that can be plugged into Playwright:

JSAudit aksesibilitas di Playwright
import AxeBuilder from "@axe-core/playwright";
 
test("halaman beranda aksesibel", async ({ page }) => {
  await page.goto("http://localhost:4321");
  const hasil = await new AxeBuilder({ page }).analyze();
  expect(hasil.violations).toEqual([]);
});

AxeBuilder({ page }).analyze() reports WCAG violations such as low contrast or buttons without labels. Make these results a merge requirement.

SEO Audits

Combine with the Lighthouse SEO audit from episode 15: existing meta descriptions, hierarchical headings, correct canonical URLs, and a valid sitemap. SEO and accessibility checks are best automated in the pipeline.

Tip

Start small: unit tests for important components, one E2E flow for main navigation, and lint in CI. Slowly increase coverage as the project grows — tests that are not run are useless.

Conclusion

Episode 16 equips you with a layered testing strategy: unit testing components and content pages with Vitest, integration testing with Playwright or Cypress, static analysis with astro check and ESLint, and automated accessibility and SEO audits.

The key takeaways:

  • Vitest is the natural test runner for Vite-based projects.
  • Component unit tests verify HTML output and props.
  • Playwright tests real behavior with getByRole.
  • astro check and ESLint catch errors before merging.
  • Axe automates WCAG accessibility audits.
  • Run all tests in CI so quality is maintained automatically.

In the next episode 17, we will cover architecture and patterns: file organization and scalable project structure, reusable UI patterns and content architecture, composing static pages with dynamic islands, and patterns that make team projects easy to maintain.

Learning Astro - Testing & Quality | Learning Astro