summaryrefslogtreecommitdiff
path: root/packages/core/src/tools/write-file.test.ts
diff options
context:
space:
mode:
authorConrad Irwin <[email protected]>2025-08-18 16:29:45 -0600
committerGitHub <[email protected]>2025-08-18 22:29:45 +0000
commitfb3ceb0da4e2cd636013c2c36a9c0016c01aa47f (patch)
tree7aa43846dd88bd5acdb8898b0ccd2e685f2d5ece /packages/core/src/tools/write-file.test.ts
parent4394b6ab4fc86637b07fcd26b9a790c627d1e065 (diff)
Read and write files through Zed (#6169)
Co-authored-by: Agus Zubiaga <[email protected]>
Diffstat (limited to 'packages/core/src/tools/write-file.test.ts')
-rw-r--r--packages/core/src/tools/write-file.test.ts71
1 files changed, 31 insertions, 40 deletions
diff --git a/packages/core/src/tools/write-file.test.ts b/packages/core/src/tools/write-file.test.ts
index 2d877115..e5d5ece9 100644
--- a/packages/core/src/tools/write-file.test.ts
+++ b/packages/core/src/tools/write-file.test.ts
@@ -37,6 +37,7 @@ import {
CorrectedEditResult,
} from '../utils/editCorrector.js';
import { createMockWorkspaceContext } from '../test-utils/mockWorkspaceContext.js';
+import { StandardFileSystemService } from '../services/fileSystemService.js';
const rootDir = path.resolve(os.tmpdir(), 'gemini-cli-test-root');
@@ -55,11 +56,13 @@ vi.mocked(ensureCorrectFileContent).mockImplementation(
);
// Mock Config
+const fsService = new StandardFileSystemService();
const mockConfigInternal = {
getTargetDir: () => rootDir,
getApprovalMode: vi.fn(() => ApprovalMode.DEFAULT),
setApprovalMode: vi.fn(),
getGeminiClient: vi.fn(), // Initialize as a plain mock function
+ getFileSystemService: () => fsService,
getIdeClient: vi.fn(),
getIdeMode: vi.fn(() => false),
getWorkspaceContext: () => createMockWorkspaceContext(rootDir),
@@ -316,10 +319,9 @@ describe('WriteFileTool', () => {
fs.writeFileSync(filePath, 'content', { mode: 0o000 });
const readError = new Error('Permission denied');
- const originalReadFileSync = fs.readFileSync;
- vi.spyOn(fs, 'readFileSync').mockImplementationOnce(() => {
- throw readError;
- });
+ vi.spyOn(fsService, 'readTextFile').mockImplementationOnce(() =>
+ Promise.reject(readError),
+ );
const result = await getCorrectedFileContent(
mockConfig,
@@ -328,7 +330,7 @@ describe('WriteFileTool', () => {
abortSignal,
);
- expect(fs.readFileSync).toHaveBeenCalledWith(filePath, 'utf8');
+ expect(fsService.readTextFile).toHaveBeenCalledWith(filePath);
expect(mockEnsureCorrectEdit).not.toHaveBeenCalled();
expect(mockEnsureCorrectFileContent).not.toHaveBeenCalled();
expect(result.correctedContent).toBe(proposedContent);
@@ -339,7 +341,6 @@ describe('WriteFileTool', () => {
code: undefined,
});
- vi.spyOn(fs, 'readFileSync').mockImplementation(originalReadFileSync);
fs.chmodSync(filePath, 0o600);
});
});
@@ -353,16 +354,14 @@ describe('WriteFileTool', () => {
fs.writeFileSync(filePath, 'original', { mode: 0o000 });
const readError = new Error('Simulated read error for confirmation');
- const originalReadFileSync = fs.readFileSync;
- vi.spyOn(fs, 'readFileSync').mockImplementationOnce(() => {
- throw readError;
- });
+ vi.spyOn(fsService, 'readTextFile').mockImplementationOnce(() =>
+ Promise.reject(readError),
+ );
const invocation = tool.build(params);
const confirmation = await invocation.shouldConfirmExecute(abortSignal);
expect(confirmation).toBe(false);
- vi.spyOn(fs, 'readFileSync').mockImplementation(originalReadFileSync);
fs.chmodSync(filePath, 0o600);
});
@@ -453,15 +452,14 @@ describe('WriteFileTool', () => {
const params = { file_path: filePath, content: 'test content' };
fs.writeFileSync(filePath, 'original', { mode: 0o000 });
- const readError = new Error('Simulated read error for execute');
- const originalReadFileSync = fs.readFileSync;
- vi.spyOn(fs, 'readFileSync').mockImplementationOnce(() => {
- throw readError;
+ vi.spyOn(fsService, 'readTextFile').mockImplementationOnce(() => {
+ const readError = new Error('Simulated read error for execute');
+ return Promise.reject(readError);
});
const invocation = tool.build(params);
const result = await invocation.execute(abortSignal);
- expect(result.llmContent).toContain('Error checking existing file:');
+ expect(result.llmContent).toContain('Error checking existing file');
expect(result.returnDisplay).toMatch(
/Error checking existing file: Simulated read error for execute/,
);
@@ -471,7 +469,6 @@ describe('WriteFileTool', () => {
type: ToolErrorType.FILE_WRITE_FAILURE,
});
- vi.spyOn(fs, 'readFileSync').mockImplementation(originalReadFileSync);
fs.chmodSync(filePath, 0o600);
});
@@ -504,7 +501,8 @@ describe('WriteFileTool', () => {
/Successfully created and wrote to new file/,
);
expect(fs.existsSync(filePath)).toBe(true);
- expect(fs.readFileSync(filePath, 'utf8')).toBe(correctedContent);
+ const writtenContent = await fsService.readTextFile(filePath);
+ expect(writtenContent).toBe(correctedContent);
const display = result.returnDisplay as FileDiff;
expect(display.fileName).toBe('execute_new_corrected_file.txt');
expect(display.fileDiff).toMatch(
@@ -563,7 +561,8 @@ describe('WriteFileTool', () => {
abortSignal,
);
expect(result.llmContent).toMatch(/Successfully overwrote file/);
- expect(fs.readFileSync(filePath, 'utf8')).toBe(correctedProposedContent);
+ const writtenContent = await fsService.readTextFile(filePath);
+ expect(writtenContent).toBe(correctedProposedContent);
const display = result.returnDisplay as FileDiff;
expect(display.fileName).toBe('execute_existing_corrected_file.txt');
expect(display.fileDiff).toMatch(
@@ -675,12 +674,11 @@ describe('WriteFileTool', () => {
const filePath = path.join(rootDir, 'permission_denied_file.txt');
const content = 'test content';
- // Mock writeFileSync to throw EACCES error
- const originalWriteFileSync = fs.writeFileSync;
- vi.spyOn(fs, 'writeFileSync').mockImplementationOnce(() => {
+ // Mock FileSystemService writeTextFile to throw EACCES error
+ vi.spyOn(fsService, 'writeTextFile').mockImplementationOnce(() => {
const error = new Error('Permission denied') as NodeJS.ErrnoException;
error.code = 'EACCES';
- throw error;
+ return Promise.reject(error);
});
const params = { file_path: filePath, content };
@@ -694,22 +692,19 @@ describe('WriteFileTool', () => {
expect(result.returnDisplay).toContain(
`Permission denied writing to file: ${filePath} (EACCES)`,
);
-
- vi.spyOn(fs, 'writeFileSync').mockImplementation(originalWriteFileSync);
});
it('should return NO_SPACE_LEFT error when write fails with ENOSPC', async () => {
const filePath = path.join(rootDir, 'no_space_file.txt');
const content = 'test content';
- // Mock writeFileSync to throw ENOSPC error
- const originalWriteFileSync = fs.writeFileSync;
- vi.spyOn(fs, 'writeFileSync').mockImplementationOnce(() => {
+ // Mock FileSystemService writeTextFile to throw ENOSPC error
+ vi.spyOn(fsService, 'writeTextFile').mockImplementationOnce(() => {
const error = new Error(
'No space left on device',
) as NodeJS.ErrnoException;
error.code = 'ENOSPC';
- throw error;
+ return Promise.reject(error);
});
const params = { file_path: filePath, content };
@@ -723,8 +718,6 @@ describe('WriteFileTool', () => {
expect(result.returnDisplay).toContain(
`No space left on device: ${filePath} (ENOSPC)`,
);
-
- vi.spyOn(fs, 'writeFileSync').mockImplementation(originalWriteFileSync);
});
it('should return TARGET_IS_DIRECTORY error when write fails with EISDIR', async () => {
@@ -740,12 +733,11 @@ describe('WriteFileTool', () => {
return originalExistsSync(path as string);
});
- // Mock writeFileSync to throw EISDIR error
- const originalWriteFileSync = fs.writeFileSync;
- vi.spyOn(fs, 'writeFileSync').mockImplementationOnce(() => {
+ // Mock FileSystemService writeTextFile to throw EISDIR error
+ vi.spyOn(fsService, 'writeTextFile').mockImplementationOnce(() => {
const error = new Error('Is a directory') as NodeJS.ErrnoException;
error.code = 'EISDIR';
- throw error;
+ return Promise.reject(error);
});
const params = { file_path: dirPath, content };
@@ -761,7 +753,6 @@ describe('WriteFileTool', () => {
);
vi.spyOn(fs, 'existsSync').mockImplementation(originalExistsSync);
- vi.spyOn(fs, 'writeFileSync').mockImplementation(originalWriteFileSync);
});
it('should return FILE_WRITE_FAILURE for generic write errors', async () => {
@@ -771,10 +762,10 @@ describe('WriteFileTool', () => {
// Ensure fs.existsSync is not mocked for this test
vi.restoreAllMocks();
- // Mock writeFileSync to throw generic error
- vi.spyOn(fs, 'writeFileSync').mockImplementationOnce(() => {
- throw new Error('Generic write error');
- });
+ // Mock FileSystemService writeTextFile to throw generic error
+ vi.spyOn(fsService, 'writeTextFile').mockImplementationOnce(() =>
+ Promise.reject(new Error('Generic write error')),
+ );
const params = { file_path: filePath, content };
const invocation = tool.build(params);