11import { createMock } from '@golevelup/ts-jest' ;
22import { HMToken__factory } from '@human-protocol/core/typechain-types' ;
3- import { Encryption , EscrowClient , OperatorUtils } from '@human-protocol/sdk' ;
3+ import {
4+ Encryption ,
5+ EncryptionUtils ,
6+ EscrowClient ,
7+ OperatorUtils ,
8+ } from '@human-protocol/sdk' ;
49import { HttpService } from '@nestjs/axios' ;
510import { ConfigService } from '@nestjs/config' ;
611import { Test } from '@nestjs/testing' ;
@@ -69,7 +74,6 @@ jest.mock('minio', () => {
6974
7075describe ( 'JobService' , ( ) => {
7176 let jobService : JobService ;
72- let web3Service : Web3Service ;
7377 let storageService : StorageService ;
7478 let jobRepository : JobRepository ;
7579 let assignmentRepository : AssignmentRepository ;
@@ -136,14 +140,18 @@ describe('JobService', () => {
136140 } ) . compile ( ) ;
137141
138142 jobService = moduleRef . get < JobService > ( JobService ) ;
139- web3Service = moduleRef . get < Web3Service > ( Web3Service ) ;
140143 storageService = moduleRef . get < StorageService > ( StorageService ) ;
141144 jobRepository = moduleRef . get < JobRepository > ( JobRepository ) ;
142145 assignmentRepository =
143146 moduleRef . get < AssignmentRepository > ( AssignmentRepository ) ;
144147 webhookRepository = moduleRef . get < WebhookRepository > ( WebhookRepository ) ;
145148 } ) ;
146149
150+ afterEach ( ( ) => {
151+ ( jobService as any ) . manifestCache . clear ( ) ;
152+ jest . clearAllMocks ( ) ;
153+ } ) ;
154+
147155 describe ( 'createJob' , ( ) => {
148156 beforeAll ( async ( ) => {
149157 jest . spyOn ( jobRepository , 'createUnique' ) ;
@@ -497,7 +505,6 @@ describe('JobService', () => {
497505 . mockResolvedValue ( solutionsUrl ) ;
498506
499507 await jobService . solveJob ( assignment . id , 'solution' ) ;
500- expect ( web3Service . getSigner ) . toHaveBeenCalledWith ( chainId ) ;
501508 expect ( webhookRepository . createUnique ) . toHaveBeenCalledWith ( {
502509 escrowAddress,
503510 chainId,
@@ -515,7 +522,6 @@ describe('JobService', () => {
515522 await expect ( jobService . solveJob ( 1 , 'solution' ) ) . rejects . toThrow (
516523 new ConflictError ( ErrorAssignment . InvalidStatus ) ,
517524 ) ;
518- expect ( web3Service . getSigner ) . toHaveBeenCalledWith ( chainId ) ;
519525 } ) ;
520526
521527 it ( 'should fail if user is not assigned to the job' , async ( ) => {
@@ -556,7 +562,6 @@ describe('JobService', () => {
556562 await expect ( jobService . solveJob ( 1 , 'solution' ) ) . rejects . toThrow (
557563 'This job has already been completed' ,
558564 ) ;
559- expect ( web3Service . getSigner ) . toHaveBeenCalledWith ( chainId ) ;
560565 } ) ;
561566
562567 it ( 'should fail if user has already submitted a solution' , async ( ) => {
@@ -589,7 +594,100 @@ describe('JobService', () => {
589594 await expect ( jobService . solveJob ( 1 , 'solution' ) ) . rejects . toThrow (
590595 new ValidationError ( ErrorJob . SolutionAlreadySubmitted ) ,
591596 ) ;
592- expect ( web3Service . getSigner ) . toHaveBeenCalledWith ( chainId ) ;
597+ } ) ;
598+ } ) ;
599+
600+ describe ( 'getManifest' , ( ) => {
601+ const downloadFileFromUrlMock = jest . mocked ( downloadFileFromUrl ) ;
602+
603+ it ( 'should fetch and parse a non encrypted manifest' , async ( ) => {
604+ const manifest : ManifestDto = {
605+ requesterTitle : 'Example Title' ,
606+ requesterDescription : 'Example Description' ,
607+ submissionsRequired : 5 ,
608+ fundAmount : 100 ,
609+ } ;
610+
611+ downloadFileFromUrlMock . mockResolvedValue ( JSON . stringify ( manifest ) ) ;
612+ EncryptionUtils . isEncrypted = jest . fn ( ) . mockReturnValue ( false ) ;
613+
614+ const result = await jobService . getManifest (
615+ chainId ,
616+ escrowAddress ,
617+ MOCK_MANIFEST_URL ,
618+ ) ;
619+
620+ expect ( result ) . toEqual ( manifest ) ;
621+ expect ( Encryption . build ) . not . toHaveBeenCalled ( ) ;
622+ } ) ;
623+
624+ it ( 'should fetch and decrypt an encrypted manifest' , async ( ) => {
625+ const manifest : ManifestDto = {
626+ requesterTitle : 'Example Title' ,
627+ requesterDescription : 'Example Description' ,
628+ submissionsRequired : 5 ,
629+ fundAmount : 100 ,
630+ } ;
631+
632+ downloadFileFromUrlMock . mockResolvedValue ( 'encrypted-content' ) ;
633+ EncryptionUtils . isEncrypted = jest . fn ( ) . mockReturnValue ( true ) ;
634+ ( Encryption . build as any ) . mockImplementation ( ( ) => ( {
635+ decrypt : jest . fn ( ) . mockResolvedValue ( JSON . stringify ( manifest ) ) ,
636+ } ) ) ;
637+
638+ const result = await jobService . getManifest (
639+ chainId ,
640+ escrowAddress ,
641+ MOCK_MANIFEST_URL ,
642+ ) ;
643+
644+ expect ( result ) . toEqual ( manifest ) ;
645+ expect ( Encryption . build ) . toHaveBeenCalled ( ) ;
646+ } ) ;
647+
648+ it ( 'should cache the manifest in memory for repeated requests' , async ( ) => {
649+ const manifest : ManifestDto = {
650+ requesterTitle : 'Example Title' ,
651+ requesterDescription : 'Example Description' ,
652+ submissionsRequired : 5 ,
653+ fundAmount : 100 ,
654+ } ;
655+
656+ downloadFileFromUrlMock . mockResolvedValue ( manifest ) ;
657+
658+ const firstManifest = await jobService . getManifest (
659+ chainId ,
660+ escrowAddress ,
661+ MOCK_MANIFEST_URL ,
662+ ) ;
663+ const secondManifest = await jobService . getManifest (
664+ chainId ,
665+ escrowAddress ,
666+ MOCK_MANIFEST_URL ,
667+ ) ;
668+
669+ expect ( firstManifest ) . toEqual ( manifest ) ;
670+ expect ( secondManifest ) . toEqual ( manifest ) ;
671+ expect ( downloadFileFromUrlMock ) . toHaveBeenCalledTimes ( 1 ) ;
672+ } ) ;
673+
674+ it ( 'should retry downloading the manifest after a failed request' , async ( ) => {
675+ downloadFileFromUrlMock . mockRejectedValue (
676+ new Error ( 'Storage file not found' ) ,
677+ ) ;
678+ jest
679+ . spyOn ( webhookRepository , 'createUnique' )
680+ . mockResolvedValue ( { } as any ) ;
681+
682+ await expect (
683+ jobService . getManifest ( chainId , escrowAddress , MOCK_MANIFEST_URL ) ,
684+ ) . rejects . toThrow ( ErrorJob . ManifestNotFound ) ;
685+ await expect (
686+ jobService . getManifest ( chainId , escrowAddress , MOCK_MANIFEST_URL ) ,
687+ ) . rejects . toThrow ( ErrorJob . ManifestNotFound ) ;
688+
689+ expect ( downloadFileFromUrlMock ) . toHaveBeenCalledTimes ( 2 ) ;
690+ expect ( webhookRepository . createUnique ) . toHaveBeenCalledTimes ( 2 ) ;
593691 } ) ;
594692 } ) ;
595693
0 commit comments