Testing and Debugging

By Syncfusion®, Inc. · Last updated

Reading Astro error messages, server vs browser console.log, the Debug component and the dev toolbar, astro check, unit tests with Vitest and getViteConfig(), component tests with the Container API, and end-to-end tests with Playwright.

Testing and Debugging

  • Every site has bugs. The question is who finds them first: you or your visitors.
  • Debugging means finding out why something is wrong.
  • Testing means writing small checks that run again and again, so old bugs do not come back.
  • In this lesson, you will read errors, print values in the right place, inspect props with <Debug />, and test components, functions and whole pages.

Simple lesson: debug to find a bug, test to keep it from coming back.

A Real-World Example

  • Asha changes her formatPrice() helper. Every price on the shop page breaks.
  • She only notices a week later, from an angry email.
  • Now she keeps small tests. They run on every change, and a broken helper shows up in seconds.

Press ▶ Run. This page runs three small tests on a helper and shows the results, like a test runner would.

What happened:

  • Each test calls the function with a known input and compares the result with the expected output.
  • When every test passes, you can change the code with confidence.
  • If a later change breaks the helper, a ❌ appears at once.

What You Will Learn

In this lesson, you will learn:

  1. How to read Astro error messages.
  2. Where console.log() output goes: terminal or browser.
  3. How to inspect values with <Debug /> and the dev toolbar.
  4. How to type-check your project with astro check.
  5. How to unit-test functions with Vitest.
  6. How to test components with the Container API.
  7. How to test whole pages in a real browser with Playwright.

Debugging

Reading Error Messages

An Astro error tells you three things:

  1. What went wrong: the message, for example Cannot read properties of undefined (reading 'join').
  2. Where: the file and line, for example src/pages/index.astro:4.
  3. Often a hint: what to try.
  • Read the first line of the error carefully. It is usually the real cause.
  • undefined in a message means a value you expected was missing.

Press ▶ Run. The page crashes. Read the error, then find the missing tags in the data.

  • The second post has no tags, so p.tags is undefined.
  • Fix: (p.tags ?? []).join(", "). The ?? gives an empty list when tags are missing.

Where Does console.log() Print?

Animation: a console.log in the component frontmatter travels to the terminal on the server. A console.log in a script tag travels to the browser's developer tools console.

index.astro --- console.log --- <script> console.log

Terminal server / build

Browser console F12 → Console

Frontmatter logs appear in the terminal. Script logs appear in the browser.

  • Code in the frontmatter runs on the server (or at build time). Its logs go to the terminal where npm run dev runs.
  • Code in a <script> runs in the browser. Its logs go to the browser's DevTools console (press F12).
  • Looking in the wrong place is the most common reason people think "my log does not work".

Press ▶ Run. In this lab both kinds of log appear in the Terminal panel. Notice which one comes first.

Inspecting Values with Debug

  • <Debug /> from astro:components prints any value on the page, nicely formatted.
  • Use it to see what a component really received in its props.
  • Remove it before you publish.

Press ▶ Run. The box shows the exact data the card got.

  • [JS] Leave out interface Props.
  • The box shows there is no likes field. That is why the card says "0 likes".

The Dev Toolbar

  • In npm run dev, Astro adds a small toolbar at the bottom of the page.
  • Inspect highlights islands and shows their props and directives.
  • Audit finds common accessibility and performance problems, such as images without alt.
  • Settings lets you hide it. It never appears on the built site.

When a page looks wrong, check in this order: the error overlay, the terminal, the browser console, then <Debug /> on the values you are unsure about.

Simple lesson: read the first error line, look for logs in the right place, and print unsure values with <Debug />.

Type Checking with astro check

  • TypeScript can find many bugs before the page runs, such as a misspelt prop.
  • Your editor shows these as red lines, but only for open files.
  • astro check checks every .astro, .ts and .tsx file at once.
npx astro check
  • The first time, Astro asks to install @astrojs/check and typescript. Say yes.
  • Add it to the build script so a type error stops a broken build:
{
  "scripts": {
    "build": "astro check && astro build"
  }
}

astro check only reports problems. It never changes your files.

Simple lesson: astro check type-checks the whole project. Run it before every build.

Unit Tests with Vitest

Setting Up Vitest

  • Vitest is a fast test runner made for Vite projects, and Astro is built on Vite.
  • Install it: npm install -D vitest.
  • Create vitest.config.ts with Astro's helper, so tests understand your Astro setup:
