tests — ui

Module: tests-ui Cohesion: 0.80 Members: 0

tests — ui

The tests/ui module contains a comprehensive suite of unit and integration tests for the user interface components and utilities located in src/ui. Its primary purpose is to ensure the correctness, reliability, and accessibility of the application's interactive elements and underlying UI logic.

These tests are crucial for maintaining the quality of the user experience, especially given the terminal-based nature of the UI, which often involves complex state management, keyboard interactions, and rendering logic.

Testing Philosophy

The tests in this module generally follow these principles:

Module Breakdown

Each test file targets a specific UI component or utility, ensuring its functionality meets expectations.

accessibility.test.ts

This file tests the pure logic utilities found in src/ui/utils/accessibility.ts. These functions are critical for ensuring the application meets accessibility standards, particularly concerning color contrast and ARIA attributes.

Key Functions Tested:

Testing Patterns: These tests focus purely on input/output of functions, using toBeCloseTo for floating-point comparisons and checking boolean flags for contrast results.

chat-interface.test.tsx

This file contains UI component tests for ink-based components related to the chat interface. It uses a custom mock for ink-testing-library to extract rendered text content from React elements, allowing for assertion against the visible output.

Key Components Tested:

Testing Patterns:

diff-renderer-logic.test.ts

This file focuses on the parsing logic for displaying code differences, specifically the parseDiffWithLineNumbers function from src/ui/components/DiffRenderer.ts. This function is responsible for transforming raw diff strings into a structured format suitable for rendering.

Key Function Tested:

Testing Patterns: Tests provide various diff string inputs and assert the structure and content of the returned array, ensuring accurate interpretation of diff syntax.

keyboard-shortcuts.test.ts

This file tests the ShortcutManager class, which handles the definition, management, and persistence of keyboard shortcuts within the application. It's crucial for customizable and accessible keyboard navigation.

Key Class Tested:

Testing Patterns:

metrics-dashboard.test.ts

This file tests the MetricsDashboard class, responsible for collecting, aggregating, and presenting usage metrics (sessions, messages, tokens, tool calls, costs). This data is vital for understanding application usage and performance.

Key Class Tested:

Testing Patterns:

status-line.test.ts

This file tests the StatusLineManager class, which controls the dynamic status line displayed in the UI. This component provides real-time information like the current model, Git branch, token usage, and custom messages.

Key Class Tested:

Testing Patterns:

tabbed-question.test.ts

This file tests the core logic for the TabbedQuestion component, which likely presents a list of options where users can navigate using keyboard input. The tests focus on the selection cycling and option handling.

Key Logic Tested:

Testing Patterns: These are simple, pure logic tests directly manipulating indices and array lengths to simulate user interaction and verify the underlying navigation logic.

themes.test.ts

This file tests the ThemeManager class, which manages the application's visual themes, including built-in options and user-defined custom themes. It's essential for providing a customizable and visually consistent experience.

Key Class Tested:

Testing Patterns:

tool-stream-output.test.ts

This file tests the logic for the ToolStreamOutput component, which is responsible for displaying potentially long streams of output from tools. The key aspect tested here is the line limiting behavior.

Key Logic Tested:

Testing Patterns: These are pure logic tests that simulate tool output strings and assert the slice and Math.max operations used to manage the displayed lines.

Common Testing Patterns

Mocking ink-testing-library and ink

For chat-interface.test.tsx, a custom mock for ink-testing-library is implemented. This mock provides a simplified render function that recursively traverses the React element tree and extracts plain text. This allows tests to assert against the visible content of ink components without needing a full ink runtime environment, making tests faster and more focused on the component's output. Similarly, ink's Text and Box components are mocked to simply render their children.

graph TD
    A[chat-interface.test.tsx] --> B{vi.mock('ink-testing-library')}
    B --> C[render(component)]
    C --> D[extractText(element)]
    D -- Recursively calls --> D
    D -- Returns string --> C
    C -- Provides lastFrame(), rerender() --> A
    A --> E{vi.mock('ink')}
    E --> F[Text / Box components]
    F -- Simply render children --> A

Using tmpDir for Persistence Tests

Several modules (keyboard-shortcuts, metrics-dashboard, themes) manage persistent configuration or data. To test their persistence logic without affecting the actual user's configuration files, tests create and clean up temporary directories using os.tmpdir() and fs-extra. This ensures tests are isolated and repeatable.

class="hl-cmt">// Example from keyboard-shortcuts.test.ts
let tmpDir: string;

beforeEach(async () => {
  tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'shortcut-test-'));
});

afterEach(async () => {
  await fs.remove(tmpDir);
});

function createManager(): ShortcutManager {
  return new ShortcutManager(path.join(tmpDir, 'shortcuts.json'));
}

Mocking child_process

In status-line.test.ts, the child_process module's execSync function is mocked using jest.mock. This allows tests to control the output of external commands that the StatusLineManager might execute (e.g., to get Git branch information), ensuring deterministic test results and preventing actual system calls during testing.

Contributing to UI Tests

When contributing to the UI, consider the following: