mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-06 19:31:15 -07:00
Co-authored-by: Krishna Korade <MushuEE@users.noreply.github.com> Co-authored-by: Jacob Richman <jacob314@gmail.com>
206 lines
6.3 KiB
TypeScript
206 lines
6.3 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright 2025 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
import type { Config } from '../config/config.js';
|
|
import {
|
|
addMemory,
|
|
listMemoryFiles,
|
|
refreshMemory,
|
|
showMemory,
|
|
} from './memory.js';
|
|
import * as memoryDiscovery from '../utils/memoryDiscovery.js';
|
|
|
|
vi.mock('../utils/memoryDiscovery.js', () => ({
|
|
refreshServerHierarchicalMemory: vi.fn(),
|
|
}));
|
|
|
|
const mockRefresh = vi.mocked(memoryDiscovery.refreshServerHierarchicalMemory);
|
|
|
|
describe('memory commands', () => {
|
|
let mockConfig: Config;
|
|
|
|
beforeEach(() => {
|
|
mockConfig = {
|
|
getUserMemory: vi.fn(),
|
|
getGeminiMdFileCount: vi.fn(),
|
|
getGeminiMdFilePaths: vi.fn(),
|
|
isJitContextEnabled: vi.fn(),
|
|
updateSystemInstructionIfInitialized: vi
|
|
.fn()
|
|
.mockResolvedValue(undefined),
|
|
} as unknown as Config;
|
|
});
|
|
|
|
afterEach(() => {
|
|
vi.restoreAllMocks();
|
|
});
|
|
|
|
describe('showMemory', () => {
|
|
it('should show memory content if it exists', () => {
|
|
vi.mocked(mockConfig.getUserMemory).mockReturnValue(
|
|
'some memory content',
|
|
);
|
|
vi.mocked(mockConfig.getGeminiMdFileCount).mockReturnValue(1);
|
|
|
|
const result = showMemory(mockConfig);
|
|
|
|
expect(result.type).toBe('message');
|
|
if (result.type === 'message') {
|
|
expect(result.messageType).toBe('info');
|
|
expect(result.content).toContain(
|
|
'Current memory content from 1 file(s)',
|
|
);
|
|
expect(result.content).toContain('some memory content');
|
|
}
|
|
});
|
|
|
|
it('should show a message if memory is empty', () => {
|
|
vi.mocked(mockConfig.getUserMemory).mockReturnValue('');
|
|
vi.mocked(mockConfig.getGeminiMdFileCount).mockReturnValue(0);
|
|
|
|
const result = showMemory(mockConfig);
|
|
|
|
expect(result.type).toBe('message');
|
|
if (result.type === 'message') {
|
|
expect(result.messageType).toBe('info');
|
|
expect(result.content).toBe('Memory is currently empty.');
|
|
}
|
|
});
|
|
});
|
|
|
|
describe('addMemory', () => {
|
|
it('should return a tool action to save memory', () => {
|
|
const result = addMemory('new memory');
|
|
expect(result.type).toBe('tool');
|
|
if (result.type === 'tool') {
|
|
expect(result.toolName).toBe('save_memory');
|
|
expect(result.toolArgs).toEqual({ fact: 'new memory' });
|
|
}
|
|
});
|
|
|
|
it('should trim the arguments', () => {
|
|
const result = addMemory(' new memory ');
|
|
expect(result.type).toBe('tool');
|
|
if (result.type === 'tool') {
|
|
expect(result.toolArgs).toEqual({ fact: 'new memory' });
|
|
}
|
|
});
|
|
|
|
it('should return an error if args are empty', () => {
|
|
const result = addMemory('');
|
|
expect(result.type).toBe('message');
|
|
if (result.type === 'message') {
|
|
expect(result.messageType).toBe('error');
|
|
expect(result.content).toBe('Usage: /memory add <text to remember>');
|
|
}
|
|
});
|
|
|
|
it('should return an error if args are just whitespace', () => {
|
|
const result = addMemory(' ');
|
|
expect(result.type).toBe('message');
|
|
if (result.type === 'message') {
|
|
expect(result.messageType).toBe('error');
|
|
expect(result.content).toBe('Usage: /memory add <text to remember>');
|
|
}
|
|
});
|
|
|
|
it('should return an error if args are undefined', () => {
|
|
const result = addMemory(undefined);
|
|
expect(result.type).toBe('message');
|
|
if (result.type === 'message') {
|
|
expect(result.messageType).toBe('error');
|
|
expect(result.content).toBe('Usage: /memory add <text to remember>');
|
|
}
|
|
});
|
|
});
|
|
|
|
describe('refreshMemory', () => {
|
|
it('should refresh memory and show success message', async () => {
|
|
mockRefresh.mockResolvedValue({
|
|
memoryContent: { project: 'refreshed content' },
|
|
fileCount: 2,
|
|
filePaths: [],
|
|
});
|
|
|
|
const result = await refreshMemory(mockConfig);
|
|
|
|
expect(mockRefresh).toHaveBeenCalledWith(mockConfig);
|
|
expect(
|
|
mockConfig.updateSystemInstructionIfInitialized,
|
|
).toHaveBeenCalled();
|
|
expect(result.type).toBe('message');
|
|
if (result.type === 'message') {
|
|
expect(result.messageType).toBe('info');
|
|
expect(result.content).toBe(
|
|
'Memory reloaded successfully. Loaded 33 characters from 2 file(s)',
|
|
);
|
|
}
|
|
});
|
|
|
|
it('should show a message if no memory content is found after refresh', async () => {
|
|
mockRefresh.mockResolvedValue({
|
|
memoryContent: { project: '' },
|
|
fileCount: 0,
|
|
filePaths: [],
|
|
});
|
|
|
|
const result = await refreshMemory(mockConfig);
|
|
expect(result.type).toBe('message');
|
|
if (result.type === 'message') {
|
|
expect(result.messageType).toBe('info');
|
|
expect(result.content).toBe(
|
|
'Memory reloaded successfully. No memory content found',
|
|
);
|
|
}
|
|
});
|
|
});
|
|
|
|
describe('listMemoryFiles', () => {
|
|
it('should list the memory files in use', () => {
|
|
const filePaths = ['/path/to/GEMINI.md', '/other/path/GEMINI.md'];
|
|
vi.mocked(mockConfig.getGeminiMdFilePaths).mockReturnValue(filePaths);
|
|
|
|
const result = listMemoryFiles(mockConfig);
|
|
|
|
expect(result.type).toBe('message');
|
|
if (result.type === 'message') {
|
|
expect(result.messageType).toBe('info');
|
|
expect(result.content).toContain(
|
|
'There are 2 GEMINI.md file(s) in use:',
|
|
);
|
|
expect(result.content).toContain(filePaths.join('\n'));
|
|
}
|
|
});
|
|
|
|
it('should show a message if no memory files are in use', () => {
|
|
vi.mocked(mockConfig.getGeminiMdFilePaths).mockReturnValue([]);
|
|
|
|
const result = listMemoryFiles(mockConfig);
|
|
|
|
expect(result.type).toBe('message');
|
|
if (result.type === 'message') {
|
|
expect(result.messageType).toBe('info');
|
|
expect(result.content).toBe('No GEMINI.md files in use.');
|
|
}
|
|
});
|
|
|
|
it('should show a message if file paths are undefined', () => {
|
|
vi.mocked(mockConfig.getGeminiMdFilePaths).mockReturnValue(
|
|
undefined as unknown as string[],
|
|
);
|
|
|
|
const result = listMemoryFiles(mockConfig);
|
|
|
|
expect(result.type).toBe('message');
|
|
if (result.type === 'message') {
|
|
expect(result.messageType).toBe('info');
|
|
expect(result.content).toBe('No GEMINI.md files in use.');
|
|
}
|
|
});
|
|
});
|
|
});
|