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:
- How to read Astro error messages.
- Where
console.log()output goes: terminal or browser. - How to inspect values with
<Debug />and the dev toolbar. - How to type-check your project with
astro check. - How to unit-test functions with Vitest.
- How to test components with the Container API.
- How to test whole pages in a real browser with Playwright.
Debugging
Reading Error Messages
An Astro error tells you three things:
- What went wrong: the message, for example
Cannot read properties of undefined (reading 'join'). - Where: the file and line, for example
src/pages/index.astro:4. - Often a hint: what to try.
- Read the first line of the error carefully. It is usually the real cause.
undefinedin 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, sop.tagsisundefined. - 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 devruns. - 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 />fromastro:componentsprints 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
likesfield. 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 checkchecks every.astro,.tsand.tsxfile at once.
npx astro check
- The first time, Astro asks to install
@astrojs/checkandtypescript. Say yes. - Add it to the
buildscript 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.tswith 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 (webServerin its config). - E2E tests are slower than unit tests, so keep them for the most important journeys: home page, login, checkout.
| Kind of test | Tool | Checks | Speed |
|---|---|---|---|
| Type check | astro check | Types in every file | Fast |
| Unit test | Vitest | One function | Very fast |
| Component test | Vitest + Container API | One component's HTML | Fast |
| End-to-end test | Playwright | Whole pages in a browser | Slow |
Simple lesson: Playwright clicks through your real site in a real browser. Use it for the key journeys.
TL;DR
- Errors = read the first line: what, where (file:line), and the hint.
- Logs = frontmatter → terminal.
<script>→ browser console (F12). - Debug =
<Debug value={x} />fromastro:componentsprints values on the page. - Dev toolbar = Inspect islands, Audit for accessibility, only in
npm run dev. - astro check = type-check every file. Put it in front of
astro build. - Vitest = unit tests with
getViteConfig().test(),expect().toBe(). - Container API =
renderToString(Component, { props })in a test. - Playwright = end-to-end tests in a real browser for key journeys.
Common mistakes
| Mistake | Wrong idea | Correct idea | What goes wrong |
|---|---|---|---|
| Looking for frontmatter logs in the browser | All logs go to DevTools | Frontmatter logs go to the terminal | "My log does not work" |
| Reading only the last error line | The end is the cause | The first line is usually the cause | Fixing the wrong thing |
Leaving <Debug /> in the page | It is hidden in production | It shows to everyone | Data leaks on the live site |
Skipping astro check | The editor catches everything | It only checks open files | Type errors reach the build |
| Testing the whole HTML string | Exact HTML is the best test | Test what the visitor sees | Tests break on harmless changes |
| Only E2E tests | One kind is enough | Mix fast unit tests and a few E2E tests | Slow, 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 checkbefore builds, Vitest for functions and components, Playwright for key journeys.
Next: Deploying Your Site, where Asha's journal goes live on the internet.