Advertisement

← vibesdk

src/routes/chat/utils/tool-display.test.ts

2.8 KB Download file
import { describe, expect, it } from 'vitest';
import type { ToolEvent } from './message-helpers';
import {
	getGroupStatus,
	getToolGroupSummary,
	getToolSummary,
	shortenPath,
} from './tool-display';

function event(
	partial: Partial<ToolEvent> & Pick<ToolEvent, 'name' | 'status'>,
): ToolEvent {
	return {
		timestamp: 1,
		...partial,
	};
}

describe('getToolSummary', () => {
	it('uses progressive tense while running', () => {
		expect(
			getToolSummary(
				event({
					name: 'read',
					status: 'start',
					args: { path: 'src/App.tsx' },
				}),
			),
		).toBe('Reading src/App.tsx…');
	});

	it('uses past tense on success', () => {
		expect(
			getToolSummary(
				event({
					name: 'read',
					status: 'success',
					args: { path: 'src/App.tsx' },
				}),
			),
		).toBe('Read src/App.tsx');
	});

	it('uses failed phrasing on error', () => {
		expect(
			getToolSummary(
				event({
					name: 'edit',
					status: 'error',
					args: { path: 'src/foo.ts' },
				}),
			),
		).toBe('Failed to edit src/foo.ts');
	});

	it('handles missing args', () => {
		expect(getToolSummary(event({ name: 'read', status: 'start' }))).toBe(
			'Reading…',
		);
	});

	it('summarizes grep and commit', () => {
		expect(
			getToolSummary(
				event({
					name: 'grep',
					status: 'success',
					args: { query: 'useState', include: '*.tsx' },
				}),
			),
		).toBe('Searched "useState" in *.tsx');

		expect(
			getToolSummary(
				event({
					name: 'commit',
					status: 'success',
					args: { message: 'Add login form' },
				}),
			),
		).toBe('Committed "Add login form"');
	});
});

describe('getToolGroupSummary', () => {
	it('collapses multiple reads', () => {
		const events = [
			event({ name: 'read', status: 'success', args: { path: 'a.ts' } }),
			event({ name: 'read', status: 'success', args: { path: 'b.ts' } }),
			event({ name: 'read', status: 'start', args: { path: 'c.ts' } }),
		];
		expect(getToolGroupSummary(events)).toBe('Reading 3 files…');
		expect(getGroupStatus(events)).toBe('start');
	});

	it('shows past tense when all done', () => {
		const events = [
			event({ name: 'edit', status: 'success', args: { path: 'a.ts' } }),
			event({ name: 'edit', status: 'success', args: { path: 'b.ts' } }),
		];
		expect(getToolGroupSummary(events)).toBe('Edited 2 files');
		expect(getGroupStatus(events)).toBe('success');
	});
});

describe('shortenPath', () => {
	it('keeps short paths intact', () => {
		expect(shortenPath('src/App.tsx')).toBe('src/App.tsx');
	});

	it('truncates long paths to last segments', () => {
		const long = 'very/long/nested/directory/structure/src/components/Button.tsx';
		const result = shortenPath(long, 30);
		expect(result.startsWith('…/')).toBe(true);
		expect(result.length).toBeLessThanOrEqual(30);
	});
});