mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-25 12:34:38 -07:00
test(cli): refactor tests for async render utilities (#23252)
This commit is contained in:
committed by
GitHub
parent
86a3a913b5
commit
6c78eb7a39
@@ -22,19 +22,13 @@ const mockChats: ChatDetail[] = [
|
||||
|
||||
describe('<ChatList />', () => {
|
||||
it('renders correctly with a list of chats', async () => {
|
||||
const { lastFrame, unmount, waitUntilReady } = render(
|
||||
<ChatList chats={mockChats} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const { lastFrame, unmount } = await render(<ChatList chats={mockChats} />);
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('renders correctly with no chats', async () => {
|
||||
const { lastFrame, unmount, waitUntilReady } = render(
|
||||
<ChatList chats={[]} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const { lastFrame, unmount } = await render(<ChatList chats={[]} />);
|
||||
expect(lastFrame()).toContain('No saved conversation checkpoints found.');
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
@@ -47,10 +41,9 @@ describe('<ChatList />', () => {
|
||||
mtime: 'an-invalid-date-string',
|
||||
},
|
||||
];
|
||||
const { lastFrame, unmount, waitUntilReady } = render(
|
||||
const { lastFrame, unmount } = await render(
|
||||
<ChatList chats={mockChatsWithInvalidDate} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toContain('(Invalid Date)');
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
|
||||
@@ -127,7 +127,7 @@ describe('ExtensionDetails', () => {
|
||||
});
|
||||
|
||||
it('should call onLink when "l" is pressed and is linkable', async () => {
|
||||
const { stdin, waitUntilReady } = await renderWithProviders(
|
||||
const { stdin } = await renderWithProviders(
|
||||
<ExtensionDetails
|
||||
extension={linkableExtension}
|
||||
onBack={mockOnBack}
|
||||
@@ -136,7 +136,6 @@ describe('ExtensionDetails', () => {
|
||||
isInstalled={false}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
await React.act(async () => {
|
||||
stdin.write('l');
|
||||
});
|
||||
@@ -146,15 +145,14 @@ describe('ExtensionDetails', () => {
|
||||
});
|
||||
|
||||
it('should NOT show "Link" button for GitHub extensions', async () => {
|
||||
const { lastFrame, waitUntilReady } = await renderDetails(false);
|
||||
await waitUntilReady();
|
||||
const { lastFrame } = await renderDetails(true);
|
||||
await waitFor(() => {
|
||||
expect(lastFrame()).not.toContain('[L] Link');
|
||||
});
|
||||
});
|
||||
|
||||
it('should show "Link" button for local extensions', async () => {
|
||||
const { lastFrame, waitUntilReady } = await renderWithProviders(
|
||||
const { lastFrame } = await renderWithProviders(
|
||||
<ExtensionDetails
|
||||
extension={linkableExtension}
|
||||
onBack={mockOnBack}
|
||||
@@ -163,7 +161,6 @@ describe('ExtensionDetails', () => {
|
||||
isInstalled={false}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
await waitFor(() => {
|
||||
expect(lastFrame()).toContain('[L] Link');
|
||||
});
|
||||
|
||||
@@ -139,8 +139,7 @@ describe('ExtensionRegistryView', () => {
|
||||
);
|
||||
|
||||
it('should render extensions', async () => {
|
||||
const { lastFrame, waitUntilReady } = await renderView();
|
||||
await waitUntilReady();
|
||||
const { lastFrame } = await renderView();
|
||||
|
||||
await waitFor(() => {
|
||||
expect(lastFrame()).toContain('Test Extension 1');
|
||||
|
||||
@@ -57,20 +57,18 @@ describe('<ExtensionsList />', () => {
|
||||
|
||||
it('should render "No extensions installed." if there are no extensions', async () => {
|
||||
mockUIState(new Map());
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
const { lastFrame, unmount } = await render(
|
||||
<ExtensionsList extensions={[]} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toContain('No extensions installed.');
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('should render a list of extensions with their version and status', async () => {
|
||||
mockUIState(new Map());
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
const { lastFrame, unmount } = await render(
|
||||
<ExtensionsList extensions={mockExtensions} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const output = lastFrame();
|
||||
expect(output).toContain('ext-one (v1.0.0) - active');
|
||||
expect(output).toContain('ext-two (v2.1.0) - active');
|
||||
@@ -80,10 +78,9 @@ describe('<ExtensionsList />', () => {
|
||||
|
||||
it('should display "unknown state" if an extension has no update state', async () => {
|
||||
mockUIState(new Map());
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
const { lastFrame, unmount } = await render(
|
||||
<ExtensionsList extensions={[mockExtensions[0]]} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toContain('(unknown state)');
|
||||
unmount();
|
||||
});
|
||||
@@ -122,10 +119,9 @@ describe('<ExtensionsList />', () => {
|
||||
async ({ state, expectedText }) => {
|
||||
const updateState = new Map([[mockExtensions[0].name, state]]);
|
||||
mockUIState(updateState);
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
const { lastFrame, unmount } = await render(
|
||||
<ExtensionsList extensions={[mockExtensions[0]]} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toContain(expectedText);
|
||||
unmount();
|
||||
},
|
||||
@@ -160,10 +156,9 @@ describe('<ExtensionsList />', () => {
|
||||
},
|
||||
],
|
||||
};
|
||||
const { lastFrame, waitUntilReady, unmount } = render(
|
||||
const { lastFrame, unmount } = await render(
|
||||
<ExtensionsList extensions={[extensionWithSettings]} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const output = lastFrame();
|
||||
expect(output).toContain('settings:');
|
||||
expect(output).toContain('- sensitiveApiKey: ***');
|
||||
|
||||
@@ -54,40 +54,34 @@ describe('McpStatus', () => {
|
||||
};
|
||||
|
||||
it('renders correctly with a connected server', async () => {
|
||||
const { lastFrame, unmount, waitUntilReady } = render(
|
||||
<McpStatus {...baseProps} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const { lastFrame, unmount } = await render(<McpStatus {...baseProps} />);
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('renders correctly with authenticated OAuth status', async () => {
|
||||
const { lastFrame, unmount, waitUntilReady } = render(
|
||||
const { lastFrame, unmount } = await render(
|
||||
<McpStatus {...baseProps} authStatus={{ 'server-1': 'authenticated' }} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('renders correctly with expired OAuth status', async () => {
|
||||
const { lastFrame, unmount, waitUntilReady } = render(
|
||||
const { lastFrame, unmount } = await render(
|
||||
<McpStatus {...baseProps} authStatus={{ 'server-1': 'expired' }} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('renders correctly with unauthenticated OAuth status', async () => {
|
||||
const { lastFrame, unmount, waitUntilReady } = render(
|
||||
const { lastFrame, unmount } = await render(
|
||||
<McpStatus
|
||||
{...baseProps}
|
||||
authStatus={{ 'server-1': 'unauthenticated' }}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
@@ -97,34 +91,29 @@ describe('McpStatus', () => {
|
||||
await import('@google/gemini-cli-core'),
|
||||
'getMCPServerStatus',
|
||||
).mockReturnValue(MCPServerStatus.DISCONNECTED);
|
||||
const { lastFrame, unmount, waitUntilReady } = render(
|
||||
<McpStatus {...baseProps} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const { lastFrame, unmount } = await render(<McpStatus {...baseProps} />);
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('renders correctly when discovery is in progress', async () => {
|
||||
const { lastFrame, unmount, waitUntilReady } = render(
|
||||
const { lastFrame, unmount } = await render(
|
||||
<McpStatus {...baseProps} discoveryInProgress={true} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('renders correctly with schema enabled', async () => {
|
||||
const { lastFrame, unmount, waitUntilReady } = render(
|
||||
const { lastFrame, unmount } = await render(
|
||||
<McpStatus {...baseProps} showSchema={true} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('renders correctly with parametersJsonSchema', async () => {
|
||||
const { lastFrame, unmount, waitUntilReady } = render(
|
||||
const { lastFrame, unmount } = await render(
|
||||
<McpStatus
|
||||
{...baseProps}
|
||||
tools={[
|
||||
@@ -145,13 +134,12 @@ describe('McpStatus', () => {
|
||||
showSchema={true}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('renders correctly with prompts', async () => {
|
||||
const { lastFrame, unmount, waitUntilReady } = render(
|
||||
const { lastFrame, unmount } = await render(
|
||||
<McpStatus
|
||||
{...baseProps}
|
||||
prompts={[
|
||||
@@ -163,13 +151,12 @@ describe('McpStatus', () => {
|
||||
]}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('renders correctly with resources', async () => {
|
||||
const { lastFrame, unmount, waitUntilReady } = render(
|
||||
const { lastFrame, unmount } = await render(
|
||||
<McpStatus
|
||||
{...baseProps}
|
||||
resources={[
|
||||
@@ -182,25 +169,23 @@ describe('McpStatus', () => {
|
||||
]}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('renders correctly with a blocked server', async () => {
|
||||
const { lastFrame, unmount, waitUntilReady } = render(
|
||||
const { lastFrame, unmount } = await render(
|
||||
<McpStatus
|
||||
{...baseProps}
|
||||
blockedServers={[{ name: 'server-1', extensionName: 'test-extension' }]}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('renders correctly with both blocked and unblocked servers', async () => {
|
||||
const { lastFrame, unmount, waitUntilReady } = render(
|
||||
const { lastFrame, unmount } = await render(
|
||||
<McpStatus
|
||||
{...baseProps}
|
||||
servers={{
|
||||
@@ -213,41 +198,37 @@ describe('McpStatus', () => {
|
||||
blockedServers={[{ name: 'server-2', extensionName: 'test-extension' }]}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('renders only blocked servers when no configured servers exist', async () => {
|
||||
const { lastFrame, unmount, waitUntilReady } = render(
|
||||
const { lastFrame, unmount } = await render(
|
||||
<McpStatus
|
||||
{...baseProps}
|
||||
servers={{}}
|
||||
blockedServers={[{ name: 'server-1', extensionName: 'test-extension' }]}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('renders correctly with a connecting server', async () => {
|
||||
const { lastFrame, unmount, waitUntilReady } = render(
|
||||
const { lastFrame, unmount } = await render(
|
||||
<McpStatus {...baseProps} connectingServers={['server-1']} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('renders correctly with a server error', async () => {
|
||||
const { lastFrame, unmount, waitUntilReady } = render(
|
||||
const { lastFrame, unmount } = await render(
|
||||
<McpStatus
|
||||
{...baseProps}
|
||||
errors={{ 'server-1': 'Failed to connect to server' }}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
@@ -259,10 +240,9 @@ describe('McpStatus', () => {
|
||||
uri: `file:///tmp/resource-${i + 1}.txt`,
|
||||
}));
|
||||
|
||||
const { lastFrame, unmount, waitUntilReady } = render(
|
||||
const { lastFrame, unmount } = await render(
|
||||
<McpStatus {...baseProps} resources={manyResources} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toContain('15 resources hidden');
|
||||
unmount();
|
||||
});
|
||||
|
||||
@@ -35,10 +35,9 @@ describe('SkillsList Component', () => {
|
||||
];
|
||||
|
||||
it('should render enabled and disabled skills separately', async () => {
|
||||
const { lastFrame, unmount, waitUntilReady } = render(
|
||||
const { lastFrame, unmount } = await render(
|
||||
<SkillsList skills={mockSkills} showDescriptions={true} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const output = lastFrame();
|
||||
|
||||
expect(output).toContain('Available Agent Skills:');
|
||||
@@ -55,10 +54,9 @@ describe('SkillsList Component', () => {
|
||||
});
|
||||
|
||||
it('should not render descriptions when showDescriptions is false', async () => {
|
||||
const { lastFrame, unmount, waitUntilReady } = render(
|
||||
const { lastFrame, unmount } = await render(
|
||||
<SkillsList skills={mockSkills} showDescriptions={false} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const output = lastFrame();
|
||||
|
||||
expect(output).toContain('skill1');
|
||||
@@ -72,10 +70,9 @@ describe('SkillsList Component', () => {
|
||||
});
|
||||
|
||||
it('should render "No skills available" when skills list is empty', async () => {
|
||||
const { lastFrame, unmount, waitUntilReady } = render(
|
||||
const { lastFrame, unmount } = await render(
|
||||
<SkillsList skills={[]} showDescriptions={true} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const output = lastFrame();
|
||||
|
||||
expect(output).toContain('No skills available');
|
||||
@@ -85,10 +82,9 @@ describe('SkillsList Component', () => {
|
||||
|
||||
it('should only render Available Agent Skills section when all skills are enabled', async () => {
|
||||
const enabledOnly = mockSkills.filter((s) => !s.disabled);
|
||||
const { lastFrame, unmount, waitUntilReady } = render(
|
||||
const { lastFrame, unmount } = await render(
|
||||
<SkillsList skills={enabledOnly} showDescriptions={true} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const output = lastFrame();
|
||||
|
||||
expect(output).toContain('Available Agent Skills:');
|
||||
@@ -99,10 +95,9 @@ describe('SkillsList Component', () => {
|
||||
|
||||
it('should only render Disabled Skills section when all skills are disabled', async () => {
|
||||
const disabledOnly = mockSkills.filter((s) => s.disabled);
|
||||
const { lastFrame, unmount, waitUntilReady } = render(
|
||||
const { lastFrame, unmount } = await render(
|
||||
<SkillsList skills={disabledOnly} showDescriptions={true} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const output = lastFrame();
|
||||
|
||||
expect(output).not.toContain('Available Agent Skills:');
|
||||
@@ -121,10 +116,9 @@ describe('SkillsList Component', () => {
|
||||
isBuiltin: true,
|
||||
};
|
||||
|
||||
const { lastFrame, unmount, waitUntilReady } = render(
|
||||
const { lastFrame, unmount } = await render(
|
||||
<SkillsList skills={[builtinSkill]} showDescriptions={true} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const output = lastFrame();
|
||||
|
||||
expect(output).toContain('builtin-skill');
|
||||
|
||||
@@ -32,34 +32,31 @@ const mockTools: ToolDefinition[] = [
|
||||
|
||||
describe('<ToolsList />', () => {
|
||||
it('renders correctly with descriptions', async () => {
|
||||
const { lastFrame, waitUntilReady } = await renderWithProviders(
|
||||
const { lastFrame } = await renderWithProviders(
|
||||
<ToolsList
|
||||
tools={mockTools}
|
||||
showDescriptions={true}
|
||||
terminalWidth={40}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('renders correctly without descriptions', async () => {
|
||||
const { lastFrame, waitUntilReady } = await renderWithProviders(
|
||||
const { lastFrame } = await renderWithProviders(
|
||||
<ToolsList
|
||||
tools={mockTools}
|
||||
showDescriptions={false}
|
||||
terminalWidth={40}
|
||||
/>,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('renders correctly with no tools', async () => {
|
||||
const { lastFrame, waitUntilReady } = await renderWithProviders(
|
||||
const { lastFrame } = await renderWithProviders(
|
||||
<ToolsList tools={[]} showDescriptions={true} terminalWidth={40} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user