The test kit
dist/testkit.cjs, for a game’s headless tests in Node. It drives Chromium through the game’s own Playwright, or through puppeteer-core with the Chrome in $CHROME (as CI’s browser-actions/setup-chrome provides); $TYCHO_DRIVER picks one.
const tk = require('../vendor/tycho/dist/testkit.cjs');
const kit = await tk.launch({ gl: true }); // gl: WebGL2 in software; without, the GPU is off
const { page, errors } = await tk.open(kit, {
root: ROOT, // the game's folder, opened from a file...
serve: true, // ...or served over http
viewport: tk.PHONE_WIDE, // PHONE, PHONE_WIDE, DESKTOP, or { width, height, mobile, scale }
storage: null, // start with empty localStorage (or { key: value })
ready: 'typeof Game !== "undefined" && Game.ready', // an expression or a function run in the page
});
await tk.waitFor(page, () => Game.frame > 10);
await tk.shot(page, OUT, 'phone-start');
tk.finish('smoke', failures); // prints the verdict, exits 1 on failure
await kit.close();
| Name | What it does |
|---|---|
launch({ gl, args, driver }) |
A browser: { driver, browser, page(viewport), close() }. Each page is in a context of its own on both drivers, so nothing one page stored (a save written as it closed) reaches the next |
serve(root, routes) |
Serves a folder on a free port (version.json answers a local build) |
open(kit, options) |
A fresh page on the game, errors gathered, storage set, ready waited for |
waitFor(page, test, { timeout, every, arg }) |
Polls until true, the same under either driver |
errorsOf(page) |
Page errors and console errors, as they come |
shot(page, dir, name) |
A screenshot |
golden(file, values, { update }) |
Compares name/value pairs with a JSON file; --update writes it |
PAGE |
Helpers to put in a page (page.evaluate(tk.PAGE)): TK.hash(bytes), TK.canvas(c), TK.image(img) |
diff(kit, pngA, pngB, { tone }) |
Compares two pictures tone by tone: { same, maxTone, share, mean } |
finish(name, failures) |
The verdict (failures are annotations under GitHub Actions) |
run(name, body) |
Runs an async body returning failures; a crash is a failure too |