Skip to content

Commit 191e9a4

Browse files
committed
test: add comprehensive tests for safeDelete function
1 parent b2dcff4 commit 191e9a4

1 file changed

Lines changed: 92 additions & 0 deletions

File tree

tests/utils/trash.test.ts

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2+
import { safeDelete } from '../../src/utils/trash.js';
3+
import { rmSync } from 'fs';
4+
import { platform } from 'os';
5+
import trash from 'trash';
6+
7+
// Mock the dependencies
8+
vi.mock('fs', () => ({
9+
rmSync: vi.fn(),
10+
}));
11+
12+
vi.mock('trash', () => ({
13+
default: vi.fn(),
14+
}));
15+
16+
// Use cross-platform test paths
17+
const getTestPaths = () => {
18+
if (platform() === 'win32') {
19+
return ['C:\\temp\\test1', 'C:\\temp\\test2'];
20+
}
21+
return ['/tmp/test1', '/tmp/test2'];
22+
};
23+
24+
describe('safeDelete', () => {
25+
beforeEach(() => {
26+
vi.clearAllMocks();
27+
});
28+
29+
it('should move files to trash when permanent is false', async () => {
30+
const testPaths = getTestPaths();
31+
(trash as any).mockResolvedValue(undefined);
32+
33+
const result = await safeDelete(testPaths, false);
34+
35+
expect(result).toBe(true);
36+
expect(trash).toHaveBeenCalledWith(testPaths);
37+
expect(rmSync).not.toHaveBeenCalled();
38+
});
39+
40+
it('should permanently delete files when permanent is true', async () => {
41+
const testPaths = getTestPaths().slice(0, 1); // Use single path
42+
(rmSync as any).mockImplementation(() => {});
43+
44+
const result = await safeDelete(testPaths, true);
45+
46+
expect(result).toBe(true);
47+
expect(rmSync).toHaveBeenCalledTimes(testPaths.length);
48+
testPaths.forEach(path => {
49+
expect(rmSync).toHaveBeenCalledWith(path, { recursive: true, force: true });
50+
});
51+
expect(trash).not.toHaveBeenCalled();
52+
});
53+
54+
it('should return false and log error when trash fails', async () => {
55+
const testPaths = getTestPaths().slice(0, 1);
56+
const errorMessage = 'Trash failed';
57+
(trash as any).mockRejectedValue(new Error(errorMessage));
58+
59+
const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
60+
const result = await safeDelete(testPaths, false);
61+
62+
expect(result).toBe(false);
63+
expect(consoleErrorSpy).toHaveBeenCalledWith(
64+
`Failed to delete ${testPaths.join(', ')}: ${errorMessage}`
65+
);
66+
consoleErrorSpy.mockRestore();
67+
});
68+
69+
it('should return false and log error when permanent deletion fails', async () => {
70+
const testPaths = getTestPaths().slice(0, 1);
71+
const errorMessage = 'Permission denied';
72+
(rmSync as any).mockImplementation(() => { throw new Error(errorMessage); });
73+
74+
const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
75+
const result = await safeDelete(testPaths, true);
76+
77+
expect(result).toBe(false);
78+
expect(consoleErrorSpy).toHaveBeenCalledWith(
79+
`Failed to delete ${testPaths.join(', ')}: ${errorMessage}`
80+
);
81+
consoleErrorSpy.mockRestore();
82+
});
83+
84+
it('should handle empty paths array', async () => {
85+
// Mock trash to succeed even with empty array
86+
(trash as any).mockResolvedValue(undefined);
87+
88+
const result = await safeDelete([], false);
89+
expect(result).toBe(true);
90+
expect(trash).toHaveBeenCalledWith([]);
91+
});
92+
});

0 commit comments

Comments
 (0)