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' ;
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" ;
88
99// Mock console to prevent actual logging
10- vi . spyOn ( console , ' log' ) . mockImplementation ( ( ) => { } ) ;
11- vi . spyOn ( console , ' error' ) . mockImplementation ( ( ) => { } ) ;
10+ vi . spyOn ( console , " log" ) . mockImplementation ( ( ) => { } ) ;
11+ vi . spyOn ( console , " error" ) . mockImplementation ( ( ) => { } ) ;
1212
1313// Mock dependencies
14- vi . mock ( ' chalk' , ( ) => ( {
14+ vi . mock ( " chalk" , ( ) => ( {
1515 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- }
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+ } ,
2222} ) ) ;
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 } ;
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 } ;
3131} ) ;
32- vi . mock ( '../src/modules/PuterModule.js' ) ;
33- vi . mock ( '../src/commands/auth.js' ) ;
34- vi . mock ( '../src/commons.js' ) ;
35-
32+ vi . mock ( "../src/modules/PuterModule.js" ) ;
33+ vi . mock ( "../src/commands/auth.js" ) ;
34+ vi . mock ( "../src/commons.js" ) ;
3635
3736const mockPuter = {
38- fs : {
39- stat : vi . fn ( ) ,
40- space : vi . fn ( ) ,
41- mkdir : vi . fn ( ) ,
42- upload : vi . fn ( ) ,
43- } ,
37+ fs : {
38+ stat : vi . fn ( ) ,
39+ space : vi . fn ( ) ,
40+ mkdir : vi . fn ( ) ,
41+ upload : vi . fn ( ) ,
42+ } ,
4443} ;
4544
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 ) ) ;
45+ describe ( "createFile" , ( ) => {
46+
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 ) =>
53+ path . join ( current , newPath )
54+ ) ;
55+ } ) ;
56+
57+ it ( "should create a file successfully" , async ( ) => {
58+ mockPuter . fs . stat . mockRejectedValue ( { code : "subject_does_not_exist" } ) ;
59+ mockPuter . fs . space . mockResolvedValue ( { used : 500 , capacity : 1000 } ) ;
60+ mockPuter . fs . upload . mockResolvedValue ( {
61+ name : "test.txt" ,
62+ path : "/testuser/files/test.txt" ,
63+ uid : "file-uid" ,
64+ } ) ;
65+
66+ const result = await createFile ( [ "test.txt" , "hello world" ] ) ;
67+
68+ expect ( result ) . toBe ( true ) ;
69+ expect ( mockPuter . fs . upload ) . toHaveBeenCalled ( ) ;
70+ expect ( console . log ) . toHaveBeenCalledWith (
71+ expect . stringContaining ( 'File "test.txt" created successfully!' )
72+ ) ;
73+ } ) ;
74+
75+ it ( "should show usage and return false if no arguments are provided" , async ( ) => {
76+ const result = await createFile ( [ ] ) ;
77+ expect ( result ) . toBe ( false ) ;
78+ expect ( console . log ) . toHaveBeenCalledWith (
79+ chalk . red ( "Usage: touch <file_name> [content]" )
80+ ) ;
81+ } ) ;
82+
83+ it ( "should overwrite an existing file" , async ( ) => {
84+ mockPuter . fs . stat . mockResolvedValue ( { id : "existing-file-id" } ) ;
85+ mockPuter . fs . space . mockResolvedValue ( { used : 500 , capacity : 1000 } ) ;
86+ mockPuter . fs . upload . mockResolvedValue ( {
87+ name : "test.txt" ,
88+ path : "/testuser/files/test.txt" ,
89+ uid : "file-uid" ,
90+ } ) ;
91+
92+ const result = await createFile ( [ "test.txt" , "new content" ] ) ;
93+
94+ expect ( result ) . toBe ( true ) ;
95+ expect ( console . log ) . toHaveBeenCalledWith (
96+ chalk . yellow ( 'File "test.txt" already exists. It will be overwritten.' )
97+ ) ;
98+ expect ( mockPuter . fs . upload ) . toHaveBeenCalled ( ) ;
99+ } ) ;
100+
101+ it ( "should return false if there is not enough disk space" , async ( ) => {
102+ mockPuter . fs . stat . mockRejectedValue ( { code : "subject_does_not_exist" } ) ;
103+ mockPuter . fs . space . mockResolvedValue ( { used : 1000 , capacity : 1000 } ) ;
104+ vi . spyOn ( commons , "showDiskSpaceUsage" ) . mockImplementation ( ( ) => { } ) ;
105+
106+ const result = await createFile ( [ "test.txt" ] ) ;
107+
108+ expect ( result ) . toBe ( false ) ;
109+ expect ( console . error ) . toHaveBeenCalledWith (
110+ chalk . red ( "Not enough disk space to create the file." )
111+ ) ;
112+ expect ( commons . showDiskSpaceUsage ) . toHaveBeenCalled ( ) ;
113+ } ) ;
114+
115+ it ( "should create missing directories" , async ( ) => {
116+ // First stat for file fails, second for directory also fails
117+ mockPuter . fs . stat
118+ . mockRejectedValueOnce ( { code : "subject_does_not_exist" } ) // file check
119+ . mockRejectedValueOnce ( { code : "subject_does_not_exist" } ) ; // dir check
120+ mockPuter . fs . space . mockResolvedValue ( { used : 500 , capacity : 1000 } ) ;
121+ mockPuter . fs . mkdir . mockResolvedValue ( { } ) ;
122+ mockPuter . fs . upload . mockResolvedValue ( {
123+ name : "test.txt" ,
124+ path : "/testuser/files/newdir/test.txt" ,
125+ uid : "file-uid" ,
53126 } ) ;
54127
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- } ) ;
128+ const result = await createFile ( [ "newdir/test.txt" , "content" ] ) ;
129+
130+ expect ( result ) . toBe ( true ) ;
131+ expect ( mockPuter . fs . mkdir ) . toHaveBeenCalledWith ( "/testuser/files/newdir" , {
132+ overwrite : false ,
133+ dedupeName : true ,
134+ createMissingParents : true ,
140135 } ) ;
141- } ) ;
136+ expect ( mockPuter . fs . upload ) . toHaveBeenCalled ( ) ;
137+ } ) ;
138+
139+ it ( "should handle API errors during file creation" , async ( ) => {
140+ mockPuter . fs . stat . mockRejectedValue ( { code : "subject_does_not_exist" } ) ;
141+ mockPuter . fs . space . mockResolvedValue ( { used : 500 , capacity : 1000 } ) ;
142+ mockPuter . fs . upload . mockRejectedValue ( new Error ( "API Error" ) ) ;
143+
144+ const result = await createFile ( [ "test.txt" ] ) ;
145+
146+ expect ( result ) . toBe ( false ) ;
147+ expect ( console . error ) . toHaveBeenCalledWith (
148+ chalk . red ( "Failed to create file.\nError: API Error" )
149+ ) ;
150+ } ) ;
151+ } ) ;
0 commit comments