Texture fill e2e checks pick the right image in a full run (#186)
game-maker / gate (push) Successful in 2m19s
game-maker / suite (push) Successful in 8m5s

CI run 217 for 592ea94 failed three checks in block 47i. In the full
run the texture list is longer than in a single module run, so the
picker click missed "halves" and the texture stayed empty.

- The check now types "halves" into the menu search field and picks
  it with Enter, independent of the list length.
- FIND_HALVES looks the image up by name. Matching only by size had
  picked the 32 px image "wedge" in the full run.
- The texture fill check forces a redraw before reading pixels. After
  the work of earlier modules the vector tab does not redraw once the
  texture has loaded. That bug is tracked in #196, and the forced
  redraw goes away with it.

Tests:
- ./check.sh: CHECK EXIT 0
- npm run build: BUILD EXIT 0
- GM_STEPS=47 (fresh seed): ALL PASSED, 54 checks
- Full run not repeated locally. CI decides.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
adminandClaude Opus 5 committed 2026-09-21 14:59:06 +02:00
1 parent 592ea942d9
commit 1c8a20fcac
2 files changed
+23 -7

No files matched your search

+17 -5
View File
@@ -832,23 +832,35 @@ export async function vectorArt(t) {
const halvesName = await json( const halvesName = await json(
`__gm.state.project.assets.find((a) => a.id === ${JSON.stringify(halves?.id ?? '')})?.name ?? null`, `__gm.state.project.assets.find((a) => a.id === ${JSON.stringify(halves?.id ?? '')})?.name ?? null`,
); );
const halvesEntry = halvesName && (await inOverlay(halvesName)); // Picked through the search box: after the earlier modules the list holds 30-odd pictures, and
if (halvesEntry) await click(halvesEntry.x, halvesEntry.y); // an entry below the fold of the capped menu cannot be clicked. Enter takes the first match; a
else await press('Escape'); // click would hit the typed name in the search box first.
if (halvesName) {
await typeText(halvesName);
await settle();
}
const filteredOffers = (await json('__gm.menuRows()')) ?? [];
const halvesEntry = Boolean(halvesName) && filteredOffers.includes(halvesName);
await press(halvesEntry ? 'Enter' : 'Escape');
await settle(); await settle();
// The picture loads asynchronously and the shape keeps its plain fill until it is there. In the
// full run the tab then waits for the next redraw instead of drawing when the picture lands
// (#196), so the check asks for that redraw itself. Remove the preview() with #196.
await sleep(300); await sleep(300);
await evaluate('__gm.state.preview()');
await settle();
const tiled = (await sky())?.paint; const tiled = (await sky())?.paint;
const leftHalf = await tabPixel(60, 100); const leftHalf = await tabPixel(60, 100);
const rightHalf = await tabPixel(196, 100); const rightHalf = await tabPixel(196, 100);
check( check(
'Texture offers the uploaded pictures but no drawing, and fills the shape with the one picked', 'Texture offers the uploaded pictures but no drawing, and fills the shape with the one picked',
Boolean(halvesEntry) && halvesEntry &&
!pictureOffers.includes('Emblem') && !pictureOffers.includes('Emblem') &&
tiled?.type === 'texture' && tiled?.type === 'texture' &&
tiled.texture === halves?.id && tiled.texture === halves?.id &&
colourDistance(leftHalf, HALVES_LEFT) < 20 && colourDistance(leftHalf, HALVES_LEFT) < 20 &&
colourDistance(rightHalf, HALVES_RIGHT) < 20, colourDistance(rightHalf, HALVES_RIGHT) < 20,
JSON.stringify({ pictureOffers, tiled, leftHalf, rightHalf }), JSON.stringify({ filteredOffers, tiled, leftHalf, rightHalf }),
); );
const tileCorner = await screenAt(228, 228); const tileCorner = await screenAt(228, 228);
+6 -2
View File
@@ -14,6 +14,10 @@ export const PASTE_HALVES = `(async () => {
export const HALVES_LEFT = '#e63c3c'; export const HALVES_LEFT = '#e63c3c';
export const HALVES_RIGHT = '#3cc85a'; export const HALVES_RIGHT = '#3cc85a';
/** The pasted picture's asset, once the paste has landed. */ /**
* The pasted picture's asset, once the paste has landed: the newest one named after the pasted
* file. Size alone is not enough – in the full run a module before 47 leaves a 32 px "wedge"
* behind, and taking the first 32 px texture picked that one (CI task 217).
*/
export const FIND_HALVES = export const FIND_HALVES =
"__gm.state.project.assets.filter((a) => a.type === 'texture' && a.width === 32 && a.height === 32).map((a) => ({ id: a.id, file: a.file }))[0] ?? null"; "__gm.state.project.assets.filter((a) => a.type === 'texture' && a.name === 'halves' && a.width === 32 && a.height === 32).map((a) => ({ id: a.id, file: a.file })).at(-1) ?? null";