From a07c663ca9923092a3727a1709a626eceede6b5d Mon Sep 17 00:00:00 2001 From: Codeman maintainer Date: Wed, 7 Oct 2026 04:05:30 +0200 Subject: [PATCH] test(tiles): the grid harness finds a tile's element, and serves the pure helpers Five tile-grid tests defined the same `tileEl(id)` lookup and three more inlined it; the harness (test/mocks/tile-grid-vm.ts) now exports it and they import it. tile-grid-open-set built a second vm context just to read constants.js, although the harness it already imports has loaded the same file: it reads windowStub.CodemanTileGrid instead. No assertion changed. Mutation-checked: tiles without their data-session-id fail 34 tests across the seven files, and a broken tileGridOpenSet fails the open-set cases. Co-Authored-By: Claude Opus 5.5 (1M context) --- test/mocks/tile-grid-vm.ts | 2 ++ test/tile-grid-attach.test.ts | 4 +--- test/tile-grid-auto-join.test.ts | 4 ++-- test/tile-grid-chrome.test.ts | 5 ++--- test/tile-grid-dividers.test.ts | 2 +- test/tile-grid-entry-points.test.ts | 2 +- test/tile-grid-open-set.test.ts | 12 ++++-------- test/tile-grid-select-branch.test.ts | 4 ++-- test/tile-grid-zoom.test.ts | 11 +++++++++-- 9 files changed, 24 insertions(+), 22 deletions(-) diff --git a/test/mocks/tile-grid-vm.ts b/test/mocks/tile-grid-vm.ts index 2b1863cf..82f74712 100644 --- a/test/mocks/tile-grid-vm.ts +++ b/test/mocks/tile-grid-vm.ts @@ -159,6 +159,8 @@ export const section = new FakeEl(); section.id = 'tileGrid'; section.className = 'tile-grid'; main.appendChild(section); +/** The grid's element for one tiled session (its `.tile`), found by its data-session-id. */ +export const tileEl = (id: string) => section.children.find((el) => el.dataset.sessionId === id) as FakeEl; /** Extra elements `document.querySelector` finds, by exact selector (e.g. '.btn-split'). */ export const bySelector = new Map(); diff --git a/test/tile-grid-attach.test.ts b/test/tile-grid-attach.test.ts index 9d5a281b..f4eeb094 100644 --- a/test/tile-grid-attach.test.ts +++ b/test/tile-grid-attach.test.ts @@ -18,18 +18,16 @@ */ import { beforeEach, describe, expect, it, vi } from 'vitest'; import { - FakeEl, FakeTile, fetchSpy, makeGridApp, resetGridHarness, - section, windowStub, type GridApp, + tileEl, } from './mocks/tile-grid-vm.js'; const IDS = ['s-a', 's-b', 's-c']; -const tileEl = (id: string) => section.children.find((el) => el.dataset.sessionId === id) as FakeEl; const overlayOf = (id: string) => tileEl(id).children[1].children.find((c) => c.className === 'tile-attach') ?? null; const visible = (id: string) => !!overlayOf(id) && !overlayOf(id)!.hidden; const textOf = (id: string) => overlayOf(id)!.children[0].textContent; diff --git a/test/tile-grid-auto-join.test.ts b/test/tile-grid-auto-join.test.ts index 9de44700..c63ccaed 100644 --- a/test/tile-grid-auto-join.test.ts +++ b/test/tile-grid-auto-join.test.ts @@ -18,7 +18,7 @@ import { readFileSync } from 'node:fs'; import { resolve } from 'node:path'; import { beforeEach, describe, expect, it, vi } from 'vitest'; -import { FakeEl, FakeTile, makeGridApp, resetGridHarness, section, type GridApp } from './mocks/tile-grid-vm.js'; +import { FakeTile, makeGridApp, resetGridHarness, section, type GridApp, tileEl } from './mocks/tile-grid-vm.js'; const IDS = ['s-a', 's-b']; const addSession = (app: GridApp, id: string, workingDir = '/w') => @@ -52,7 +52,7 @@ describe('Run from this tab', () => { app.openTileGrid(IDS); addSession(app, 's-new'); app._joinTileGridFromRun('s-new'); - const tile = section.children.find((el) => el.dataset.sessionId === 's-new') as FakeEl; + const tile = tileEl('s-new'); const overlay = tile.children[1].children.find((c) => c.className === 'tile-attach'); expect(!overlay || overlay.hidden).toBe(true); }); diff --git a/test/tile-grid-chrome.test.ts b/test/tile-grid-chrome.test.ts index 15abd939..3b5a07da 100644 --- a/test/tile-grid-chrome.test.ts +++ b/test/tile-grid-chrome.test.ts @@ -18,7 +18,7 @@ import { readFileSync } from 'node:fs'; import { resolve } from 'node:path'; import { beforeEach, describe, expect, it, vi } from 'vitest'; -import { FakeEl, FakeTile, makeGridApp, resetGridHarness, section, type GridApp } from './mocks/tile-grid-vm.js'; +import { FakeEl, FakeTile, makeGridApp, resetGridHarness, type GridApp, tileEl } from './mocks/tile-grid-vm.js'; const IDS = ['s-a', 's-b', 's-c']; @@ -38,7 +38,6 @@ function openGrid(): GridApp { return app; } -const tileEl = (id: string) => section.children.find((el) => el.dataset.sessionId === id) as FakeEl; const headerOf = (id: string) => tileEl(id).children[0]; const buttonOf = (id: string, cls: string) => headerOf(id).children[2].children.find((b) => b.className.includes(cls)) as FakeEl; @@ -99,7 +98,7 @@ describe('the header', () => { describe('header buttons', () => { it('are ⋯ ⤢ × and nothing else: no + (owner decision 9)', () => { const app = openGrid(); - const tile = section.children.find((el) => el.dataset.sessionId === 's-a') as FakeEl; + const tile = tileEl('s-a'); const actions = tile.children[0].children.find((c) => c.className === 'tile-actions') as FakeEl; expect(actions.children.map((b) => b.className)).toEqual([ 'tile-btn tile-menu', diff --git a/test/tile-grid-dividers.test.ts b/test/tile-grid-dividers.test.ts index 9f3e7604..1e3e8fbe 100644 --- a/test/tile-grid-dividers.test.ts +++ b/test/tile-grid-dividers.test.ts @@ -22,10 +22,10 @@ import { resetGridHarness, section, type GridApp, + tileEl, } from './mocks/tile-grid-vm.js'; const SIX = ['s-a', 's-b', 's-c', 's-d', 's-e', 's-f']; -const tileEl = (id: string) => section.children.find((el) => el.dataset.sessionId === id) as FakeEl; const divider = (app: GridApp, key: string) => app._tileGrid.dividers.get(key) as FakeEl; const tile = (id: string) => FakeTile.all.find((t) => t.sessionId === id) as FakeTile; diff --git a/test/tile-grid-entry-points.test.ts b/test/tile-grid-entry-points.test.ts index 2c181677..194ade22 100644 --- a/test/tile-grid-entry-points.test.ts +++ b/test/tile-grid-entry-points.test.ts @@ -24,10 +24,10 @@ import { section, windowStub, type GridApp, + tileEl, } from './mocks/tile-grid-vm.js'; const IDS = ['s-a', 's-b', 's-c']; -const tileEl = (id: string) => section.children.find((el) => el.dataset.sessionId === id) as FakeEl; const slots = () => section.children.filter((el) => el.className === 'tile-slot'); const dragEvent = () => ({ preventDefault: vi.fn(), stopPropagation: vi.fn(), dataTransfer: { dropEffect: '' } }); diff --git a/test/tile-grid-open-set.test.ts b/test/tile-grid-open-set.test.ts index de4775dc..b8c5f2d6 100644 --- a/test/tile-grid-open-set.test.ts +++ b/test/tile-grid-open-set.test.ts @@ -11,12 +11,11 @@ * (`toggleTileGrid`); right-click (contextmenu) opens the picker. With the * grid open the picker shows the current tiles, and Open replaces them. * - * Pure helper via `vm`, the app via the shared harness (test/mocks/tile-grid-vm.ts). + * The pure helper and the app both via the shared harness (test/mocks/tile-grid-vm.ts). * Port: N/A. */ import { readFileSync } from 'node:fs'; import { resolve } from 'node:path'; -import vm from 'node:vm'; import { beforeEach, describe, expect, it, vi } from 'vitest'; import { FakeEl, @@ -25,17 +24,14 @@ import { documentAddEventListener, makeGridApp, resetGridHarness, + windowStub, } from './mocks/tile-grid-vm.js'; type OpenSet = { source: string; ids: string[]; focusedId: string | null } | null; type Helpers = { tileGridOpenSet(p: Record): OpenSet; TILE_GRID_MAX: number }; -function loadHelpers(): Helpers { - const context = vm.createContext({ window: {}, globalThis: {} }); - vm.runInContext(readFileSync(resolve(import.meta.dirname, '../src/web/public/constants.js'), 'utf8'), context); - return (context.window as { CodemanTileGrid: Helpers }).CodemanTileGrid; -} -const T = loadHelpers(); +// constants.js as the harness loaded it (window.CodemanTileGrid). +const T = windowStub.CodemanTileGrid as Helpers; const INDEX_HTML = readFileSync(resolve(import.meta.dirname, '../src/web/public/index.html'), 'utf8'); const order = Array.from({ length: 9 }, (_, i) => `t${i + 1}`); diff --git a/test/tile-grid-select-branch.test.ts b/test/tile-grid-select-branch.test.ts index b52b1a91..14c9b115 100644 --- a/test/tile-grid-select-branch.test.ts +++ b/test/tile-grid-select-branch.test.ts @@ -26,8 +26,8 @@ import { localStore, makeGridApp, resetGridHarness, - section, type GridApp, + tileEl, } from './mocks/tile-grid-vm.js'; const IDS = ['s-a', 's-b', 's-c']; @@ -163,7 +163,7 @@ describe('moving focus between tiles', () => { it('pressing a tile is a human selection of its session', async () => { const app = openGrid(); app.selectSession = vi.fn(); - const tileB = section.children.find((el) => el.dataset.sessionId === 's-b'); + const tileB = tileEl('s-b'); tileB?.dispatch('pointerdown'); expect(app.selectSession).toHaveBeenCalledWith('s-b'); }); diff --git a/test/tile-grid-zoom.test.ts b/test/tile-grid-zoom.test.ts index 70f22a36..7dce6516 100644 --- a/test/tile-grid-zoom.test.ts +++ b/test/tile-grid-zoom.test.ts @@ -16,10 +16,17 @@ import { readFileSync } from 'node:fs'; import { resolve } from 'node:path'; import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; -import { FakeEl, FakeTile, makeGridApp, resetGridHarness, section, type GridApp } from './mocks/tile-grid-vm.js'; +import { + FakeEl, + FakeTile, + makeGridApp, + resetGridHarness, + section, + type GridApp, + tileEl, +} from './mocks/tile-grid-vm.js'; const IDS = ['s-a', 's-b', 's-c', 's-d']; -const tileEl = (id: string) => section.children.find((el) => el.dataset.sessionId === id) as FakeEl; const zoomButton = (id: string) => tileEl(id).children[0].children[2].children.find((b) => b.className.includes('tile-zoom')) as FakeEl;