@@ -698,4 +698,249 @@ describe('runInCI', () => {
698698 } ) ;
699699 } ) ;
700700 } ) ;
701+
702+ describe . each < [ string , Options ] > ( [
703+ [
704+ 'projects explicitly configured using folder patterns' ,
705+ {
706+ monorepo : true ,
707+ projects : [ 'frontend' , 'backend/*' ] ,
708+ } ,
709+ ] ,
710+ [
711+ 'projects implicitly determined by package.json files' ,
712+ {
713+ monorepo : true ,
714+ } ,
715+ ] ,
716+ ] ) ( 'monorepo mode - custom: %s' , ( _ , monorepoOptions ) => {
717+ beforeEach ( async ( ) => {
718+ const monorepoDir = join ( fixturesDir , 'monorepos' , 'custom' ) ;
719+ await cp ( monorepoDir , workDir , { recursive : true } ) ;
720+ await git . add ( '.' ) ;
721+ await git . commit ( 'Create projects in monorepo' ) ;
722+ } ) ;
723+
724+ describe ( 'push event' , ( ) => {
725+ beforeEach ( async ( ) => {
726+ await git . checkout ( 'main' ) ;
727+ } ) ;
728+
729+ it ( 'should collect reports for all projects' , async ( ) => {
730+ await expect (
731+ runInCI (
732+ { head : { ref : 'main' , sha : await git . revparse ( 'main' ) } } ,
733+ { } as ProviderAPIClient ,
734+ { ...options , ...monorepoOptions } ,
735+ git ,
736+ ) ,
737+ ) . resolves . toEqual ( {
738+ mode : 'monorepo' ,
739+ projects : [
740+ {
741+ name : expect . stringContaining ( 'api' ) ,
742+ files : {
743+ report : {
744+ json : join ( workDir , 'backend/api/.code-pushup/report.json' ) ,
745+ md : join ( workDir , 'backend/api/.code-pushup/report.md' ) ,
746+ } ,
747+ } ,
748+ } ,
749+ {
750+ name : expect . stringContaining ( 'auth' ) ,
751+ files : {
752+ report : {
753+ json : join ( workDir , 'backend/auth/.code-pushup/report.json' ) ,
754+ md : join ( workDir , 'backend/auth/.code-pushup/report.md' ) ,
755+ } ,
756+ } ,
757+ } ,
758+ {
759+ name : 'frontend' ,
760+ files : {
761+ report : {
762+ json : join ( workDir , 'frontend/.code-pushup/report.json' ) ,
763+ md : join ( workDir , 'frontend/.code-pushup/report.md' ) ,
764+ } ,
765+ } ,
766+ } ,
767+ ] ,
768+ } satisfies RunResult ) ;
769+
770+ expect (
771+ executeProcessSpy . mock . calls . filter ( ( [ cfg ] ) =>
772+ cfg . command . includes ( 'code-pushup' ) ,
773+ ) ,
774+ ) . toHaveLength ( 6 ) ; // 3 autoruns and 3 print-configs for each project
775+ expect ( utils . executeProcess ) . toHaveBeenCalledWith ( {
776+ command : options . bin ,
777+ args : [ 'print-config' ] ,
778+ cwd : expect . stringContaining ( workDir ) ,
779+ } satisfies utils . ProcessConfig ) ;
780+ expect ( utils . executeProcess ) . toHaveBeenCalledWith ( {
781+ command : options . bin ,
782+ args : [ '--persist.format=json' , '--persist.format=md' ] ,
783+ cwd : expect . stringContaining ( workDir ) ,
784+ } satisfies utils . ProcessConfig ) ;
785+
786+ expect ( logger . error ) . not . toHaveBeenCalled ( ) ;
787+ expect ( logger . warn ) . not . toHaveBeenCalled ( ) ;
788+ expect ( logger . info ) . toHaveBeenCalled ( ) ;
789+ expect ( logger . debug ) . toHaveBeenCalled ( ) ;
790+ } ) ;
791+ } ) ;
792+
793+ describe ( 'pull request event' , ( ) => {
794+ let refs : GitRefs ;
795+ let diffMdString : string ;
796+
797+ beforeEach ( async ( ) => {
798+ await git . checkoutLocalBranch ( 'feature-1' ) ;
799+
800+ await writeFile ( join ( workDir , 'README.md' ) , '# Hello, world\n' ) ;
801+ await git . add ( 'README.md' ) ;
802+ await git . commit ( 'Create README' ) ;
803+
804+ refs = {
805+ head : { ref : 'feature-1' , sha : await git . revparse ( 'feature-1' ) } ,
806+ base : { ref : 'main' , sha : await git . revparse ( 'main' ) } ,
807+ } ;
808+
809+ diffMdString = await readFile ( fixturePaths . diffs . merged . md , 'utf8' ) ;
810+ } ) ;
811+
812+ it ( 'should collect and compare reports for all projects and comment merged diff' , async ( ) => {
813+ const api : ProviderAPIClient = {
814+ maxCommentChars : 1_000_000 ,
815+ createComment : vi . fn ( ) . mockResolvedValue ( mockComment ) ,
816+ updateComment : vi . fn ( ) ,
817+ listComments : vi . fn ( ) . mockResolvedValue ( [ ] ) ,
818+ downloadReportArtifact : vi . fn ( ) . mockImplementation ( async project => {
819+ const downloadPath = join ( workDir , 'tmp' , project , 'report.json' ) ;
820+ await mkdir ( dirname ( downloadPath ) , { recursive : true } ) ;
821+ await copyFile ( fixturePaths . reports . before . json , downloadPath ) ;
822+ return downloadPath ;
823+ } ) ,
824+ } ;
825+
826+ await expect (
827+ runInCI ( refs , api , { ...options , ...monorepoOptions } , git ) ,
828+ ) . resolves . toEqual ( {
829+ mode : 'monorepo' ,
830+ commentId : mockComment . id ,
831+ diffPath : join ( workDir , '.code-pushup/merged-report-diff.md' ) ,
832+ projects : [
833+ {
834+ name : expect . stringContaining ( 'api' ) ,
835+ files : {
836+ report : {
837+ json : join ( workDir , 'backend/api/.code-pushup/report.json' ) ,
838+ md : join ( workDir , 'backend/api/.code-pushup/report.md' ) ,
839+ } ,
840+ diff : {
841+ json : join (
842+ workDir ,
843+ 'backend/api/.code-pushup/report-diff.json' ,
844+ ) ,
845+ md : join ( workDir , 'backend/api/.code-pushup/report-diff.md' ) ,
846+ } ,
847+ } ,
848+ newIssues : [ ] ,
849+ } ,
850+ {
851+ name : expect . stringContaining ( 'auth' ) ,
852+ files : {
853+ report : {
854+ json : join ( workDir , 'backend/auth/.code-pushup/report.json' ) ,
855+ md : join ( workDir , 'backend/auth/.code-pushup/report.md' ) ,
856+ } ,
857+ diff : {
858+ json : join (
859+ workDir ,
860+ 'backend/auth/.code-pushup/report-diff.json' ,
861+ ) ,
862+ md : join ( workDir , 'backend/auth/.code-pushup/report-diff.md' ) ,
863+ } ,
864+ } ,
865+ newIssues : [ ] ,
866+ } ,
867+ {
868+ name : 'frontend' ,
869+ files : {
870+ report : {
871+ json : join ( workDir , 'frontend/.code-pushup/report.json' ) ,
872+ md : join ( workDir , 'frontend/.code-pushup/report.md' ) ,
873+ } ,
874+ diff : {
875+ json : join ( workDir , 'frontend/.code-pushup/report-diff.json' ) ,
876+ md : join ( workDir , 'frontend/.code-pushup/report-diff.md' ) ,
877+ } ,
878+ } ,
879+ newIssues : [ ] ,
880+ } ,
881+ ] ,
882+ } satisfies RunResult ) ;
883+
884+ await expect (
885+ readFile ( join ( workDir , '.code-pushup/merged-report-diff.md' ) , 'utf8' ) ,
886+ ) . resolves . toBe ( diffMdString ) ;
887+
888+ expect ( api . listComments ) . toHaveBeenCalledWith ( ) ;
889+ expect ( api . createComment ) . toHaveBeenCalledWith (
890+ expect . stringContaining ( diffMdString ) ,
891+ ) ;
892+ expect ( api . updateComment ) . not . toHaveBeenCalled ( ) ;
893+
894+ // 3 autoruns for each project
895+ // 3 print-configs for each project
896+ // 3 compares for each project
897+ // 0 autoruns and print-configs for uncached projects
898+ // 1 merge-diffs for all projects
899+ expect (
900+ executeProcessSpy . mock . calls . filter ( ( [ cfg ] ) =>
901+ cfg . command . includes ( 'code-pushup' ) ,
902+ ) ,
903+ ) . toHaveLength ( 10 ) ;
904+ expect ( utils . executeProcess ) . toHaveBeenCalledWith ( {
905+ command : options . bin ,
906+ args : [ 'print-config' ] ,
907+ cwd : expect . stringContaining ( workDir ) ,
908+ } satisfies utils . ProcessConfig ) ;
909+ expect ( utils . executeProcess ) . toHaveBeenCalledWith ( {
910+ command : options . bin ,
911+ args : [ '--persist.format=json' , '--persist.format=md' ] ,
912+ cwd : expect . stringContaining ( workDir ) ,
913+ } satisfies utils . ProcessConfig ) ;
914+ expect ( utils . executeProcess ) . toHaveBeenCalledWith ( {
915+ command : options . bin ,
916+ args : [
917+ 'compare' ,
918+ expect . stringMatching ( / ^ - - b e f o r e = .* p r e v - r e p o r t .j s o n $ / ) ,
919+ expect . stringMatching ( / ^ - - a f t e r = .* c u r r - r e p o r t .j s o n $ / ) ,
920+ expect . stringMatching ( / ^ - - l a b e l = \w + $ / ) ,
921+ '--persist.format=json' ,
922+ '--persist.format=md' ,
923+ ] ,
924+ cwd : expect . stringContaining ( workDir ) ,
925+ } satisfies utils . ProcessConfig ) ;
926+ expect ( utils . executeProcess ) . toHaveBeenCalledWith ( {
927+ command : options . bin ,
928+ args : [
929+ 'merge-diffs' ,
930+ `--files=${ join ( workDir , 'backend/api/.code-pushup/report-diff.json' ) } ` ,
931+ `--files=${ join ( workDir , 'backend/auth/.code-pushup/report-diff.json' ) } ` ,
932+ `--files=${ join ( workDir , 'frontend/.code-pushup/report-diff.json' ) } ` ,
933+ expect . stringMatching ( / ^ - - p e r s i s t .o u t p u t D i r = .* \. c o d e - p u s h u p $ / ) ,
934+ '--persist.filename=merged-report' ,
935+ ] ,
936+ cwd : expect . stringContaining ( workDir ) ,
937+ } satisfies utils . ProcessConfig ) ;
938+
939+ expect ( logger . error ) . not . toHaveBeenCalled ( ) ;
940+ expect ( logger . warn ) . not . toHaveBeenCalled ( ) ;
941+ expect ( logger . info ) . toHaveBeenCalled ( ) ;
942+ expect ( logger . debug ) . toHaveBeenCalled ( ) ;
943+ } ) ;
944+ } ) ;
945+ } ) ;
701946} ) ;
0 commit comments