Pixel art e2e checks run through in a full CI run (#130)

CI has been red since 66d6aaf (tasks 221 and 223, two failures each).
Both failures come from the tests added with #130, not from the
editor.

- Module 04 still expected 19 asset types in the + menu. Pixel art
  and Palette make it 21.
- Module 48 died with "reading 'assets'". The password change in
  module 45 ends every other session of the e2e account, including
  the one the tools had cached, so api() got a 401. api() now drops
  the cached session and signs in once more on a 401.

Tests:
- GM_STEPS=4,45,48 (fresh seed): ALL PASSED, 102 checks.
- Counter-check: without the retry module 48 dies with exactly the
  CI error.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
adminandClaude Opus 5 committed 2026-09-21 18:48:47 +02:00
1 parent 6a2b06dd4b
commit 8adef83f23
3 files changed
+20 -5

No files matched your search

+2 -2
View File
@@ -77,7 +77,7 @@ export async function assets(t) {
// 4c. Create a new asset through the + menu. Since #43 the menu is two alphabetical groups –
// what can be placed in a scene, a line, then what only lives in the library – and it is
// tall enough to show all nineteen types without scrolling.
// tall enough to show all twenty-one types without scrolling.
await clickText('+');
const rows = await json('__gm.menuRows()');
const cut = rows.indexOf(null);
@@ -90,7 +90,7 @@ export async function assets(t) {
);
check(
'every asset type is offered once, each group sorted by label',
placeable.length + library.length === 19 &&
placeable.length + library.length === 21 &&
String(placeable) === String([...placeable].sort()) &&
String(library) === String([...library].sort()),
JSON.stringify({ placeable, library }),
+8
View File
@@ -52,6 +52,14 @@ export async function sessionCookie(baseUrl) {
return cookie;
}
/**
* Drops the cached session, so the next request signs in again. Changing the password ends every
* other session of the account (#182) – the step that does it leaves the tools' one dead.
*/
export function forgetSession(baseUrl) {
cookies.delete(baseUrl);
}
/** The headers a tool's `fetch` needs on top of its own. */
export async function authHeaders(baseUrl) {
return { Cookie: await sessionCookie(baseUrl) };
+10 -3
View File
@@ -4,7 +4,7 @@
* the summary line is missing, since chromium can die halfway under memory pressure.
*/
import { writeFileSync } from 'node:fs';
import { authHeaders, SESSION_COOKIE, sessionToken } from './auth.mjs';
import { authHeaders, forgetSession, SESSION_COOKIE, sessionToken } from './auth.mjs';
import { launchBrowser } from './browser.mjs';
/**
@@ -400,9 +400,16 @@ function makeTools({ cdp, projectId, baseUrl, consoleLog, check, shotPrefix }) {
// the whole run hangs on this line instead of failing.
const api = async (route) => {
const url = `${baseUrl}api/index.php?r=${route}`;
const request = async () =>
fetch(url, { headers: await authHeaders(baseUrl), signal: AbortSignal.timeout(SERVER_TIMEOUT_MS) });
try {
const headers = await authHeaders(baseUrl);
return await (await fetch(url, { headers, signal: AbortSignal.timeout(SERVER_TIMEOUT_MS) })).json();
let res = await request();
// The session can have been ended by a password change in the login step (#182).
if (res.status === 401) {
forgetSession(baseUrl);
res = await request();
}
return await res.json();
} catch (error) {
throw new Error(`request to ${route} failed: ${error.message}`, { cause: error });
}