
game-qa
Game QA testing with Playwright — visual regression, gameplay verification, performance, and accessibility for browser games. Use when writing or running game tests, debugging test failures, or building QA infrastructure. This is the reference skill — use qa-game for the user-facing command.
- Installs
- 1.1K
- Last 24h
- —
- Trending rank
- —
- Security
- Not audited
Install
Works with every agent the skills CLI supports.
npx skills add https://github.com/playableintelligence/game-creator --skill game-qa- 01
Install
Run the command in your project. The CLI asks which agents to install for.
- 02
Describe the task
Ask your agent for something this skill covers. It loads game-qa automatically when relevant.
- 03
Review the result
The agent follows the SKILL.md steps, scripts and references bundled with the skill.
SKILL.md
The instructions your agent reads when the skill is triggered.
Game QA with Playwright
You are an expert QA engineer for browser games. You use Playwright to write automated tests that verify visual correctness, gameplay behavior, performance, and accessibility.
Performance Notes
- Take your time with each step. Quality is more important than speed.
- Do not skip validation steps — they catch issues early.
- Read the full context of each file before making changes.
- Write tests that verify gameplay, not just that the page loads.
Reference Files
For detailed reference, see companion files in this directory:
test-patterns.md— Custom fixture code, boot tests, gameplay verification tests, scoring testsgameplay-invariants.md— All 7 core gameplay invariant patterns (scoring, death, buttons, render_game_to_text, design intent, entity audit, mute)visual-regression.md— Screenshot comparison tests, masking dynamic elements, performance/FPS tests, accessibility tests, deterministic testing patternsclock-control.md— Playwright Clock API patterns for frame-precise testingplaywright-mcp.md— MCP server setup, when to use MCP vs scripted tests, inspection flowiterate-client.md— Standalone iterate client usage, action JSON format, output interpretationmobile-tests.md— Mobile input simulation and responsive layout test patterns
Tech Stack
- Test Runner: Playwright Test (
@playwright/test) - Visual Regression: Playwright built-in
toHaveScreenshot() - Accessibility:
@axe-core/playwright - Build Tool Integration: Vite dev server via
webServerconfig - Language: JavaScript ES modules
Project Setup
When adding Playwright to a game project:
npm install -D @playwright/test @axe-core/playwright
npx playwright install chromium
Add to package.json scripts:
{
"scripts": {
"test": "npx playwright test",
"test:ui": "npx playwright test --ui",
"test:headed": "npx playwright test --headed",
"test:update-snapshots": "npx playwright test --update-snapshots"
}
}
Required Directory Structure
tests/
├── e2e/
│ ├── game.spec.js # Core game tests (boot, scenes, input, score)
│ ├── visual.spec.js # Visual regression screenshots
│ └── perf.spec.js # Performance and FPS tests
├── fixtures/
│ ├── game-test.js # Custom test fixture with game helpers
│ └── screenshot.css # CSS to mask dynamic elements for visual tests
├── helpers/
│ └── seed-random.js # Seeded PRNG for deterministic game behavior
playwright.config.js
Playwright Config
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './tests',
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: [['html', { open: 'never' }], ['list']],
use: {
baseURL: 'http://localhost:3000',
trace: 'on-first-retry',
screenshot: 'only-on-failure',
video: 'retain-on-failure',
},
expect: {
toHaveScreenshot: {
maxDiffPixels: 200,
threshold: 0.3,
},
},
projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
{ name: 'mobile-chrome', use: { ...devices['Pixel 5'] } },
],
webServer: {
command: 'npm run dev',
url: 'http://localhost:3000',
reuseExistingServer: !process.env.CI,
timeout: 30000,
},
});
Key points:
webServerauto-starts Vite before testsreuseExistingServerreuses a running dev server locallybaseURLmatches the Vite port configured invite.config.js- Screenshot tolerance is generous (games have minor render variance)
Testability Requirements
For Playwright to inspect game state, the game MUST expose these globals on window in main.js:
1. Core globals (required)
// Expose for Playwright QA
window.__GAME__ = game;
window.__GAME_STATE__ = gameState;
window.__EVENT_BUS__ = eventBus;
window.__EVENTS__ = Events;
2. render_game_to_text() (required)
Returns a concise JSON string of the current game state for AI agents to reason about the game without interpreting pixels. Must include coordinate system, game mode, score, and player state.
window.render_game_to_text = () => {
if (!game || !gameState) return JSON.stringify({ error: 'not_ready' });
const activeScenes = game.scene.getScenes(true).map(s => s.scene.key);
const payload = {
coords: 'origin:top-left x:right y:down', // coordinate system
mode: gameState.gameOver ? 'game_over' : 'playing',
scene: activeScenes[0] || null,
score: gameState.score,
bestScore: gameState.bestScore,
};
// Add player info when in gameplay
const gameScene = game.scene.getScene('GameScene');
if (gameState.started && gameScene?.player?.sprite) {
const s = gameScene.player.sprite;
const body = s.body;
payload.player = {
x: Math.round(s.x), y: Math.round(s.y),
vx: Math.round(body.velocity.x), vy: Math.round(body.velocity.y),
onGround: body.blocked.down,
};
}
// Extend with visible entities as you add them:
// payload.entities = obstacles.map(o => ({ x: o.x, y: o.y, type: o.type }));
return JSON.stringify(payload);
};
Guidelines for render_game_to_text():
- Keep the payload succinct — only current, visible, interactive elements
- Include coordinate system note (origin and axis directions)
- Include player position/velocity, active obstacles/enemies, collectibles, timers, score, and mode flags
- Avoid large histories; only include what's currently relevant
- The iterate client and AI agents use this to verify game behavior without screenshots
3. advanceTime(ms) (required)
Lets test scripts advance the game by a precise duration. The game loop runs normally via RAF; this waits for real time to elapse.
window.advanceTime = (ms) => {
return new Promise((resolve) => {
const start = performance.now();
function step() {
if (performance.now() - start >= ms) return resolve();
requestAnimationFrame(step);
}
requestAnimationFrame(step);
});
};
For frame-precise control in @playwright/test, prefer page.clock.install() + page.clock.runFor(). The advanceTime hook is primarily used by the standalone iterate client (scripts/iterate-client.js).
For Three.js games, expose the Game orchestrator instance similarly.
See test-patterns.md for custom fixture code, boot tests, gameplay verification tests, and scoring tests.
See gameplay-invariants.md for all 7 core gameplay invariant patterns (scoring, death, buttons, render_game_to_text, design intent, entity audit, mute).
When Adding QA to a Game
- Install Playwright:
npm install -D @playwright/test @axe-core/playwright && npx playwright install chromium - Create
playwright.config.jswith the game's dev server port - Expose
window.__GAME__,window.__GAME_STATE__,window.__EVENT_BUS__inmain.js - Create
tests/fixtures/game-test.jswith thegamePagefixture - Create
tests/helpers/seed-random.jsfor deterministic behavior - Write tests in
tests/e2e/:game.spec.js— boot, scene flow, input, scoring, game overvisual.spec.js— screenshot regression for each sceneperf.spec.js— load time, FPS budget
- Add npm scripts:
test,test:ui,test:headed,test:update-snapshots - Generate initial baselines:
npm run test:update-snapshots
What NOT to Test (Automated)
- Exact pixel positions of animated objects (non-deterministic without clock control)
- Active gameplay screenshots — moving objects make stable screenshots impossible; use MCP instead
- Audio playback (Playwright has no audio inspection; test that audio objects exist via evaluate)
- External API calls unless mocked (e.g., Play.fun SDK — mock with
page.route()) - Subjective visual quality — use MCP for "does this look good?" evaluations
FAQ
What does the game-qa skill do?
Game QA testing with Playwright — visual regression, gameplay verification, performance, and accessibility for browser games. Use when writing or running game tests, debugging test failures, or building QA infrastructure. This is the reference skill — use qa-game for the user-facing command.
How do I install game-qa?
Run npx skills add https://github.com/playableintelligence/game-creator --skill game-qa in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/game-qa/ (personal) or .claude/skills/game-qa/ (project).
Which AI agents can use game-qa?
Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.
Is game-qa safe to install?
No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.
Who maintains game-qa?
It is published by playableintelligence in playableintelligence/game-creator. It has 1,083 recorded installs.
More from playableintelligence/game-creator
game-designer
playableintelligence/game-creator
Game UI/UX designer that analyzes and improves the visual polish, atmosphere, and player experience of browser games. Use when a game needs visual improvements, better backgrounds, particles, animations, screen transitions, juice/feel, or overall aesthetic upgrades.
game-assets
playableintelligence/game-creator
Game asset engineer that creates pixel art sprites, animated characters, and visual entities for browser games. Use when a game needs better character art, enemy sprites, item visuals, or any upgrade from basic geometric shapes to recognizable pixel art.
design-game
playableintelligence/game-creator
Audit and improve the visual design, polish, and player experience of an existing game. Use when the user says "make my game look better", "improve the design", "add polish", "add juice", "add particles", "fix the UI", or "make it more visually appealing". Do NOT use for gameplay logic changes (use add-feature instead).
phaser
playableintelligence/game-creator
Build 2D browser games with Phaser 3 using scene-based architecture and centralized state. Use when creating a new 2D game, adding 2D game features, working with Phaser, or building sprite-based web games.
game-audio
playableintelligence/game-creator
Game audio engineer using Web Audio API for procedural music and sound effects in browser games. Zero dependencies. Use when adding music or SFX to a game.
game-architecture
playableintelligence/game-creator
Game architecture patterns and best practices for browser games. Use when designing game systems, planning architecture, structuring a game project, or making architectural decisions about game code.
Popular testing & qa skills
tdd
mattpocock/skills
Test-driven development. Use when the user wants to build features or fix bugs test-first, mentions "red-green-refactor", or wants integration tests.
grilling
mattpocock/skills
Grill the user relentlessly about a plan, decision, or idea. Use when the user wants to stress-test their thinking, or uses any 'grill' trigger phrases.
migrate-to-shoehorn
mattpocock/skills
Migrate test files from as type assertions to @total-typescript/shoehorn. Use when user mentions shoehorn, wants to replace as in tests, or needs partial test data.
run-train
lllllllama/rigorpilot-skills
Rigor Train skill for deep learning research repositories. Use when a documented or selected training command should be run conservatively for startup verification, short-run verification, full kickoff, or resume, with command, config, seed, log, checkpoint, status, and metric evidence written to standardized trainoutputs/. Do not use for environment setup, exploratory sweeps, speculative idea implementation, or end-to-end orchestration.
test-driven-development
obra/superpowers
Use when implementing any feature or bugfix, before writing implementation code
finishing-a-development-branch
obra/superpowers
Use when implementation is complete, all tests pass, and you need to decide how to integrate the work