Robot players: end-to-end tests

Play this lesson

All green, still broken

Every unit and integration test for Hyper Shards passes. Then Remy opens the game on a phone: the new logo covers the Start button, and nobody can start a run.

Small tests never open the game, so they couldn't see it. An end-to-end test (e2e test) does: it runs the whole game from one end to the other, in a real browser, the way a player would. Open the page, click Start, press keys, then check what is on screen.

Meet Playwright

Our studio writes e2e tests with Playwright, a free testing tool made by Microsoft. It drives three real browser engines:

npx playwright test runs every test in all three, several at once, and headless: the browsers run out of sight, with no window on screen. A bug that only shows up in Safari still gets caught.

Bolt says: npx playwright codegen opens a browser and writes test code while you click and type. It makes a good first draft, which you then tidy up.

A test, line by line

await page.goto('/'); opens the game.
await page.getByRole('button', { name: 'Start' }).click(); finds the Start button the way a player sees it, and clicks it.
await page.keyboard.press('ArrowLeft'); taps the left arrow.
await expect(page.getByTestId('wave')).toHaveText('Wave 1'); checks the screen.

await means "finish this step before the next one". Playwright also auto-waits: it waits until the button is visible and ready before clicking, and expect keeps retrying until the text matches or time runs out.

Finish the test

tests/shoot.spec.js
import { test, expect } from '@playwright/test'; test('hit an alien, score 10', async ({ page }) => {  await page.goto('/');  await page.getByRole('button', { name: 'Start' })    .click();  // ...the ship flies up and fires at one alien });

Kai's test hits an alien but never checks anything, so it passes even when scoring is broken. Which line belongs at line 8?

  1. await expect(page.getByTestId('score')).toHaveText('10');
  2. await page.waitForTimeout(5000);
  3. console.log('probably worked');
Show the answer

await expect(page.getByTestId('score')).toHaveText('10');

A test with no expect only proves nothing crashed. The expect checks what the player sees, and keeps retrying until the score shows 10. A fixed 5 second wait checks nothing, and Playwright's own docs warn that tests that wait for time are flaky.

Canvas is a closed box

Hyper Shards draws everything with PixiJS onto one canvas: a single picture, redrawn about 60 times a second. To Playwright, the ship and the aliens are just coloured pixels. There is no button or text inside to find.

So studios leave a way in:

Quick check

Playwright can find each alien ship in Hyper Shards with getByRole, because it reads everything drawn on the canvas.

Show the answer

False

A canvas is one big picture, so there are no elements inside it to find. Tests check the HTML HUD with getByTestId, or read the game's state through a test hook with page.evaluate.

Phone-sized screens

Garden Defense is built for phones, and many Hyper Shards players will install the PWA on a phone. Playwright can emulate (imitate) devices from a built-in list. In playwright.config.js you add one project per device:

{ name: 'phone', use: { ...devices['Pixel 7'] } }

That makes the page about 412 pixels wide, turns on touch, and tells the game it is a phone browser. Every test now runs at desktop and phone sizes, which is how the hidden Start button gets caught.

Bolt says: Emulation is close, not perfect. Before a release, still play on a real phone.

Slow, flaky, and how to debug

E2e tests have two weaknesses. They are slow: each one starts a browser and loads the game, so it takes seconds, not milliseconds. And they can be flaky: passing one run and failing the next, with no code change, because of timing, animations or random alien spawns.

Pick the e2e test

Remy wants to add one more end-to-end test to Hyper Shards. Which one deserves it?

  1. Play until game over, then check the final score appears on the leaderboard
  2. Check that scoreFor(1, 2) returns 20, by playing until a combo happens
  3. Check the colour of every alien, one test per alien
Show the answer

Play until game over, then check the final score appears on the leaderboard

Finishing a run and saving the score is a journey every player takes, and it crosses many pieces at once. Combo maths is a job for a fast unit test, and colours belong in a visual test, not in dozens of slow e2e tests.

Few and focused

Because e2e tests are slow, studios keep them few, and save them for the journeys that would hurt most if they broke. Ours:

Bolt says: Who runs all these tests on every push? Next lesson: the robot tester.

Fact-checked 9 October 2026