summaryrefslogtreecommitdiff
path: root/packages/cli/src/ui/commands/directoryCommand.test.tsx
diff options
context:
space:
mode:
authorYuki Okita <[email protected]>2025-08-01 04:02:08 +0900
committerGitHub <[email protected]>2025-07-31 19:02:08 +0000
commitf9a05401c1d2d93d1251d3ebf2c079ee1f4ba8df (patch)
tree870f1cf4b31ed974ca180bb7068388ba2dfc3788 /packages/cli/src/ui/commands/directoryCommand.test.tsx
parent9a6422f331294ea2f56d67599ed142d09cc33320 (diff)
feat: Multi-Directory Workspace Support (part2: add "directory" command) (#5241)
Diffstat (limited to 'packages/cli/src/ui/commands/directoryCommand.test.tsx')
-rw-r--r--packages/cli/src/ui/commands/directoryCommand.test.tsx172
1 files changed, 172 insertions, 0 deletions
diff --git a/packages/cli/src/ui/commands/directoryCommand.test.tsx b/packages/cli/src/ui/commands/directoryCommand.test.tsx
new file mode 100644
index 00000000..081083d3
--- /dev/null
+++ b/packages/cli/src/ui/commands/directoryCommand.test.tsx
@@ -0,0 +1,172 @@
+/**
+ * @license
+ * Copyright 2025 Google LLC
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import { describe, it, expect, vi, beforeEach } from 'vitest';
+import { directoryCommand, expandHomeDir } from './directoryCommand.js';
+import { Config, WorkspaceContext } from '@google/gemini-cli-core';
+import { CommandContext } from './types.js';
+import { MessageType } from '../types.js';
+import * as os from 'os';
+import * as path from 'path';
+
+describe('directoryCommand', () => {
+ let mockContext: CommandContext;
+ let mockConfig: Config;
+ let mockWorkspaceContext: WorkspaceContext;
+ const addCommand = directoryCommand.subCommands?.find(
+ (c) => c.name === 'add',
+ );
+ const showCommand = directoryCommand.subCommands?.find(
+ (c) => c.name === 'show',
+ );
+
+ beforeEach(() => {
+ mockWorkspaceContext = {
+ addDirectory: vi.fn(),
+ getDirectories: vi
+ .fn()
+ .mockReturnValue([
+ path.normalize('/home/user/project1'),
+ path.normalize('/home/user/project2'),
+ ]),
+ } as unknown as WorkspaceContext;
+
+ mockConfig = {
+ getWorkspaceContext: () => mockWorkspaceContext,
+ isRestrictiveSandbox: vi.fn().mockReturnValue(false),
+ getGeminiClient: vi.fn().mockReturnValue({
+ addDirectoryContext: vi.fn(),
+ }),
+ } as unknown as Config;
+
+ mockContext = {
+ services: {
+ config: mockConfig,
+ },
+ ui: {
+ addItem: vi.fn(),
+ },
+ } as unknown as CommandContext;
+ });
+
+ describe('show', () => {
+ it('should display the list of directories', () => {
+ if (!showCommand?.action) throw new Error('No action');
+ showCommand.action(mockContext, '');
+ expect(mockWorkspaceContext.getDirectories).toHaveBeenCalled();
+ expect(mockContext.ui.addItem).toHaveBeenCalledWith(
+ expect.objectContaining({
+ type: MessageType.INFO,
+ text: `Current workspace directories:\n- ${path.normalize(
+ '/home/user/project1',
+ )}\n- ${path.normalize('/home/user/project2')}`,
+ }),
+ expect.any(Number),
+ );
+ });
+ });
+
+ describe('add', () => {
+ it('should show an error if no path is provided', () => {
+ if (!addCommand?.action) throw new Error('No action');
+ addCommand.action(mockContext, '');
+ expect(mockContext.ui.addItem).toHaveBeenCalledWith(
+ expect.objectContaining({
+ type: MessageType.ERROR,
+ text: 'Please provide at least one path to add.',
+ }),
+ expect.any(Number),
+ );
+ });
+
+ it('should call addDirectory and show a success message for a single path', async () => {
+ const newPath = path.normalize('/home/user/new-project');
+ if (!addCommand?.action) throw new Error('No action');
+ await addCommand.action(mockContext, newPath);
+ expect(mockWorkspaceContext.addDirectory).toHaveBeenCalledWith(newPath);
+ expect(mockContext.ui.addItem).toHaveBeenCalledWith(
+ expect.objectContaining({
+ type: MessageType.INFO,
+ text: `Successfully added directories:\n- ${newPath}`,
+ }),
+ expect.any(Number),
+ );
+ });
+
+ it('should call addDirectory for each path and show a success message for multiple paths', async () => {
+ const newPath1 = path.normalize('/home/user/new-project1');
+ const newPath2 = path.normalize('/home/user/new-project2');
+ if (!addCommand?.action) throw new Error('No action');
+ await addCommand.action(mockContext, `${newPath1},${newPath2}`);
+ expect(mockWorkspaceContext.addDirectory).toHaveBeenCalledWith(newPath1);
+ expect(mockWorkspaceContext.addDirectory).toHaveBeenCalledWith(newPath2);
+ expect(mockContext.ui.addItem).toHaveBeenCalledWith(
+ expect.objectContaining({
+ type: MessageType.INFO,
+ text: `Successfully added directories:\n- ${newPath1}\n- ${newPath2}`,
+ }),
+ expect.any(Number),
+ );
+ });
+
+ it('should show an error if addDirectory throws an exception', async () => {
+ const error = new Error('Directory does not exist');
+ vi.mocked(mockWorkspaceContext.addDirectory).mockImplementation(() => {
+ throw error;
+ });
+ const newPath = path.normalize('/home/user/invalid-project');
+ if (!addCommand?.action) throw new Error('No action');
+ await addCommand.action(mockContext, newPath);
+ expect(mockContext.ui.addItem).toHaveBeenCalledWith(
+ expect.objectContaining({
+ type: MessageType.ERROR,
+ text: `Error adding '${newPath}': ${error.message}`,
+ }),
+ expect.any(Number),
+ );
+ });
+
+ it('should handle a mix of successful and failed additions', async () => {
+ const validPath = path.normalize('/home/user/valid-project');
+ const invalidPath = path.normalize('/home/user/invalid-project');
+ const error = new Error('Directory does not exist');
+ vi.mocked(mockWorkspaceContext.addDirectory).mockImplementation(
+ (p: string) => {
+ if (p === invalidPath) {
+ throw error;
+ }
+ },
+ );
+
+ if (!addCommand?.action) throw new Error('No action');
+ await addCommand.action(mockContext, `${validPath},${invalidPath}`);
+
+ expect(mockContext.ui.addItem).toHaveBeenCalledWith(
+ expect.objectContaining({
+ type: MessageType.INFO,
+ text: `Successfully added directories:\n- ${validPath}`,
+ }),
+ expect.any(Number),
+ );
+
+ expect(mockContext.ui.addItem).toHaveBeenCalledWith(
+ expect.objectContaining({
+ type: MessageType.ERROR,
+ text: `Error adding '${invalidPath}': ${error.message}`,
+ }),
+ expect.any(Number),
+ );
+ });
+ });
+ it('should correctly expand a Windows-style home directory path', () => {
+ const windowsPath = '%userprofile%\\Documents';
+ const expectedPath = path.win32.join(os.homedir(), 'Documents');
+ const result = expandHomeDir(windowsPath);
+ expect(path.win32.normalize(result)).toBe(
+ path.win32.normalize(expectedPath),
+ );
+ });
+});