// @vitest-environment jsdom // TerminalBlock: the prompt label's cwd shortening, the running/empty/settled // arms, the prompt line's run-state dot, the exit-status pill, the head/tail height cap and its expand control, // and the copy control writing the raw output on both the accepted and the // refused clipboard paths. writeClipboard's own return contract is pinned here // too, since it is the seam both copy controls in this package share; the // resolution of ANSI runs into styles is pinned in ansi.spec.ts, so only its // DOM consequence (which runs get a span wrapper) is asserted here. import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { act, cleanup, fireEvent, render, screen } from '@testing-library/react' import { DEFAULT_TERMINAL_MAX_LINES, TerminalBlock } from '../src/index.ts' import { writeClipboard } from '../src/clipboard.ts' const ESC = '\u001b' afterEach(cleanup) beforeEach(() => { vi.useRealTimers() }) /** The rendered output rows, one string per visible line (CSS-module class prefix). */ function outputLines(container: HTMLElement): string[] { return [...container.querySelectorAll('[class^="_line_"]')].map(row => row.textContent ?? '') } /** The prompt line's run-state dot: its StateDot state plus the hidden text label beside it. */ function runStateOf(container: HTMLElement): { state: string | null; label: string | undefined } { const dot = container.querySelector('[class*="_runState_"][data-state]') return { state: dot?.getAttribute('data-state') ?? null, label: container.querySelector('[class^="_runStateLabel_"]')?.textContent ?? undefined, } } /** The prompt rows as `