2025-05-31 12:49:28 -07:00
|
|
|
/**
|
|
|
|
|
* @license
|
|
|
|
|
* Copyright 2025 Google LLC
|
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
*/
|
|
|
|
|
|
2025-09-06 01:39:02 -04:00
|
|
|
import { describe, it, expect, vi } from 'vitest';
|
|
|
|
|
import { render } from 'ink-testing-library';
|
|
|
|
|
import { Text } from 'ink';
|
|
|
|
|
import { App } from './App.js';
|
|
|
|
|
import { UIStateContext, type UIState } from './contexts/UIStateContext.js';
|
2025-08-26 00:04:53 +02:00
|
|
|
import { StreamingState } from './types.js';
|
2025-05-31 12:49:28 -07:00
|
|
|
|
2025-09-06 01:39:02 -04:00
|
|
|
// Mock components to isolate App component testing
|
|
|
|
|
vi.mock('./components/MainContent.js', () => ({
|
|
|
|
|
MainContent: () => <Text>MainContent</Text>,
|
2025-08-08 11:02:27 -07:00
|
|
|
}));
|
|
|
|
|
|
2025-09-06 01:39:02 -04:00
|
|
|
vi.mock('./components/DialogManager.js', () => ({
|
|
|
|
|
DialogManager: () => <Text>DialogManager</Text>,
|
2025-09-03 11:44:26 -07:00
|
|
|
}));
|
|
|
|
|
|
2025-09-06 01:39:02 -04:00
|
|
|
vi.mock('./components/Composer.js', () => ({
|
|
|
|
|
Composer: () => <Text>Composer</Text>,
|
2025-05-31 12:49:28 -07:00
|
|
|
}));
|
|
|
|
|
|
2025-09-06 01:39:02 -04:00
|
|
|
vi.mock('./components/Notifications.js', () => ({
|
|
|
|
|
Notifications: () => <Text>Notifications</Text>,
|
2025-08-30 03:18:22 +09:00
|
|
|
}));
|
|
|
|
|
|
2025-09-06 01:39:02 -04:00
|
|
|
vi.mock('./components/QuittingDisplay.js', () => ({
|
|
|
|
|
QuittingDisplay: () => <Text>Quitting...</Text>,
|
2025-07-25 17:35:26 -07:00
|
|
|
}));
|
|
|
|
|
|
2025-09-23 11:04:49 -07:00
|
|
|
vi.mock('./components/Footer.js', () => ({
|
|
|
|
|
Footer: () => <Text>Footer</Text>,
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
vi.mock('./semantic-colors.js', () => ({
|
|
|
|
|
theme: {
|
|
|
|
|
status: {
|
|
|
|
|
warning: 'yellow',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
// Don't mock the layout components - let them render normally so tests can see the Ctrl messages
|
|
|
|
|
|
|
|
|
|
vi.mock('./hooks/useLayoutConfig.js', () => ({
|
|
|
|
|
useLayoutConfig: () => ({
|
|
|
|
|
mode: 'default',
|
|
|
|
|
shouldUseStatic: true,
|
|
|
|
|
shouldShowFooterInComposer: true,
|
|
|
|
|
}),
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
vi.mock('./hooks/useFooterProps.js', () => ({
|
|
|
|
|
useFooterProps: () => ({
|
|
|
|
|
model: 'test-model',
|
|
|
|
|
targetDir: '/test',
|
|
|
|
|
debugMode: false,
|
|
|
|
|
branchName: 'test-branch',
|
|
|
|
|
debugMessage: '',
|
|
|
|
|
corgiMode: false,
|
|
|
|
|
errorCount: 0,
|
|
|
|
|
showErrorDetails: false,
|
|
|
|
|
showMemoryUsage: false,
|
|
|
|
|
promptTokenCount: 0,
|
|
|
|
|
nightly: false,
|
|
|
|
|
isTrustedFolder: true,
|
|
|
|
|
vimMode: undefined,
|
|
|
|
|
}),
|
|
|
|
|
}));
|
|
|
|
|
|
2025-09-06 01:39:02 -04:00
|
|
|
describe('App', () => {
|
|
|
|
|
const mockUIState: Partial<UIState> = {
|
|
|
|
|
streamingState: StreamingState.Idle,
|
|
|
|
|
quittingMessages: null,
|
|
|
|
|
dialogsVisible: false,
|
|
|
|
|
mainControlsRef: { current: null },
|
2025-09-22 11:45:02 -07:00
|
|
|
historyManager: {
|
|
|
|
|
addItem: vi.fn(),
|
|
|
|
|
history: [],
|
|
|
|
|
updateItem: vi.fn(),
|
|
|
|
|
clearItems: vi.fn(),
|
|
|
|
|
loadHistory: vi.fn(),
|
|
|
|
|
},
|
2025-05-31 12:49:28 -07:00
|
|
|
};
|
2025-06-30 01:56:37 +02:00
|
|
|
|
2025-09-06 01:39:02 -04:00
|
|
|
it('should render main content and composer when not quitting', () => {
|
|
|
|
|
const { lastFrame } = render(
|
|
|
|
|
<UIStateContext.Provider value={mockUIState as UIState}>
|
|
|
|
|
<App />
|
|
|
|
|
</UIStateContext.Provider>,
|
2025-07-09 21:16:42 +00:00
|
|
|
);
|
2025-05-31 12:49:28 -07:00
|
|
|
|
2025-09-06 01:39:02 -04:00
|
|
|
expect(lastFrame()).toContain('MainContent');
|
|
|
|
|
expect(lastFrame()).toContain('Composer');
|
2025-07-28 17:56:52 -07:00
|
|
|
});
|
|
|
|
|
|
2025-09-06 01:39:02 -04:00
|
|
|
it('should render quitting display when quittingMessages is set', () => {
|
|
|
|
|
const quittingUIState = {
|
|
|
|
|
...mockUIState,
|
|
|
|
|
quittingMessages: [{ id: 1, type: 'user', text: 'test' }],
|
|
|
|
|
} as UIState;
|
2025-07-18 18:14:46 -04:00
|
|
|
|
2025-09-06 01:39:02 -04:00
|
|
|
const { lastFrame } = render(
|
|
|
|
|
<UIStateContext.Provider value={quittingUIState}>
|
|
|
|
|
<App />
|
|
|
|
|
</UIStateContext.Provider>,
|
2025-07-18 18:14:46 -04:00
|
|
|
);
|
|
|
|
|
|
2025-09-06 01:39:02 -04:00
|
|
|
expect(lastFrame()).toContain('Quitting...');
|
2025-08-19 17:06:01 -04:00
|
|
|
});
|
|
|
|
|
|
2025-09-06 01:39:02 -04:00
|
|
|
it('should render dialog manager when dialogs are visible', () => {
|
|
|
|
|
const dialogUIState = {
|
|
|
|
|
...mockUIState,
|
|
|
|
|
dialogsVisible: true,
|
|
|
|
|
} as UIState;
|
2025-08-19 17:06:01 -04:00
|
|
|
|
2025-09-06 01:39:02 -04:00
|
|
|
const { lastFrame } = render(
|
|
|
|
|
<UIStateContext.Provider value={dialogUIState}>
|
|
|
|
|
<App />
|
|
|
|
|
</UIStateContext.Provider>,
|
2025-08-19 17:06:01 -04:00
|
|
|
);
|
2025-08-26 12:01:31 -06:00
|
|
|
|
2025-09-06 01:39:02 -04:00
|
|
|
expect(lastFrame()).toContain('MainContent');
|
|
|
|
|
expect(lastFrame()).toContain('DialogManager');
|
2025-08-26 12:01:31 -06:00
|
|
|
});
|
2025-09-19 14:52:29 +08:00
|
|
|
|
|
|
|
|
it('should show Ctrl+C exit prompt when dialogs are visible and ctrlCPressedOnce is true', () => {
|
|
|
|
|
const ctrlCUIState = {
|
|
|
|
|
...mockUIState,
|
|
|
|
|
dialogsVisible: true,
|
|
|
|
|
ctrlCPressedOnce: true,
|
|
|
|
|
} as UIState;
|
|
|
|
|
|
|
|
|
|
const { lastFrame } = render(
|
|
|
|
|
<UIStateContext.Provider value={ctrlCUIState}>
|
|
|
|
|
<App />
|
|
|
|
|
</UIStateContext.Provider>,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
expect(lastFrame()).toContain('Press Ctrl+C again to exit.');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should show Ctrl+D exit prompt when dialogs are visible and ctrlDPressedOnce is true', () => {
|
|
|
|
|
const ctrlDUIState = {
|
|
|
|
|
...mockUIState,
|
|
|
|
|
dialogsVisible: true,
|
|
|
|
|
ctrlDPressedOnce: true,
|
|
|
|
|
} as UIState;
|
|
|
|
|
|
|
|
|
|
const { lastFrame } = render(
|
|
|
|
|
<UIStateContext.Provider value={ctrlDUIState}>
|
|
|
|
|
<App />
|
|
|
|
|
</UIStateContext.Provider>,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
expect(lastFrame()).toContain('Press Ctrl+D again to exit.');
|
|
|
|
|
});
|
2025-05-31 12:49:28 -07:00
|
|
|
});
|