// @vitest-environment jsdom /** * test/preview-grid.test.ts โ€” shared launcher/manage preview helpers. * * xterm Terminal is stubbed; fetch is mocked. Covers the DRY core extracted in * Phase 4: formatting, the card factory, fit scaling, and the preview/list * fetch helpers (best-effort, no throw on failure). */ import { describe, it, expect, vi, beforeEach } from 'vitest' import type { LiveSessionInfo } from '../src/types.js' class FakeTerminal { cols = 80 rows = 24 open = vi.fn() reset = vi.fn() resize = vi.fn() dispose = vi.fn() write = vi.fn((_d: string, cb?: () => void) => cb?.()) } vi.mock('@xterm/xterm', () => ({ Terminal: FakeTerminal })) const mod = await import('../public/preview-grid.js') const { el, relTime, statusText, sessionName, makePreviewCard, updatePreviewCard, fitThumb, fetchPreview, renderPreview, loadPreviewInto, fetchLiveSessions, } = mod function session(over: Partial = {}): LiveSessionInfo { return { id: 'aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee', createdAt: Date.now() - 5000, clientCount: 0, status: 'idle', exited: false, cwd: '/work/proj', cols: 80, rows: 24, ...over, } } beforeEach(() => { vi.restoreAllMocks() vi.stubGlobal('requestAnimationFrame', (cb: FrameRequestCallback) => { cb(0) return 0 }) }) describe('formatting helpers', () => { it('el builds an element with class + text', () => { const n = el('div', 'x', 'hi') expect(n.className).toBe('x') expect(n.textContent).toBe('hi') }) it('relTime renders s/m/h/d buckets', () => { const now = Date.now() expect(relTime(now)).toMatch(/^\d+s$/) expect(relTime(now - 120_000)).toBe('2m') expect(relTime(now - 2 * 3600_000)).toBe('2h') expect(relTime(now - 3 * 86400_000)).toBe('3d') }) it('statusText maps each status', () => { expect(statusText('working')).toContain('working') expect(statusText('waiting')).toContain('waiting') expect(statusText('idle')).toContain('idle') expect(statusText('unknown')).toBe('ยท') }) it('sessionName uses last cwd segment, else short id', () => { expect(sessionName(session({ cwd: '/a/b/cool' }))).toBe('cool') expect(sessionName(session({ cwd: null }))).toBe('aaaaaaaa') }) }) describe('makePreviewCard / updatePreviewCard', () => { it('builds a card and fires onOpen when the thumb is clicked (button variant)', () => { const onOpen = vi.fn() const card = makePreviewCard(session(), { onOpen }) card.thumb.click() expect(onOpen).toHaveBeenCalledWith(session().id) // The Open control is a