Skip to content

Commit 578ca28

Browse files
committed
add unit test for all fs operations
1 parent 0357cfd commit 578ca28

File tree

1 file changed

+373
-0
lines changed

1 file changed

+373
-0
lines changed

tests/pint-fs-client.test.ts

Lines changed: 373 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,373 @@
1+
import { describe, it, expect, vi, beforeEach } from 'vitest';
2+
import { PintFsClient } from '../src/PintClient/fs';
3+
import { Client } from '../src/api-clients/pint/client';
4+
import * as pintApi from '../src/api-clients/pint';
5+
6+
// Mock the API functions
7+
vi.mock('../src/api-clients/pint', () => ({
8+
createFile: vi.fn(),
9+
readFile: vi.fn(),
10+
performFileAction: vi.fn(),
11+
listDirectory: vi.fn(),
12+
createDirectory: vi.fn(),
13+
deleteDirectory: vi.fn(),
14+
getFileStat: vi.fn(),
15+
}));
16+
17+
// Helper to create proper mock response
18+
const createMockResponse = (data: any, error?: any) => ({
19+
data,
20+
error,
21+
request: {} as any,
22+
response: {} as any,
23+
});
24+
25+
describe('PintFsClient', () => {
26+
let client: PintFsClient;
27+
let mockApiClient: Client;
28+
29+
beforeEach(() => {
30+
vi.clearAllMocks();
31+
mockApiClient = {} as Client;
32+
client = new PintFsClient(mockApiClient);
33+
});
34+
35+
describe('readFile', () => {
36+
it('should successfully read a file and convert to Uint8Array', async () => {
37+
const mockResponse = createMockResponse({ content: 'Hello World' });
38+
vi.mocked(pintApi.readFile).mockResolvedValue(mockResponse);
39+
40+
const result = await client.readFile('/test/file.txt');
41+
42+
expect(result).toEqual({
43+
type: 'ok',
44+
result: {
45+
content: new TextEncoder().encode('Hello World'),
46+
},
47+
});
48+
expect(pintApi.readFile).toHaveBeenCalledWith({
49+
client: mockApiClient,
50+
path: { path: '/test/file.txt' },
51+
});
52+
});
53+
54+
it('should handle API error response', async () => {
55+
const mockResponse = createMockResponse(undefined, { message: 'File not found' });
56+
vi.mocked(pintApi.readFile).mockResolvedValue(mockResponse);
57+
58+
const result = await client.readFile('/test/missing.txt');
59+
60+
expect(result).toEqual({
61+
type: 'error',
62+
error: 'File not found',
63+
errno: null,
64+
});
65+
});
66+
67+
it('should handle thrown exceptions', async () => {
68+
vi.mocked(pintApi.readFile).mockRejectedValue(new Error('Network error'));
69+
70+
const result = await client.readFile('/test/file.txt');
71+
72+
expect(result).toEqual({
73+
type: 'error',
74+
error: 'Network error',
75+
errno: null,
76+
});
77+
});
78+
79+
it('should handle unknown error types', async () => {
80+
vi.mocked(pintApi.readFile).mockRejectedValue('String error');
81+
82+
const result = await client.readFile('/test/file.txt');
83+
84+
expect(result).toEqual({
85+
type: 'error',
86+
error: 'Unknown error',
87+
errno: null,
88+
});
89+
});
90+
});
91+
92+
describe('readdir', () => {
93+
it('should successfully read directory entries', async () => {
94+
const mockResponse = createMockResponse({
95+
files: [
96+
{ name: 'file1.txt', isDir: false },
97+
{ name: 'subdir', isDir: true },
98+
],
99+
});
100+
vi.mocked(pintApi.listDirectory).mockResolvedValue(mockResponse);
101+
102+
const result = await client.readdir('/test');
103+
104+
expect(result).toEqual({
105+
type: 'ok',
106+
result: {
107+
entries: [
108+
{ name: 'file1.txt', type: 0, isSymlink: false },
109+
{ name: 'subdir', type: 1, isSymlink: false },
110+
],
111+
},
112+
});
113+
expect(pintApi.listDirectory).toHaveBeenCalledWith({
114+
client: mockApiClient,
115+
path: { path: '/test' },
116+
});
117+
});
118+
119+
it('should handle API error response', async () => {
120+
const mockResponse = createMockResponse(undefined, { message: 'Permission denied' });
121+
vi.mocked(pintApi.listDirectory).mockResolvedValue(mockResponse);
122+
123+
const result = await client.readdir('/protected');
124+
125+
expect(result).toEqual({
126+
type: 'error',
127+
error: 'Permission denied',
128+
errno: null,
129+
});
130+
});
131+
});
132+
133+
describe('writeFile', () => {
134+
it('should successfully write file content', async () => {
135+
const mockResponse = createMockResponse({});
136+
vi.mocked(pintApi.createFile).mockResolvedValue(mockResponse);
137+
138+
const content = new TextEncoder().encode('Hello World');
139+
const result = await client.writeFile('/test/new.txt', content);
140+
141+
expect(result).toEqual({
142+
type: 'ok',
143+
result: {},
144+
});
145+
expect(pintApi.createFile).toHaveBeenCalledWith({
146+
client: mockApiClient,
147+
path: { path: '/test/new.txt' },
148+
body: { content: 'Hello World' },
149+
});
150+
});
151+
152+
it('should handle API error response', async () => {
153+
const mockResponse = createMockResponse(undefined, { message: 'Disk full' });
154+
vi.mocked(pintApi.createFile).mockResolvedValue(mockResponse);
155+
156+
const content = new TextEncoder().encode('data');
157+
const result = await client.writeFile('/test/file.txt', content);
158+
159+
expect(result).toEqual({
160+
type: 'error',
161+
error: 'Disk full',
162+
errno: null,
163+
});
164+
});
165+
});
166+
167+
describe('remove', () => {
168+
it('should successfully remove directory/file', async () => {
169+
const mockResponse = createMockResponse({});
170+
vi.mocked(pintApi.deleteDirectory).mockResolvedValue(mockResponse);
171+
172+
const result = await client.remove('/test/path');
173+
174+
expect(result).toEqual({
175+
type: 'ok',
176+
result: {},
177+
});
178+
expect(pintApi.deleteDirectory).toHaveBeenCalledWith({
179+
client: mockApiClient,
180+
path: { path: '/test/path' },
181+
});
182+
});
183+
184+
it('should handle API error response', async () => {
185+
const mockResponse = createMockResponse(undefined, { message: 'Path not found' });
186+
vi.mocked(pintApi.deleteDirectory).mockResolvedValue(mockResponse);
187+
188+
const result = await client.remove('/test/missing');
189+
190+
expect(result).toEqual({
191+
type: 'error',
192+
error: 'Path not found',
193+
errno: null,
194+
});
195+
});
196+
});
197+
198+
describe('mkdir', () => {
199+
it('should successfully create directory', async () => {
200+
const mockResponse = createMockResponse({});
201+
vi.mocked(pintApi.createDirectory).mockResolvedValue(mockResponse);
202+
203+
const result = await client.mkdir('/test/newdir');
204+
205+
expect(result).toEqual({
206+
type: 'ok',
207+
result: {},
208+
});
209+
expect(pintApi.createDirectory).toHaveBeenCalledWith({
210+
client: mockApiClient,
211+
path: { path: '/test/newdir' },
212+
});
213+
});
214+
215+
it('should handle API error response', async () => {
216+
const mockResponse = createMockResponse(undefined, { message: 'Directory exists' });
217+
vi.mocked(pintApi.createDirectory).mockResolvedValue(mockResponse);
218+
219+
const result = await client.mkdir('/test/existing');
220+
221+
expect(result).toEqual({
222+
type: 'error',
223+
error: 'Directory exists',
224+
errno: null,
225+
});
226+
});
227+
});
228+
229+
describe('stat', () => {
230+
it('should successfully get file stats', async () => {
231+
const mockResponse = createMockResponse({
232+
isDir: false,
233+
size: 1024,
234+
modTime: '2023-01-01T12:00:00Z',
235+
});
236+
vi.mocked(pintApi.getFileStat).mockResolvedValue(mockResponse);
237+
238+
const result = await client.stat('/test/file.txt');
239+
240+
const expectedTime = new Date('2023-01-01T12:00:00Z').getTime();
241+
expect(result).toEqual({
242+
type: 'ok',
243+
result: {
244+
type: 0, // file
245+
isSymlink: false,
246+
size: 1024,
247+
mtime: expectedTime,
248+
ctime: expectedTime,
249+
atime: expectedTime,
250+
},
251+
});
252+
expect(pintApi.getFileStat).toHaveBeenCalledWith({
253+
client: mockApiClient,
254+
path: { path: '/test/file.txt' },
255+
});
256+
});
257+
258+
it('should handle directory stats', async () => {
259+
const mockResponse = createMockResponse({
260+
isDir: true,
261+
size: 0,
262+
modTime: '2023-01-01T12:00:00Z',
263+
});
264+
vi.mocked(pintApi.getFileStat).mockResolvedValue(mockResponse);
265+
266+
const result = await client.stat('/test/dir');
267+
268+
expect(result.type).toBe('ok');
269+
if (result.type === 'ok') {
270+
expect(result.result.type).toBe(1); // directory
271+
}
272+
});
273+
274+
it('should handle API error response', async () => {
275+
const mockResponse = createMockResponse(undefined, { message: 'File not found' });
276+
vi.mocked(pintApi.getFileStat).mockResolvedValue(mockResponse);
277+
278+
const result = await client.stat('/test/missing.txt');
279+
280+
expect(result).toEqual({
281+
type: 'error',
282+
error: 'File not found',
283+
errno: null,
284+
});
285+
});
286+
});
287+
288+
describe('copy', () => {
289+
it('should successfully copy file', async () => {
290+
const mockResponse = createMockResponse({});
291+
vi.mocked(pintApi.performFileAction).mockResolvedValue(mockResponse);
292+
293+
const result = await client.copy('/src/file.txt', '/dest/file.txt');
294+
295+
expect(result).toEqual({
296+
type: 'ok',
297+
result: {},
298+
});
299+
expect(pintApi.performFileAction).toHaveBeenCalledWith({
300+
client: mockApiClient,
301+
path: { path: '/src/file.txt' },
302+
body: {
303+
action: 'copy',
304+
destination: '/dest/file.txt',
305+
},
306+
});
307+
});
308+
309+
it('should handle API error response', async () => {
310+
const mockResponse = createMockResponse(undefined, { message: 'Source not found' });
311+
vi.mocked(pintApi.performFileAction).mockResolvedValue(mockResponse);
312+
313+
const result = await client.copy('/src/missing.txt', '/dest/file.txt');
314+
315+
expect(result).toEqual({
316+
type: 'error',
317+
error: 'Source not found',
318+
errno: null,
319+
});
320+
});
321+
});
322+
323+
describe('rename', () => {
324+
it('should successfully rename/move file', async () => {
325+
const mockResponse = createMockResponse({});
326+
vi.mocked(pintApi.performFileAction).mockResolvedValue(mockResponse);
327+
328+
const result = await client.rename('/old/path.txt', '/new/path.txt');
329+
330+
expect(result).toEqual({
331+
type: 'ok',
332+
result: {},
333+
});
334+
expect(pintApi.performFileAction).toHaveBeenCalledWith({
335+
client: mockApiClient,
336+
path: { path: '/old/path.txt' },
337+
body: {
338+
action: 'move',
339+
destination: '/new/path.txt',
340+
},
341+
});
342+
});
343+
344+
it('should handle API error response', async () => {
345+
const mockResponse = createMockResponse(undefined, { message: 'Destination exists' });
346+
vi.mocked(pintApi.performFileAction).mockResolvedValue(mockResponse);
347+
348+
const result = await client.rename('/old/path.txt', '/new/path.txt');
349+
350+
expect(result).toEqual({
351+
type: 'error',
352+
error: 'Destination exists',
353+
errno: null,
354+
});
355+
});
356+
});
357+
358+
describe('watch', () => {
359+
it('should throw not implemented error', async () => {
360+
await expect(
361+
client.watch('/test', {}, () => {})
362+
).rejects.toThrow('Not implemented');
363+
});
364+
});
365+
366+
describe('download', () => {
367+
it('should throw not implemented error', async () => {
368+
await expect(
369+
client.download('/test')
370+
).rejects.toThrow('Not implemented');
371+
});
372+
});
373+
});

0 commit comments

Comments
 (0)