1
+ /* eslint-disable prettier/prettier */
1
2
import Arweave from 'arweave' ;
2
3
import { expect } from 'chai' ;
3
- import { stub } from 'sinon' ;
4
+ import { stub , SinonStub } from 'sinon' ;
4
5
import {
5
6
stubArweaveAddress ,
6
7
stubEntityID ,
7
8
stubEntityIDAlt ,
8
9
stubPublicDrive ,
9
10
stubPublicFile ,
10
- stubPublicFolder
11
+ stubPublicFolder ,
12
+ stubTxID ,
13
+ stubTxIDAlt ,
14
+ stubTxIDAltTwo
11
15
} from '../../tests/stubs' ;
12
- import { ArweaveAddress , DriveID , EntityID } from '../types' ;
16
+ import { ADDR , ArweaveAddress , DriveID , EID , EntityID } from '../types' ;
13
17
import {
14
18
ArFSAnonymousCache ,
15
19
ArFSDAOAnonymous ,
@@ -19,6 +23,7 @@ import {
19
23
} from './arfsdao_anonymous' ;
20
24
import { ArFSPublicDrive , ArFSPublicFile , ArFSPublicFolder } from './arfs_entities' ;
21
25
import { ArFSEntityCache } from './arfs_entity_cache' ;
26
+ import { ArFSPublicFileBuilder } from './arfs_builders/arfs_file_builders' ;
22
27
23
28
const fakeArweave = Arweave . init ( {
24
29
host : 'localhost' ,
@@ -226,4 +231,280 @@ describe('ArFSDAOAnonymous class', () => {
226
231
// });
227
232
} ) ;
228
233
} ) ;
234
+
235
+ describe ( 'getPublicFilesWithParentFolderIds' , ( ) => {
236
+ let dao : ArFSDAOAnonymous ;
237
+ let gqlRequestStub : SinonStub ;
238
+ let ArFSPublicFileBuilderStub : SinonStub ;
239
+
240
+ beforeEach ( ( ) => {
241
+ dao = new ArFSDAOAnonymous ( fakeArweave ) ;
242
+ gqlRequestStub = stub ( dao [ 'gatewayApi' ] , 'gqlRequest' ) ;
243
+ ArFSPublicFileBuilderStub = stub ( ArFSPublicFileBuilder . prototype , 'getDataForTxID' ) ;
244
+ } ) ;
245
+
246
+ afterEach ( ( ) => {
247
+ gqlRequestStub . restore ( ) ;
248
+ ArFSPublicFileBuilderStub . restore ( ) ;
249
+ } ) ;
250
+
251
+ it ( 'returns expected files for given folder IDs' , async ( ) => {
252
+ // Mock GQL response
253
+ const mockGQLResponse = {
254
+ edges : [
255
+ {
256
+ cursor : 'cursor1' ,
257
+ node : {
258
+ id : `${ stubTxID } ` ,
259
+ tags : [
260
+ { name : 'App-Name' , value : 'ArDrive-CLI' } ,
261
+ { name : 'App-Version' , value : '1.2.0' } ,
262
+ { name : 'ArFS' , value : '0.11' } ,
263
+ { name : 'Content-Type' , value : 'application/json' } ,
264
+ { name : 'Drive-Id' , value : 'e93cf9c4-5f20-4d7a-87c4-034777cbb51e' } ,
265
+ { name : 'Entity-Type' , value : 'file' } ,
266
+ { name : 'Unix-Time' , value : '1639073846' } ,
267
+ { name : 'Parent-Folder-Id' , value : '6c312b3e-4778-4a18-8243-f2b346f5e7cb' } ,
268
+ { name : 'File-Id' , value : '9f7038c7-26bd-4856-a843-8de24b828d4e' }
269
+ ] ,
270
+ owner : { address : 'vh-NTHVvlKZqRxc8LyyTNok65yQ55a_PJ1zWLb9G2JI' }
271
+ }
272
+ }
273
+ ] ,
274
+ pageInfo : {
275
+ hasNextPage : false
276
+ }
277
+ } ;
278
+
279
+ gqlRequestStub . resolves ( mockGQLResponse ) ;
280
+
281
+ // Add stub for getDataForTxID
282
+ const stubFileGetDataResult = Buffer . from (
283
+ JSON . stringify ( {
284
+ name : '2' ,
285
+ size : 2048 ,
286
+ lastModifiedDate : 1639073634269 ,
287
+ dataTxId : 'yAogaGWWYgWO5xWZevb45Y7YRp7E9iDsvkJvfR7To9c' ,
288
+ dataContentType : 'unknown'
289
+ } )
290
+ ) ;
291
+
292
+ // Stub the getDataForTxID method on the builder
293
+ ArFSPublicFileBuilderStub . resolves ( stubFileGetDataResult ) ;
294
+
295
+ const folderIds = [ EID ( '6c312b3e-4778-4a18-8243-f2b346f5e7cb' ) ] ;
296
+ const owner = ADDR ( 'vh-NTHVvlKZqRxc8LyyTNok65yQ55a_PJ1zWLb9G2JI' ) ;
297
+ const driveId = EID ( 'e93cf9c4-5f20-4d7a-87c4-034777cbb51e' ) ;
298
+
299
+ const files = await dao . getPublicFilesWithParentFolderIds ( folderIds , owner , driveId , true ) ;
300
+
301
+ expect ( files ) . to . have . lengthOf ( 1 ) ;
302
+ expect ( `${ files [ 0 ] . fileId } ` ) . to . equal ( '9f7038c7-26bd-4856-a843-8de24b828d4e' ) ;
303
+ expect ( `${ files [ 0 ] . driveId } ` ) . to . equal ( 'e93cf9c4-5f20-4d7a-87c4-034777cbb51e' ) ;
304
+ expect ( `${ files [ 0 ] . parentFolderId } ` ) . to . equal ( '6c312b3e-4778-4a18-8243-f2b346f5e7cb' ) ;
305
+ } ) ;
306
+
307
+ it ( 'handles pagination correctly' , async ( ) => {
308
+ const fileId1 = '9f7038c7-26bd-4856-a843-8de24b828d4e' ;
309
+ const fileId2 = '1f7038c7-26bd-4856-a843-8de24b828d4e' ;
310
+
311
+ // Mock two pages of GQL responses
312
+ const mockGQLResponse1 = {
313
+ edges : [
314
+ {
315
+ cursor : 'cursor1' ,
316
+ node : {
317
+ id : `${ stubTxID } ` ,
318
+ tags : [
319
+ { name : 'App-Name' , value : 'ArDrive-CLI' } ,
320
+ { name : 'App-Version' , value : '1.2.0' } ,
321
+ { name : 'ArFS' , value : '0.11' } ,
322
+ { name : 'Content-Type' , value : 'application/json' } ,
323
+ { name : 'Drive-Id' , value : 'e93cf9c4-5f20-4d7a-87c4-034777cbb51e' } ,
324
+ { name : 'Entity-Type' , value : 'file' } ,
325
+ { name : 'Unix-Time' , value : '1639073846' } ,
326
+ { name : 'Parent-Folder-Id' , value : '6c312b3e-4778-4a18-8243-f2b346f5e7cb' } ,
327
+ { name : 'File-Id' , value : fileId1 }
328
+ ] ,
329
+ owner : { address : 'vh-NTHVvlKZqRxc8LyyTNok65yQ55a_PJ1zWLb9G2JI' }
330
+ }
331
+ }
332
+ ] ,
333
+ pageInfo : {
334
+ hasNextPage : true
335
+ }
336
+ } ;
337
+
338
+ const mockGQLResponse2 = {
339
+ edges : [
340
+ {
341
+ cursor : 'cursor2' ,
342
+ node : {
343
+ id : `${ stubTxIDAlt } ` ,
344
+ tags : [
345
+ { name : 'App-Name' , value : 'ArDrive-CLI' } ,
346
+ { name : 'App-Version' , value : '1.2.0' } ,
347
+ { name : 'ArFS' , value : '0.11' } ,
348
+ { name : 'Content-Type' , value : 'application/json' } ,
349
+ { name : 'Drive-Id' , value : 'e93cf9c4-5f20-4d7a-87c4-034777cbb51e' } ,
350
+ { name : 'Entity-Type' , value : 'file' } ,
351
+ { name : 'Unix-Time' , value : '1639073846' } ,
352
+ { name : 'Parent-Folder-Id' , value : '6c312b3e-4778-4a18-8243-f2b346f5e7cb' } ,
353
+ { name : 'File-Id' , value : fileId2 }
354
+ ] ,
355
+ owner : { address : 'vh-NTHVvlKZqRxc8LyyTNok65yQ55a_PJ1zWLb9G2JI' }
356
+ }
357
+ }
358
+ ] ,
359
+ pageInfo : {
360
+ hasNextPage : false
361
+ }
362
+ } ;
363
+
364
+ gqlRequestStub . onFirstCall ( ) . resolves ( mockGQLResponse1 ) ;
365
+ gqlRequestStub . onSecondCall ( ) . resolves ( mockGQLResponse2 ) ;
366
+
367
+ const folderIds = [ EID ( '6c312b3e-4778-4a18-8243-f2b346f5e7cb' ) ] ;
368
+ const owner = ADDR ( 'vh-NTHVvlKZqRxc8LyyTNok65yQ55a_PJ1zWLb9G2JI' ) ;
369
+ const driveId = EID ( 'e93cf9c4-5f20-4d7a-87c4-034777cbb51e' ) ;
370
+
371
+ // Add stub for getDataForTxID
372
+ const stubFileGetDataResult = Buffer . from (
373
+ JSON . stringify ( {
374
+ name : '2' ,
375
+ size : 2048 ,
376
+ lastModifiedDate : 1639073634269 ,
377
+ dataTxId : 'yAogaGWWYgWO5xWZevb45Y7YRp7E9iDsvkJvfR7To9c' ,
378
+ dataContentType : 'unknown'
379
+ } )
380
+ ) ;
381
+
382
+ ArFSPublicFileBuilderStub . withArgs ( stubTxID ) . resolves ( stubFileGetDataResult ) ;
383
+ ArFSPublicFileBuilderStub . withArgs ( stubTxIDAlt ) . resolves ( stubFileGetDataResult ) ;
384
+
385
+ const files = await dao . getPublicFilesWithParentFolderIds ( folderIds , owner , driveId , true ) ;
386
+
387
+ expect ( files ) . to . have . lengthOf ( 2 ) ;
388
+ expect ( `${ files [ 0 ] . fileId } ` ) . to . equal ( fileId1 ) ;
389
+ expect ( `${ files [ 1 ] . fileId } ` ) . to . equal ( fileId2 ) ;
390
+ expect ( gqlRequestStub . callCount ) . to . equal ( 2 ) ;
391
+ } ) ;
392
+
393
+ it ( 'skips invalid files and continues processing' , async ( ) => {
394
+ const fileId1 = '9f7038c7-26bd-4856-a843-8de24b828d4e' ;
395
+ const fileId2 = '1f7038c7-26bd-4856-a843-8de24b828d4e' ;
396
+ const fileId3 = '2f7038c7-26bd-4856-a843-8de24b828d4e' ;
397
+
398
+ const mockGQLResponse = {
399
+ edges : [
400
+ {
401
+ cursor : 'cursor1' ,
402
+ node : {
403
+ id : `${ stubTxID } ` ,
404
+ tags : [
405
+ { name : 'App-Name' , value : 'ArDrive-CLI' } ,
406
+ { name : 'App-Version' , value : '1.2.0' } ,
407
+ { name : 'ArFS' , value : '0.11' } ,
408
+ { name : 'Content-Type' , value : 'application/json' } ,
409
+ { name : 'Drive-Id' , value : 'e93cf9c4-5f20-4d7a-87c4-034777cbb51e' } ,
410
+ { name : 'Entity-Type' , value : 'file' } ,
411
+ { name : 'Unix-Time' , value : '1639073846' } ,
412
+ { name : 'Parent-Folder-Id' , value : '6c312b3e-4778-4a18-8243-f2b346f5e7cb' } ,
413
+ { name : 'File-Id' , value : fileId1 }
414
+ ] ,
415
+ owner : { address : 'vh-NTHVvlKZqRxc8LyyTNok65yQ55a_PJ1zWLb9G2JI' }
416
+ }
417
+ } ,
418
+ {
419
+ cursor : 'cursor2' ,
420
+ node : {
421
+ id : `${ stubTxIDAlt } ` ,
422
+ tags : [
423
+ { name : 'App-Name' , value : 'ArDrive-CLI' } ,
424
+ { name : 'App-Version' , value : '1.2.0' } ,
425
+ { name : 'ArFS' , value : '0.11' } ,
426
+ { name : 'Content-Type' , value : 'application/json' } ,
427
+ { name : 'Drive-Id' , value : 'e93cf9c4-5f20-4d7a-87c4-034777cbb51e' } ,
428
+ { name : 'Entity-Type' , value : 'file' } ,
429
+ { name : 'Unix-Time' , value : '1639073846' } ,
430
+ { name : 'Parent-Folder-Id' , value : '1c312b3e-4778-4a18-8243-f2b346f5e7cb' } ,
431
+ { name : 'File-Id' , value : fileId2 }
432
+ ] ,
433
+ owner : { address : 'vh-NTHVvlKZqRxc8LyyTNok65yQ55a_PJ1zWLb9G2JI' }
434
+ }
435
+ } ,
436
+ {
437
+ cursor : 'cursor3' ,
438
+ node : {
439
+ id : `${ stubTxIDAltTwo } ` ,
440
+ tags : [
441
+ { name : 'App-Name' , value : 'ArDrive-CLI' } ,
442
+ { name : 'App-Version' , value : '1.2.0' } ,
443
+ { name : 'ArFS' , value : '0.11' } ,
444
+ { name : 'Content-Type' , value : 'application/json' } ,
445
+ { name : 'Drive-Id' , value : 'e93cf9c4-5f20-4d7a-87c4-034777cbb51e' } ,
446
+ { name : 'Entity-Type' , value : 'file' } ,
447
+ { name : 'Unix-Time' , value : '1639073846' } ,
448
+ { name : 'Parent-Folder-Id' , value : '1c312b3e-4778-4a18-8243-f2b346f5e7cb' } ,
449
+ { name : 'File-Id' , value : fileId3 }
450
+ ] ,
451
+ owner : { address : 'vh-NTHVvlKZqRxc8LyyTNok65yQ55a_PJ1zWLb9G2JI' }
452
+ }
453
+ }
454
+ ] ,
455
+ pageInfo : {
456
+ hasNextPage : false
457
+ }
458
+ } ;
459
+ gqlRequestStub . resolves ( mockGQLResponse ) ;
460
+ // Mock the getDataForTxID method to return valid metadata for the second file
461
+ const stubFileGetDataResultValid1 = Buffer . from (
462
+ JSON . stringify ( {
463
+ name : '2' ,
464
+ size : 2048 ,
465
+ lastModifiedDate : 1639073634269 ,
466
+ dataTxId : 'yAogaGWWYgWO5xWZevb45Y7YRp7E9iDsvkJvfR7To9c' ,
467
+ dataContentType : 'application/json'
468
+ } )
469
+ ) ;
470
+ // Invalid file metadata missing dataContentType
471
+ const stubFileGetDataResultWithEmptyContentType = Buffer . from (
472
+ JSON . stringify ( {
473
+ name : '2' ,
474
+ size : 2048 ,
475
+ lastModifiedDate : 1639073634269 ,
476
+ dataTxId : 'yAogaGWWYgWO5xWZevb45Y7YRp7E9iDsvkJvfR7To9c' ,
477
+ dataContentType : ''
478
+ } )
479
+ ) ;
480
+ // Valid file metadata
481
+ const stubFileGetDataResultValid2 = Buffer . from (
482
+ JSON . stringify ( {
483
+ name : '2' ,
484
+ size : 2048 ,
485
+ lastModifiedDate : 1639073634269 ,
486
+ dataTxId : 'yAogaGWWYgWO5xWZevb45Y7YRp7E9iDsvkJvfR7To9c' ,
487
+ dataContentType : 'text/plain'
488
+ } )
489
+ ) ;
490
+
491
+ // Valid file metadata
492
+ ArFSPublicFileBuilderStub . withArgs ( stubTxID ) . resolves ( stubFileGetDataResultValid1 ) ;
493
+ // Invalid file metadata missing dataContentType
494
+ ArFSPublicFileBuilderStub . withArgs ( stubTxIDAlt ) . resolves ( stubFileGetDataResultWithEmptyContentType ) ;
495
+ // Valid file metadata
496
+ ArFSPublicFileBuilderStub . withArgs ( stubTxIDAltTwo ) . resolves ( stubFileGetDataResultValid2 ) ;
497
+
498
+ const folderIds = [ EID ( '6c312b3e-4778-4a18-8243-f2b346f5e7cb' ) ] ;
499
+ const owner = ADDR ( 'vh-NTHVvlKZqRxc8LyyTNok65yQ55a_PJ1zWLb9G2JI' ) ;
500
+ const driveId = EID ( 'e93cf9c4-5f20-4d7a-87c4-034777cbb51e' ) ;
501
+
502
+ const files = await dao . getPublicFilesWithParentFolderIds ( folderIds , owner , driveId , true ) ;
503
+
504
+ // Verify that the invalid file was skipped
505
+ expect ( files ) . to . have . lengthOf ( 2 ) ;
506
+ expect ( `${ files [ 0 ] . fileId } ` ) . to . equal ( fileId1 ) ;
507
+ expect ( `${ files [ 1 ] . fileId } ` ) . to . equal ( fileId3 ) ;
508
+ } ) ;
509
+ } ) ;
229
510
} ) ;
0 commit comments