/** * @license * Copyright 2025 Google LLC * SPDX-License-Identifier: Apache-2.0 */ import { GeminiClient } from '@google/gemini-cli-core'; import { vi, describe, it, expect, beforeEach } from 'vitest'; import { compressCommand } from './compressCommand.js'; import { createMockCommandContext } from '../../test-utils/mockCommandContext.js'; import { MessageType } from '../types.js'; describe('compressCommand', () => { let context: ReturnType; let mockTryCompressChat: ReturnType; beforeEach(() => { mockTryCompressChat = vi.fn(); context = createMockCommandContext({ services: { config: { getGeminiClient: () => ({ tryCompressChat: mockTryCompressChat, }) as unknown as GeminiClient, }, }, }); }); it('should do nothing if a compression is already pending', async () => { context.ui.pendingItem = { type: MessageType.COMPRESSION, compression: { isPending: true, originalTokenCount: null, newTokenCount: null, }, }; await compressCommand.action!(context, ''); expect(context.ui.addItem).toHaveBeenCalledWith( expect.objectContaining({ type: MessageType.ERROR, text: 'Already compressing, wait for previous request to complete', }), expect.any(Number), ); expect(context.ui.setPendingItem).not.toHaveBeenCalled(); expect(mockTryCompressChat).not.toHaveBeenCalled(); }); it('should set pending item, call tryCompressChat, and add result on success', async () => { const compressedResult = { originalTokenCount: 200, newTokenCount: 100, }; mockTryCompressChat.mockResolvedValue(compressedResult); await compressCommand.action!(context, ''); expect(context.ui.setPendingItem).toHaveBeenNthCalledWith( 1, expect.objectContaining({ type: MessageType.COMPRESSION, compression: { isPending: true, originalTokenCount: null, newTokenCount: null, }, }), ); expect(mockTryCompressChat).toHaveBeenCalledWith( expect.stringMatching(/^compress-\d+$/), true, ); expect(context.ui.addItem).toHaveBeenCalledWith( expect.objectContaining({ type: MessageType.COMPRESSION, compression: { isPending: false, originalTokenCount: 200, newTokenCount: 100, }, }), expect.any(Number), ); expect(context.ui.setPendingItem).toHaveBeenNthCalledWith(2, null); }); it('should add an error message if tryCompressChat returns falsy', async () => { mockTryCompressChat.mockResolvedValue(null); await compressCommand.action!(context, ''); expect(context.ui.addItem).toHaveBeenCalledWith( expect.objectContaining({ type: MessageType.ERROR, text: 'Failed to compress chat history.', }), expect.any(Number), ); expect(context.ui.setPendingItem).toHaveBeenCalledWith(null); }); it('should add an error message if tryCompressChat throws', async () => { const error = new Error('Compression failed'); mockTryCompressChat.mockRejectedValue(error); await compressCommand.action!(context, ''); expect(context.ui.addItem).toHaveBeenCalledWith( expect.objectContaining({ type: MessageType.ERROR, text: `Failed to compress chat history: ${error.message}`, }), expect.any(Number), ); expect(context.ui.setPendingItem).toHaveBeenCalledWith(null); }); it('should clear the pending item in a finally block', async () => { mockTryCompressChat.mockRejectedValue(new Error('some error')); await compressCommand.action!(context, ''); expect(context.ui.setPendingItem).toHaveBeenCalledWith(null); }); });