@@ -43,6 +43,7 @@ let getAllChecks
4343let getCheckById
4444let getAllChecklists
4545let getChecklistById
46+ let getProjectById
4647
4748beforeAll ( async ( ) => {
4849 // Initialize server asynchronously
@@ -58,7 +59,8 @@ beforeAll(async () => {
5859 getAllChecks,
5960 getCheckById,
6061 getAllChecklists,
61- getChecklistById
62+ getChecklistById,
63+ getProjectById
6264 } = initializeStore ( knex ) )
6365} )
6466
@@ -557,4 +559,137 @@ describe('HTTP Server API V1', () => {
557559
558560 test . todo ( 'should return 500 for internal server error' )
559561 } )
562+
563+ describe ( 'POST /api/v1/bulk-import' , ( ) => {
564+ const operationId = getAllBulkImportOperations ( ) [ 0 ] . id
565+ let largePayload
566+ let validPayload
567+ let projectId
568+
569+ beforeEach ( async ( ) => {
570+ // Create a test project for each test
571+ const project = await addProject ( { name : 'test-project' } )
572+ projectId = project . id
573+ largePayload = [ {
574+ type : 'annualDependencyRefresh' ,
575+ project_id : projectId ,
576+ is_subscribed : true
577+ } , {
578+ type : 'vulnResponse14Days' ,
579+ project_id : projectId ,
580+ is_subscribed : true
581+ } , {
582+ type : 'incidentResponsePlan' ,
583+ project_id : projectId ,
584+ is_subscribed : true
585+ } , {
586+ type : 'assignCVEForKnownVulns' ,
587+ project_id : projectId ,
588+ is_subscribed : true
589+ } , {
590+ type : 'includeCVEInReleaseNotes' ,
591+ project_id : projectId ,
592+ is_subscribed : true
593+ } ]
594+ validPayload = [ largePayload [ 0 ] ]
595+ } )
596+
597+ test ( 'should return 202 and a success message' , async ( ) => {
598+ // Check initial state
599+ let storedProject = await getProjectById ( projectId )
600+ expect ( storedProject . has_annualDependencyRefresh_policy ) . toBe ( null )
601+
602+ // Perform bulk import
603+ const response = await app
604+ . post ( '/api/v1/bulk-import' )
605+ . send ( { id : operationId , payload : validPayload } )
606+
607+ expect ( response . status ) . toBe ( 202 )
608+ expect ( response . body ) . toHaveProperty ( 'status' , 'completed' )
609+ expect ( response . body ) . toHaveProperty ( 'started' )
610+ expect ( response . body ) . toHaveProperty ( 'finished' )
611+ expect ( response . body ) . toHaveProperty ( 'result' )
612+ expect ( response . body . result ) . toHaveProperty ( 'message' , 'Bulk import completed successfully' )
613+ expect ( response . body . result ) . toHaveProperty ( 'success' , true )
614+
615+ // Check final state
616+ storedProject = await getProjectById ( projectId )
617+ expect ( storedProject . has_annualDependencyRefresh_policy ) . toBe ( true )
618+ } )
619+
620+ test ( 'should return 202 and a success message (case: multiple updates)' , async ( ) => {
621+ // Check initial state
622+ let storedProject = await getProjectById ( projectId )
623+ expect ( storedProject . has_annualDependencyRefresh_policy ) . toBe ( null )
624+ expect ( storedProject . has_vulnResponse14Days_policy ) . toBe ( null )
625+ expect ( storedProject . has_incidentResponsePlan_policy ) . toBe ( null )
626+ expect ( storedProject . has_assignCVEForKnownVulns_policy ) . toBe ( null )
627+ expect ( storedProject . has_includeCVEInReleaseNotes_policy ) . toBe ( null )
628+
629+ // Perform bulk import
630+ const response = await app
631+ . post ( '/api/v1/bulk-import' )
632+ . send ( { id : operationId , payload : largePayload } )
633+
634+ expect ( response . status ) . toBe ( 202 )
635+ expect ( response . body ) . toHaveProperty ( 'status' , 'completed' )
636+ expect ( response . body ) . toHaveProperty ( 'started' )
637+ expect ( response . body ) . toHaveProperty ( 'finished' )
638+ expect ( response . body ) . toHaveProperty ( 'result' )
639+ expect ( response . body . result ) . toHaveProperty ( 'message' , 'Bulk import completed successfully' )
640+ expect ( response . body . result ) . toHaveProperty ( 'success' , true )
641+
642+ // Check final state
643+ storedProject = await getProjectById ( projectId )
644+ expect ( storedProject . has_annualDependencyRefresh_policy ) . toBe ( true )
645+ expect ( storedProject . has_vulnResponse14Days_policy ) . toBe ( true )
646+ expect ( storedProject . has_incidentResponsePlan_policy ) . toBe ( true )
647+ expect ( storedProject . has_assignCVEForKnownVulns_policy ) . toBe ( true )
648+ expect ( storedProject . has_includeCVEInReleaseNotes_policy ) . toBe ( true )
649+ } )
650+
651+ test ( 'should return 400 for invalid payload (case: Swagger rejection)' , async ( ) => {
652+ const response = await app
653+ . post ( '/api/v1/bulk-import' )
654+ . send ( { id : operationId , payload : 'invalid' } )
655+
656+ expect ( response . status ) . toBe ( 400 )
657+ expect ( response . body ) . toHaveProperty ( 'errors' )
658+ expect ( response . body . errors [ 0 ] ) . toHaveProperty ( 'message' , 'must be object' )
659+ } )
660+
661+ test ( 'should return 400 for invalid payload (case: invalid payload against JSON Schema)' , async ( ) => {
662+ const response = await app
663+ . post ( '/api/v1/bulk-import' )
664+ . send ( { id : operationId , payload : [ { invalid : 'payload' } ] } )
665+
666+ expect ( response . status ) . toBe ( 400 )
667+ expect ( response . body ) . toHaveProperty ( 'errors' )
668+ expect ( response . body . errors [ 0 ] ) . toHaveProperty ( 'message' , 'The data does not match the schema' )
669+ } )
670+
671+ test ( 'should return 404 for invalid operation ID' , async ( ) => {
672+ const response = await app
673+ . post ( '/api/v1/bulk-import' )
674+ . send ( { id : 'invalid' , payload : validPayload } )
675+
676+ expect ( response . status ) . toBe ( 404 )
677+ expect ( response . body ) . toHaveProperty ( 'errors' )
678+ expect ( response . body . errors [ 0 ] ) . toHaveProperty ( 'message' , 'Bulk import operation not found' )
679+ } )
680+
681+ test ( 'should return 500 if the request is not completed (due project not found)' , async ( ) => {
682+ const invalidPayload = validPayload . map ( p => ( { ...p , project_id : 9999999 } ) )
683+
684+ const response = await app
685+ . post ( '/api/v1/bulk-import' )
686+ . send ( { id : operationId , payload : invalidPayload } )
687+
688+ expect ( response . status ) . toBe ( 500 )
689+ expect ( response . body ) . toHaveProperty ( 'errors' )
690+ expect ( response . body . errors [ 0 ] ) . toHaveProperty ( 'message' , 'Failed to run bulk import: Operation failed for item type: annualDependencyRefresh, project_id: 9999999' )
691+ } )
692+
693+ test . skip ( 'should return 500 for internal server error' , async ( ) => { } )
694+ } )
560695} )
0 commit comments