@@ -176,4 +176,141 @@ describe('SQLiteFileSystemProvider', () => {
176176 } , / F i l e N o t F o u n d / ) ;
177177 } ) ;
178178 } ) ;
179+ describe ( 'writeFile' , ( ) => {
180+ const provider = new SQLiteFileSystemProvider ( ) ;
181+ const docKey = 'test-doc' ;
182+
183+ it ( 'should throw NoPermissions if writing to __create__.sql' , async ( ) => {
184+ setupMockDocument ( docKey , { } ) ;
185+ const uri = vscode . Uri . parse ( `vscode-sqlite://${ docKey } /users/group/__create__.sql/create.sql` ) ;
186+ await assert . rejects ( async ( ) => {
187+ await provider . writeFile ( uri , new Uint8Array ( ) , { create : false , overwrite : true } ) ;
188+ } , ( err : any ) => err . message . includes ( 'Cannot edit CREATE statement directly' ) ) ;
189+ } ) ;
190+
191+ it ( 'should throw Unavailable for invalid row ID' , async ( ) => {
192+ setupMockDocument ( docKey , { } ) ;
193+ const uri = vscode . Uri . parse ( `vscode-sqlite://${ docKey } /users/group/invalid-id/col.txt` ) ;
194+ await assert . rejects ( async ( ) => {
195+ await provider . writeFile ( uri , new Uint8Array ( ) , { create : false , overwrite : true } ) ;
196+ } , ( err : any ) => err . message . includes ( 'Invalid Row ID' ) ) ;
197+ } ) ;
198+
199+ it ( 'should map string error to Unavailable' , async ( ) => {
200+ const dbOps = {
201+ updateCell : mock . fn ( async ( ) => {
202+ throw 'Database write string error' ;
203+ } )
204+ } ;
205+ setupMockDocument ( docKey , dbOps ) ;
206+
207+ const uri = vscode . Uri . parse ( `vscode-sqlite://${ docKey } /users/group/1/col.txt` ) ;
208+
209+ await assert . rejects ( async ( ) => {
210+ await provider . writeFile ( uri , new Uint8Array ( ) , { create : false , overwrite : true } ) ;
211+ } , ( err : any ) => err . message . includes ( 'Database write string error' ) ) ;
212+ } ) ;
213+
214+ it ( 'should map Error object to Unavailable' , async ( ) => {
215+ const dbOps = {
216+ updateCell : mock . fn ( async ( ) => {
217+ throw new Error ( 'Database write error' ) ;
218+ } )
219+ } ;
220+ setupMockDocument ( docKey , dbOps ) ;
221+
222+ const uri = vscode . Uri . parse ( `vscode-sqlite://${ docKey } /users/group/1/col.txt` ) ;
223+
224+ await assert . rejects ( async ( ) => {
225+ await provider . writeFile ( uri , new Uint8Array ( ) , { create : false , overwrite : true } ) ;
226+ } , ( err : any ) => err . message . includes ( 'Database write error' ) ) ;
227+ } ) ;
228+
229+ it ( 'should write text content correctly' , async ( ) => {
230+ const dbOps = {
231+ updateCell : mock . fn ( async ( ) => { } )
232+ } ;
233+ const doc = setupMockDocument ( docKey , dbOps ) ;
234+
235+ const uri = vscode . Uri . parse ( `vscode-sqlite://${ docKey } /users/group/1/col.txt` ) ;
236+ const content = new TextEncoder ( ) . encode ( 'Hello World' ) ;
237+ await provider . writeFile ( uri , content , { create : false , overwrite : true } ) ;
238+
239+ assert . strictEqual ( dbOps . updateCell . mock . callCount ( ) , 1 ) ;
240+ assert . deepStrictEqual ( dbOps . updateCell . mock . calls [ 0 ] . arguments , [ 'users' , 1 , 'col' , 'Hello World' ] ) ;
241+ assert . strictEqual ( doc . recordExternalModification . mock . callCount ( ) , 1 ) ;
242+ } ) ;
243+
244+ it ( 'should write binary content if not valid UTF-8' , async ( ) => {
245+ const dbOps = {
246+ updateCell : mock . fn ( async ( ) => { } )
247+ } ;
248+ const doc = setupMockDocument ( docKey , dbOps ) ;
249+
250+ const uri = vscode . Uri . parse ( `vscode-sqlite://${ docKey } /users/group/1/col.txt` ) ;
251+ const content = new Uint8Array ( [ 0xff , 0xff , 0xff ] ) ; // Invalid UTF-8
252+ await provider . writeFile ( uri , content , { create : false , overwrite : true } ) ;
253+
254+ assert . strictEqual ( dbOps . updateCell . mock . callCount ( ) , 1 ) ;
255+ assert . deepStrictEqual ( dbOps . updateCell . mock . calls [ 0 ] . arguments , [ 'users' , 1 , 'col' , content ] ) ;
256+ assert . strictEqual ( doc . recordExternalModification . mock . callCount ( ) , 1 ) ;
257+ } ) ;
258+ } ) ;
259+
260+ describe ( 'delete / rename / stat / watch' , ( ) => {
261+ const provider = new SQLiteFileSystemProvider ( ) ;
262+ const docKey = 'test-doc' ;
263+
264+ it ( 'should throw NoPermissions for createDirectory' , async ( ) => {
265+ const uri = vscode . Uri . parse ( `vscode-sqlite://${ docKey } /users/group` ) ;
266+ await assert . rejects ( async ( ) => {
267+ await provider . createDirectory ( uri ) ;
268+ } , ( err : any ) => err . message . includes ( 'NoPermissions' ) ) ;
269+ } ) ;
270+
271+ it ( 'should return empty array for readDirectory' , async ( ) => {
272+ const uri = vscode . Uri . parse ( `vscode-sqlite://${ docKey } /users/group` ) ;
273+ const res = await provider . readDirectory ( uri ) ;
274+ assert . deepStrictEqual ( res , [ ] ) ;
275+ } ) ;
276+
277+ it ( 'stat should return generic file stat for normal cell' , async ( ) => {
278+ const uri = vscode . Uri . parse ( `vscode-sqlite://${ docKey } /users/group/1/col.txt` ) ;
279+ setupMockDocument ( docKey , { } ) ;
280+ const s = await provider . stat ( uri ) ;
281+ assert . strictEqual ( s . type , vscode . FileType . File ) ;
282+ assert . strictEqual ( s . size , 0 ) ;
283+ assert . strictEqual ( s . permissions , undefined ) ;
284+ } ) ;
285+
286+ it ( 'stat should return generic file stat with Readonly for __create__.sql' , async ( ) => {
287+ const uri = vscode . Uri . parse ( `vscode-sqlite://${ docKey } /users/group/__create__.sql/create.sql` ) ;
288+ setupMockDocument ( docKey , { } ) ;
289+ const s = await provider . stat ( uri ) ;
290+ assert . strictEqual ( s . type , vscode . FileType . File ) ;
291+ assert . strictEqual ( s . size , 0 ) ;
292+ assert . strictEqual ( s . permissions , vscode . FilePermission . Readonly ) ;
293+ } ) ;
294+
295+ it ( 'watch should return a generic Disposable' , async ( ) => {
296+ const uri = vscode . Uri . parse ( `vscode-sqlite://${ docKey } /users/group/1/col.txt` ) ;
297+ const disposable = provider . watch ( uri , { recursive : false , excludes : [ ] } ) ;
298+ assert . ok ( disposable . dispose ) ;
299+ } ) ;
300+
301+ it ( 'should throw NoPermissions for delete' , async ( ) => {
302+ const uri = vscode . Uri . parse ( `vscode-sqlite://${ docKey } /users/group/1/col.txt` ) ;
303+ await assert . rejects ( async ( ) => {
304+ await provider . delete ( uri , { recursive : false } ) ;
305+ } , ( err : any ) => err . message . includes ( 'NoPermissions' ) ) ;
306+ } ) ;
307+
308+ it ( 'should throw NoPermissions for rename' , async ( ) => {
309+ const uri1 = vscode . Uri . parse ( `vscode-sqlite://${ docKey } /users/group/1/col.txt` ) ;
310+ const uri2 = vscode . Uri . parse ( `vscode-sqlite://${ docKey } /users/group/1/col2.txt` ) ;
311+ await assert . rejects ( async ( ) => {
312+ await provider . rename ( uri1 , uri2 , { overwrite : true } ) ;
313+ } , ( err : any ) => err . message . includes ( 'NoPermissions' ) ) ;
314+ } ) ;
315+ } ) ;
179316} ) ;
0 commit comments