Skip to content

Commit 053c657

Browse files
test(arfs dao anonymous)
- implement tests for `getPublicFilesWithParentFolderIds,` ensuring the broken files are skipped when having a bad state
1 parent 0855aa0 commit 053c657

File tree

2 files changed

+289
-5
lines changed

2 files changed

+289
-5
lines changed

src/arfs/arfs_builders/arfs_file_builders.test.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
import { expect } from 'chai';
22
import { stub } from 'sinon';
3-
import { fakeArweave, stubTxID } from '../../../tests/stubs';
3+
import { fakeArweave, stubTxID, stubTxIDAlt } from '../../../tests/stubs';
44
import { expectAsyncErrorThrow } from '../../../tests/test_helpers';
5-
import { EntityKey, GQLNodeInterface } from '../../types';
5+
import { EID, EntityKey, GQLNodeInterface } from '../../types';
66
import { gatewayUrlForArweave } from '../../utils/common';
77
import { GatewayAPI } from '../../utils/gateway_api';
88
import { ArFSPrivateFileBuilder, ArFSPublicFileBuilder } from './arfs_file_builders';
9+
import { ArFSDAOAnonymous } from '../arfsdao_anonymous';
10+
import { ADDR, DriveID, FolderID } from '../../types';
11+
import { stub, SinonStub } from 'sinon';
912

1013
const gatewayApi = new GatewayAPI({
1114
gatewayUrl: gatewayUrlForArweave(fakeArweave),

src/arfs/arfsdao_anonymous.test.ts

Lines changed: 284 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
1+
/* eslint-disable prettier/prettier */
12
import Arweave from 'arweave';
23
import { expect } from 'chai';
3-
import { stub } from 'sinon';
4+
import { stub, SinonStub } from 'sinon';
45
import {
56
stubArweaveAddress,
67
stubEntityID,
78
stubEntityIDAlt,
89
stubPublicDrive,
910
stubPublicFile,
10-
stubPublicFolder
11+
stubPublicFolder,
12+
stubTxID,
13+
stubTxIDAlt,
14+
stubTxIDAltTwo
1115
} from '../../tests/stubs';
12-
import { ArweaveAddress, DriveID, EntityID } from '../types';
16+
import { ADDR, ArweaveAddress, DriveID, EID, EntityID } from '../types';
1317
import {
1418
ArFSAnonymousCache,
1519
ArFSDAOAnonymous,
@@ -19,6 +23,7 @@ import {
1923
} from './arfsdao_anonymous';
2024
import { ArFSPublicDrive, ArFSPublicFile, ArFSPublicFolder } from './arfs_entities';
2125
import { ArFSEntityCache } from './arfs_entity_cache';
26+
import { ArFSPublicFileBuilder } from './arfs_builders/arfs_file_builders';
2227

2328
const fakeArweave = Arweave.init({
2429
host: 'localhost',
@@ -226,4 +231,280 @@ describe('ArFSDAOAnonymous class', () => {
226231
// });
227232
});
228233
});
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+
});
229510
});

0 commit comments

Comments
 (0)