// vitest.config.ts
import { getViteConfig } from "astro/config";

export default getViteConfig({
  test: {
    // Vitest options go here.
  },
});

Writing a Test

// src/utils/price.test.ts
import { expect, test } from "vitest";
import { formatPrice } from "./price";

test("formats thousands with commas", () => {
  expect(formatPrice(1500)).toBe("₹1,500");
});
  • test() names one check. expect(value).toBe(wanted) compares.
  • Run all tests with npx vitest. It reruns them every time you save a file.

Simple lesson: Vitest runs small checks on your functions every time you save.

Testing Components with the Container API

  • The Container API renders an Astro component to an HTML string, outside a real site.
  • In a test, you render a component with some props and check the HTML.
// src/components/PostCard.test.ts
import { experimental_AstroContainer as AstroContainer } from "astro/container";
import { expect, test } from "vitest";
import PostCard from "./PostCard.astro";

test("PostCard shows the title", async () => {
  const container = await AstroContainer.create();
  const html = await container.renderToString(PostCard, {
    props: { title: "Islands explained" },
  });
  expect(html).toContain("<h2>Islands explained</h2>");
});
  • The name starts with experimental_: the API may still change a little between versions.

Press ▶ Run. The lab runs the same kind of component tests with the real Container API and shows the results.

  • [JS] Leave out interface Props.

Test what the visitor sees (a title, a price, a link), not every space and attribute. Tests that compare the whole HTML break on harmless changes.

Simple lesson: the Container API renders a component in a test, so you can check its HTML.

End-to-End Tests with Playwright

  • An end-to-end (E2E) test opens your real site in a real browser and clicks around like a visitor.
  • Playwright is a popular tool for this. Set it up with npm init playwright@latest.
// tests/home.spec.ts
import { expect, test } from "@playwright/test";

test("the like button counts", async ({ page }) => {
  await page.goto("http://localhost:4321/");
  await page.getByRole("button", { name: /Likes/ }).click();
  await expect(page.getByRole("button", { name: /Likes/ })).toHaveText("👍 Likes: 1");
});
  • Run with npx playwright test. Playwright can start your dev or preview server for you (webServer in its config).
  • E2E tests are slower than unit tests, so keep them for the most important journeys: home page, login, checkout.
Kind of testToolChecksSpeed
Type checkastro checkTypes in every fileFast
Unit testVitestOne functionVery fast
Component testVitest + Container APIOne component's HTMLFast
End-to-end testPlaywrightWhole pages in a browserSlow

Simple lesson: Playwright clicks through your real site in a real browser. Use it for the key journeys.

TL;DR

  1. Errors = read the first line: what, where (file:line), and the hint.
  2. Logs = frontmatter → terminal. <script> → browser console (F12).
  3. Debug = <Debug value={x} /> from astro:components prints values on the page.
  4. Dev toolbar = Inspect islands, Audit for accessibility, only in npm run dev.
  5. astro check = type-check every file. Put it in front of astro build.
  6. Vitest = unit tests with getViteConfig(). test(), expect().toBe().
  7. Container API = renderToString(Component, { props }) in a test.
  8. Playwright = end-to-end tests in a real browser for key journeys.

Common mistakes

MistakeWrong ideaCorrect ideaWhat goes wrong
Looking for frontmatter logs in the browserAll logs go to DevToolsFrontmatter logs go to the terminal"My log does not work"
Reading only the last error lineThe end is the causeThe first line is usually the causeFixing the wrong thing
Leaving <Debug /> in the pageIt is hidden in productionIt shows to everyoneData leaks on the live site
Skipping astro checkThe editor catches everythingIt only checks open filesType errors reach the build
Testing the whole HTML stringExact HTML is the best testTest what the visitor seesTests break on harmless changes
Only E2E testsOne kind is enoughMix fast unit tests and a few E2E testsSlow, flaky test runs

Check Yourself

Exercises

What to Remember

  • Read the first line of an error: what, where, and the hint.
  • Frontmatter logs go to the terminal, script logs to the browser console.
  • Use <Debug /> and the dev toolbar to see values and islands.
  • Run astro check before builds, Vitest for functions and components, Playwright for key journeys.

Next: Deploying Your Site, where Asha's journal goes live on the internet.