feat(ui): add flicker detection and metrics (#10821)

This commit is contained in:
Shreya Keshive
2025-10-10 13:18:38 -07:00
committed by GitHub
parent ab3804d823
commit ae48e964f0
13 changed files with 297 additions and 39 deletions
+24 -35
View File
@@ -10,6 +10,11 @@ import { Text, useIsScreenReaderEnabled } from 'ink';
import { App } from './App.js';
import { UIStateContext, type UIState } from './contexts/UIStateContext.js';
import { StreamingState } from './types.js';
import {
ConfigContext,
type Config,
type Telemetry,
} from './contexts/ConfigContext.js';
vi.mock('ink', async (importOriginal) => {
const original = await importOriginal<typeof import('ink')>();
@@ -49,6 +54,7 @@ describe('App', () => {
quittingMessages: null,
dialogsVisible: false,
mainControlsRef: { current: null },
rootUiRef: { current: null },
historyManager: {
addItem: vi.fn(),
history: [],
@@ -58,13 +64,20 @@ describe('App', () => {
},
};
it('should render main content and composer when not quitting', () => {
const { lastFrame } = render(
<UIStateContext.Provider value={mockUIState as UIState}>
<App />
</UIStateContext.Provider>,
const mockConfig = {
telemetry: {} as Telemetry,
} as Config;
const renderWithProviders = (ui: React.ReactElement, state: UIState) =>
render(
<ConfigContext.Provider value={mockConfig}>
<UIStateContext.Provider value={state}>{ui}</UIStateContext.Provider>
</ConfigContext.Provider>,
);
it('should render main content and composer when not quitting', () => {
const { lastFrame } = renderWithProviders(<App />, mockUIState as UIState);
expect(lastFrame()).toContain('MainContent');
expect(lastFrame()).toContain('Notifications');
expect(lastFrame()).toContain('Composer');
@@ -76,11 +89,7 @@ describe('App', () => {
quittingMessages: [{ id: 1, type: 'user', text: 'test' }],
} as UIState;
const { lastFrame } = render(
<UIStateContext.Provider value={quittingUIState}>
<App />
</UIStateContext.Provider>,
);
const { lastFrame } = renderWithProviders(<App />, quittingUIState);
expect(lastFrame()).toContain('Quitting...');
});
@@ -91,11 +100,7 @@ describe('App', () => {
dialogsVisible: true,
} as UIState;
const { lastFrame } = render(
<UIStateContext.Provider value={dialogUIState}>
<App />
</UIStateContext.Provider>,
);
const { lastFrame } = renderWithProviders(<App />, dialogUIState);
expect(lastFrame()).toContain('MainContent');
expect(lastFrame()).toContain('Notifications');
@@ -109,11 +114,7 @@ describe('App', () => {
ctrlCPressedOnce: true,
} as UIState;
const { lastFrame } = render(
<UIStateContext.Provider value={ctrlCUIState}>
<App />
</UIStateContext.Provider>,
);
const { lastFrame } = renderWithProviders(<App />, ctrlCUIState);
expect(lastFrame()).toContain('Press Ctrl+C again to exit.');
});
@@ -125,11 +126,7 @@ describe('App', () => {
ctrlDPressedOnce: true,
} as UIState;
const { lastFrame } = render(
<UIStateContext.Provider value={ctrlDUIState}>
<App />
</UIStateContext.Provider>,
);
const { lastFrame } = renderWithProviders(<App />, ctrlDUIState);
expect(lastFrame()).toContain('Press Ctrl+D again to exit.');
});
@@ -137,11 +134,7 @@ describe('App', () => {
it('should render ScreenReaderAppLayout when screen reader is enabled', () => {
(useIsScreenReaderEnabled as vi.Mock).mockReturnValue(true);
const { lastFrame } = render(
<UIStateContext.Provider value={mockUIState as UIState}>
<App />
</UIStateContext.Provider>,
);
const { lastFrame } = renderWithProviders(<App />, mockUIState as UIState);
expect(lastFrame()).toContain(
'Notifications\nFooter\nMainContent\nComposer',
@@ -151,11 +144,7 @@ describe('App', () => {
it('should render DefaultAppLayout when screen reader is not enabled', () => {
(useIsScreenReaderEnabled as vi.Mock).mockReturnValue(false);
const { lastFrame } = render(
<UIStateContext.Provider value={mockUIState as UIState}>
<App />
</UIStateContext.Provider>,
);
const { lastFrame } = renderWithProviders(<App />, mockUIState as UIState);
expect(lastFrame()).toContain('MainContent\nNotifications\nComposer');
});