Skip to content

Commit ce2a1ad

Browse files
committed
test(files): add unit tests for createFile function
1 parent e2eb4d8 commit ce2a1ad

File tree

1 file changed

+141
-0
lines changed

1 file changed

+141
-0
lines changed

tests/files.test.js

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
import { describe, it, expect, vi, beforeEach } from 'vitest';
2+
import { createFile } from '../src/commands/files.js';
3+
import chalk from 'chalk';
4+
import * as PuterModule from '../src/modules/PuterModule.js';
5+
import * as auth from '../src/commands/auth.js';
6+
import * as commons from '../src/commons.js';
7+
import path from 'path';
8+
9+
// Mock console to prevent actual logging
10+
vi.spyOn(console, 'log').mockImplementation(() => { });
11+
vi.spyOn(console, 'error').mockImplementation(() => { });
12+
13+
// Mock dependencies
14+
vi.mock('chalk', () => ({
15+
default: {
16+
green: vi.fn(text => text),
17+
red: vi.fn(text => text),
18+
dim: vi.fn(text => text),
19+
yellow: vi.fn(text => text),
20+
cyan: vi.fn(text => text),
21+
}
22+
}));
23+
vi.mock('node-fetch');
24+
vi.mock('conf', () => {
25+
const Conf = vi.fn(() => ({
26+
get: vi.fn(),
27+
set: vi.fn(),
28+
clear: vi.fn(),
29+
}));
30+
return { default: Conf };
31+
});
32+
vi.mock('../src/modules/PuterModule.js');
33+
vi.mock('../src/commands/auth.js');
34+
vi.mock('../src/commons.js');
35+
36+
37+
const mockPuter = {
38+
fs: {
39+
stat: vi.fn(),
40+
space: vi.fn(),
41+
mkdir: vi.fn(),
42+
upload: vi.fn(),
43+
},
44+
};
45+
46+
describe('files.js', () => {
47+
beforeEach(() => {
48+
vi.clearAllMocks();
49+
vi.spyOn(PuterModule, 'getPuter').mockReturnValue(mockPuter);
50+
vi.spyOn(auth, 'getCurrentUserName').mockReturnValue('testuser');
51+
vi.spyOn(auth, 'getCurrentDirectory').mockReturnValue('/testuser/files');
52+
vi.spyOn(commons, 'resolvePath').mockImplementation((current, newPath) => path.join(current, newPath));
53+
});
54+
55+
describe('createFile', () => {
56+
it('should create a file successfully', async () => {
57+
mockPuter.fs.stat.mockRejectedValue({ code: 'subject_does_not_exist' });
58+
mockPuter.fs.space.mockResolvedValue({ used: 500, capacity: 1000 });
59+
mockPuter.fs.upload.mockResolvedValue({
60+
name: 'test.txt',
61+
path: '/testuser/files/test.txt',
62+
uid: 'file-uid',
63+
});
64+
65+
const result = await createFile(['test.txt', 'hello world']);
66+
67+
expect(result).toBe(true);
68+
expect(mockPuter.fs.upload).toHaveBeenCalled();
69+
expect(console.log).toHaveBeenCalledWith(expect.stringContaining('File "test.txt" created successfully!'));
70+
});
71+
72+
it('should show usage and return false if no arguments are provided', async () => {
73+
const result = await createFile([]);
74+
expect(result).toBe(false);
75+
expect(console.log).toHaveBeenCalledWith(chalk.red('Usage: touch <file_name> [content]'));
76+
});
77+
78+
it('should overwrite an existing file', async () => {
79+
mockPuter.fs.stat.mockResolvedValue({ id: 'existing-file-id' });
80+
mockPuter.fs.space.mockResolvedValue({ used: 500, capacity: 1000 });
81+
mockPuter.fs.upload.mockResolvedValue({
82+
name: 'test.txt',
83+
path: '/testuser/files/test.txt',
84+
uid: 'file-uid',
85+
});
86+
87+
const result = await createFile(['test.txt', 'new content']);
88+
89+
expect(result).toBe(true);
90+
expect(console.log).toHaveBeenCalledWith(chalk.yellow('File "test.txt" already exists. It will be overwritten.'));
91+
expect(mockPuter.fs.upload).toHaveBeenCalled();
92+
});
93+
94+
it('should return false if there is not enough disk space', async () => {
95+
mockPuter.fs.stat.mockRejectedValue({ code: 'subject_does_not_exist' });
96+
mockPuter.fs.space.mockResolvedValue({ used: 1000, capacity: 1000 });
97+
vi.spyOn(commons, 'showDiskSpaceUsage').mockImplementation(() => {});
98+
99+
const result = await createFile(['test.txt']);
100+
101+
expect(result).toBe(false);
102+
expect(console.error).toHaveBeenCalledWith(chalk.red('Not enough disk space to create the file.'));
103+
expect(commons.showDiskSpaceUsage).toHaveBeenCalled();
104+
});
105+
106+
it('should create missing directories', async () => {
107+
// First stat for file fails, second for directory also fails
108+
mockPuter.fs.stat
109+
.mockRejectedValueOnce({ code: 'subject_does_not_exist' }) // file check
110+
.mockRejectedValueOnce({ code: 'subject_does_not_exist' }); // dir check
111+
mockPuter.fs.space.mockResolvedValue({ used: 500, capacity: 1000 });
112+
mockPuter.fs.mkdir.mockResolvedValue({});
113+
mockPuter.fs.upload.mockResolvedValue({
114+
name: 'test.txt',
115+
path: '/testuser/files/newdir/test.txt',
116+
uid: 'file-uid',
117+
});
118+
119+
const result = await createFile(['newdir/test.txt', 'content']);
120+
121+
expect(result).toBe(true);
122+
expect(mockPuter.fs.mkdir).toHaveBeenCalledWith('/testuser/files/newdir', {
123+
overwrite: false,
124+
dedupeName: true,
125+
createMissingParents: true
126+
});
127+
expect(mockPuter.fs.upload).toHaveBeenCalled();
128+
});
129+
130+
it('should handle API errors during file creation', async () => {
131+
mockPuter.fs.stat.mockRejectedValue({ code: 'subject_does_not_exist' });
132+
mockPuter.fs.space.mockResolvedValue({ used: 500, capacity: 1000 });
133+
mockPuter.fs.upload.mockRejectedValue(new Error('API Error'));
134+
135+
const result = await createFile(['test.txt']);
136+
137+
expect(result).toBe(false);
138+
expect(console.error).toHaveBeenCalledWith(chalk.red('Failed to create file.\nError: API Error'));
139+
});
140+
});
141+
});

0 commit comments

Comments
 (0)