This episode covers testing Nuxt applications: unit testing with Vitest, component testing with Vue Test Utils, integration and end-to-end testing using Playwright, and static analysis and type checking to keep the codebase quality high.

The bigger an application gets, the more expensive bugs found in production become. Episode 16 covers how to maintain quality with testing: unit tests for pure logic, component tests for component behavior, and end-to-end tests for complete user flows.
We'll use Vitest as the test runner and Playwright for E2E — both live in the same ecosystem as Nuxt, so integration is seamless. Combined with type checking and linting, you'll have a safety net that catches problems before they reach users.
Install Vitest and Nuxt's test utility module:
npm install --save-dev vitest @vue/test-utils @nuxt/test-utilsAdd a test script in package.json:
{
"scripts": {
"test": "vitest run"
}
}Start with pure logic — the easiest thing to test. Take a store getter or util function:
import { describe, expect, it } from "vitest"
function hitungTotal(harga: number[], diskon: number) {
const dasar = harga.reduce((a, b) => a + b, 0)
return dasar - (dasar * diskon) / 100
}
describe("hitungTotal", () => {
it("menghitung total tanpa diskon", () => {
expect(hitungTotal([100000, 50000], 0)).toBe(150000)
})
it("menerapkan diskon persen", () => {
expect(hitungTotal([100000], 10)).toBe(90000)
})
})describe and it group and define test cases, expect checks the result. Run them with:
npm testUnit tests like these run fast and can be run again and again — they're the foundation of your testing pipeline.
Vue Test Utils lets you render components in a test environment. Test the KartuProduk component:
import { describe, expect, it } from "vitest"
import { mount } from "@vue/test-utils"
import KartuProduk from "~/components/KartuProduk.vue"
describe("KartuProduk", () => {
it("menampilkan nama dan harga", () => {
const wrapper = mount(KartuProduk, {
props: { nama: "Sneakers", harga: 250000 },
})
expect(wrapper.text()).toContain("Sneakers")
expect(wrapper.text()).toContain("250000")
})
})mount(KartuProduk, { props: {...} }) renders the component with specific props, then wrapper.text() checks the displayed content. Component tests are very useful for catching regressions in frequently changing UIs.
Install Playwright, then prepare the browser:
npm install --save-dev @playwright/test
npx playwright install chromiumE2E tests a flow like a real user: open a page, click, fill a form, and check the result:
import { expect, test } from "@playwright/test"
test("pengguna bisa checkout", async ({ page }) => {
await page.goto("/produk")
await page.getByRole("button", { name: "Beli" }).first().click()
await page.goto("/keranjang")
await expect(page.getByText("Sneakers")).toBeVisible()
})This test runs the real application in a browser. page.getByRole and page.getByText select elements the way users and screen readers find them — a pattern that also strengthens accessibility.
Playwright needs a running server. It's usually run after a production build:
npm run build
npx playwright testThis pattern verifies that the production application actually works — not just that code compiles.
Nuxt already uses TypeScript, but type checks only run when explicitly invoked. Make it part of your routine:
npx nuxi typecheckRun npx nuxi typecheck before every merge to catch type errors early. Pair it with ESLint from episode 3 so both code style and types are monitored at once.
Tests that aren't run automatically get forgotten. Episode 19 will wire these steps into CI/CD so every pull request is tested automatically.
Episode 16 completes your quality safety net: unit tests with Vitest for pure logic, component tests with Vue Test Utils for component behavior, E2E tests with Playwright for complete user flows, plus integrated type checking and linting.
Key takeaways:
@nuxt/test-utils are the primary choices for the Nuxt test runner.npx nuxi typecheck and ESLint regularly.In the next episode, episode 17, we will discuss accessibility and UX — ARIA support, keyboard navigation and focus management, semantic HTML with accessible components, responsive design with adaptive layouts, and the basics of internationalization. Your store will be friendly to every user.