@@ -6,7 +6,13 @@ import { getDependencies, getExecutionOrder, patchPackageDeps } from './deps'
66import { getNewVersion , versionToString } from './versions'
77
88import type { DirResult } from 'tmp'
9- import type { BasePackageInfo , LatestPackagesReleases , PackageVersion } from '@/types'
9+ import type {
10+ BasePackageInfo ,
11+ LatestPackagesReleases ,
12+ PackageVersion ,
13+ PackageInfoWithDependencies ,
14+ IgnoringDependencies ,
15+ } from '@/types'
1016
1117function writePackageJson ( obj : Record < string , unknown > , packagePath : string , cwd : string ) {
1218 // nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal
@@ -149,6 +155,87 @@ describe('Dependencies utils', () => {
149155 const batches = getExecutionOrder ( Object . values ( deps ) , { batching : true } )
150156 expect ( batches ) . toEqual ( [ [ pkg1Info , pkg4Info ] , [ pkg2Info ] , [ pkg3Info ] ] )
151157 } )
158+ describe ( 'Should respect ignoreDependencies' , ( ) => {
159+ const cycleLength = 6
160+ let packages : Array < PackageInfoWithDependencies > = [ ]
161+ beforeEach ( ( ) => {
162+ packages = Array . from ( { length : cycleLength } , ( _ , i ) => {
163+ const packageName = `package${ i } `
164+ const prevPackageName = `package${ ( i - 1 + cycleLength ) % cycleLength } `
165+
166+ return {
167+ name : packageName ,
168+ // nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal
169+ location : path . join ( tmpDir . name , 'packages' , packageName , 'package.json' ) ,
170+ dependsOn : [
171+ {
172+ name : prevPackageName ,
173+ type : Math . random ( ) > 0.5 ? 'dep' : 'devDep' ,
174+ value : versionToString ( getRandomVersion ( ) ) ,
175+ } ,
176+ ] ,
177+ }
178+ } )
179+ } )
180+
181+ it ( 'Simple cyclic graph test' , ( ) => {
182+ expect ( ( ) => {
183+ getExecutionOrder ( packages )
184+ } ) . toThrow ( 'The release cannot be done because of cyclic dependencies' )
185+
186+ for ( let i = 0 ; i < cycleLength ; i ++ ) {
187+ const ignoreDependencies = {
188+ [ packages [ i ] . name ] : [ packages [ ( i - 1 + cycleLength ) % cycleLength ] . name ] ,
189+ }
190+
191+ const expectedNonBatchedOrder = Array . from (
192+ { length : cycleLength } ,
193+ ( _ , idx ) => packages [ ( i + idx ) % cycleLength ] . name
194+ )
195+
196+ const nonBatchedOrder = getExecutionOrder ( packages , {
197+ ignoreDependencies,
198+ } ) . map ( ( pkg ) => pkg . name )
199+
200+ expect ( nonBatchedOrder ) . toEqual ( expectedNonBatchedOrder )
201+
202+ const expectedBatchedOrder = expectedNonBatchedOrder . map ( ( name ) => [ name ] )
203+ const batchedOrder = getExecutionOrder ( packages , {
204+ ignoreDependencies,
205+ batching : true ,
206+ } ) . map ( ( batch ) => batch . map ( ( pkg ) => pkg . name ) )
207+
208+ expect ( batchedOrder ) . toEqual ( expectedBatchedOrder )
209+ }
210+ } )
211+ it ( 'Advanced test' , ( ) => {
212+ const ignoreDependencies : IgnoringDependencies = { }
213+ const firstBatchExpected : Array < string > = [ ]
214+ const secondBatchExpected : Array < string > = [ ]
215+
216+ for ( let i = 0 ; i < cycleLength ; i ++ ) {
217+ const packageName = packages [ i ] . name
218+
219+ if ( i % 2 === 0 ) {
220+ const prevPackageName = packages [ ( i + cycleLength - 1 ) % cycleLength ] . name
221+ ignoreDependencies [ packageName ] = [ prevPackageName ]
222+ firstBatchExpected . push ( packageName )
223+ } else {
224+ secondBatchExpected . push ( packageName )
225+ }
226+ }
227+
228+ const batchedOrder = getExecutionOrder ( packages , {
229+ ignoreDependencies,
230+ batching : true ,
231+ } ) . map ( ( batch ) => batch . map ( ( pkg ) => pkg . name ) )
232+
233+ expect ( batchedOrder ) . toEqual ( [
234+ expect . objectContaining ( firstBatchExpected ) ,
235+ expect . objectContaining ( secondBatchExpected ) ,
236+ ] )
237+ } )
238+ } )
152239 } )
153240 describe ( 'patchPackageDeps' , ( ) => {
154241 it ( 'Should patch package with new version or version from latest release' , async ( ) => {
0 commit comments