/** * @license * Copyright 2026 Google LLC * SPDX-License-Identifier: Apache-2.0 */ import { describe, it, expect } from 'vitest'; import { render } from '../../../test-utils/render.js'; import { ExpandableText, MAX_WIDTH } from './ExpandableText.js'; describe('ExpandableText', () => { const color = 'white'; const flat = (s: string | undefined) => (s ?? '').replace(/\n/g, ''); it('renders plain label when no match (short label)', async () => { const renderResult = render( , ); const { waitUntilReady, unmount } = renderResult; await waitUntilReady(); await expect(renderResult).toMatchSvgSnapshot(); unmount(); }); it('truncates long label when collapsed and no match', async () => { const long = 'x'.repeat(MAX_WIDTH + 25); const renderResult = render( , ); const { lastFrame, waitUntilReady, unmount } = renderResult; await waitUntilReady(); const out = lastFrame(); const f = flat(out); expect(f.endsWith('...')).toBe(true); expect(f.length).toBe(MAX_WIDTH + 3); await expect(renderResult).toMatchSvgSnapshot(); unmount(); }); it('shows full long label when expanded and no match', async () => { const long = 'y'.repeat(MAX_WIDTH + 25); const renderResult = render( , ); const { lastFrame, waitUntilReady, unmount } = renderResult; await waitUntilReady(); const out = lastFrame(); const f = flat(out); expect(f.length).toBe(long.length); await expect(renderResult).toMatchSvgSnapshot(); unmount(); }); it('highlights matched substring when expanded (text only visible)', async () => { const label = 'run: git commit -m "feat: add search"'; const userInput = 'commit'; const matchedIndex = label.indexOf(userInput); const renderResult = render( , 100, ); const { waitUntilReady, unmount } = renderResult; await waitUntilReady(); await expect(renderResult).toMatchSvgSnapshot(); unmount(); }); it('creates centered window around match when collapsed', async () => { const prefix = 'cd_/very/long/path/that/keeps/going/'.repeat(3); const core = 'search-here'; const suffix = '/and/then/some/more/components/'.repeat(3); const label = prefix + core + suffix; const matchedIndex = prefix.length; const renderResult = render( , 100, ); const { lastFrame, waitUntilReady, unmount } = renderResult; await waitUntilReady(); const out = lastFrame(); const f = flat(out); expect(f.includes(core)).toBe(true); expect(f.startsWith('...')).toBe(true); expect(f.endsWith('...')).toBe(true); await expect(renderResult).toMatchSvgSnapshot(); unmount(); }); it('truncates match itself when match is very long', async () => { const prefix = 'find '; const core = 'x'.repeat(MAX_WIDTH + 25); const suffix = ' in this text'; const label = prefix + core + suffix; const matchedIndex = prefix.length; const renderResult = render( , ); const { lastFrame, waitUntilReady, unmount } = renderResult; await waitUntilReady(); const out = lastFrame(); const f = flat(out); expect(f.includes('...')).toBe(true); expect(f.startsWith('...')).toBe(false); expect(f.endsWith('...')).toBe(true); expect(f.length).toBe(MAX_WIDTH + 2); await expect(renderResult).toMatchSvgSnapshot(); unmount(); }); it('respects custom maxWidth', async () => { const customWidth = 50; const long = 'z'.repeat(100); const renderResult = render( , ); const { lastFrame, waitUntilReady, unmount } = renderResult; await waitUntilReady(); const out = lastFrame(); const f = flat(out); expect(f.endsWith('...')).toBe(true); expect(f.length).toBe(customWidth + 3); await expect(renderResult).toMatchSvgSnapshot(); unmount(); }); });