@@ -329,10 +329,12 @@ func TestPnpmInstallIgnoreWorkspaceScopesBuildInfo(t *testing.T) {
329329//
330330// Fixture (see testdata/pnpm/pnpmworkspace):
331331//
332- // root (private) -> devDependency: json@9.0.6 <- must be ABSENT with --prod
333- // packages/nested1 -> dependency: loadash@1.0.0 <- must be present
334- // packages/nested2 -> dependency: xml@1.0.1 <- must be present
335- // optionalDependency: is-promise@2.2.2 <- must be PRESENT (--prod doesn't touch optDeps)
332+ // root (private) -> devDependency: json@9.0.6 <- must be ABSENT with --prod
333+ // packages/nested1 -> dependency: loadash@1.0.0 <- must be present
334+ // packages/nested2 -> dependency: xml@1.0.1 <- must be present
335+ //
336+ // The orthogonal direction (devDeps preserved, regular deps filtered) is
337+ // covered by TestPnpmInstallDevFlagForwardedToBuildInfo.
336338func TestPnpmInstallProdFlagForwardedToBuildInfo (t * testing.T ) {
337339 initPnpmTest (t )
338340 defer cleanPnpmTest (t )
@@ -356,7 +358,7 @@ func TestPnpmInstallProdFlagForwardedToBuildInfo(t *testing.T) {
356358 bi , err := pnpmBuild .ToBuildInfo ()
357359 assert .NoError (t , err )
358360
359- foundLoadash , foundXml , foundIsPromise := false , false , false
361+ foundLoadash , foundXml := false , false
360362 for _ , mod := range bi .Modules {
361363 for _ , dep := range mod .Dependencies {
362364 assert .False (t , strings .HasPrefix (dep .Id , "json:" ),
@@ -367,17 +369,10 @@ func TestPnpmInstallProdFlagForwardedToBuildInfo(t *testing.T) {
367369 if strings .HasPrefix (dep .Id , "xml:" ) {
368370 foundXml = true
369371 }
370- if strings .HasPrefix (dep .Id , "is-promise:" ) {
371- foundIsPromise = true
372- }
373372 }
374373 }
375374 assert .True (t , foundLoadash , "regular dependency loadash (nested1) must remain in build-info under --prod" )
376375 assert .True (t , foundXml , "regular dependency xml (nested2) must remain in build-info under --prod" )
377- // --prod and --no-optional are orthogonal: --prod filters devDependencies, --no-optional
378- // filters optionalDependencies. Locking is-promise's presence here documents this contract
379- // and guards against accidental over-filtering by either pnpm or our forwarding logic.
380- assert .True (t , foundIsPromise , "optionalDependency is-promise (nested2) must remain in build-info under --prod (--prod is orthogonal to --no-optional)" )
381376
382377 inttestutils .DeleteBuild (serverDetails .ArtifactoryUrl , tests .PnpmBuildName , artHttpDetails )
383378}
@@ -492,6 +487,26 @@ func TestPnpmInstallSubPackageBuildInfoRoundTrip(t *testing.T) {
492487 clientTestUtils .ChangeDirAndAssert (t , pnpmWorkspacePath )
493488 rootBuildNumber := "657"
494489
490+ // Configure pnpm to resolve through Artifactory's npm-remote-cache. Without
491+ // this .npmrc the install bypasses Artifactory and fetches directly from the
492+ // public registry — the tarball never reaches Artifactory, AQL can't see it,
493+ // and dep.Sha1/Sha256/Md5 stay empty in build-info. Same setup pattern as
494+ // TestPnpmInstallWithPreviousBuildCache, which depends on the same path.
495+ registry := npmCmdUtils .GetNpmRepositoryUrl (tests .NpmRemoteRepo , serverDetails .GetArtifactoryUrl ())
496+ registryWithSlash := strings .TrimSuffix (registry , "/" ) + "/"
497+ authKey , authValue := npmCmdUtils .GetNpmAuthKeyValue (serverDetails , registryWithSlash )
498+ npmrcContent := fmt .Sprintf ("registry=%s\n %s=%s\n " , registryWithSlash , authKey , authValue )
499+ assert .NoError (t , os .WriteFile (filepath .Join (pnpmWorkspacePath , ".npmrc" ), []byte (npmrcContent ), 0644 ))
500+
501+ // Drop any pnpm metadata cache for this Artifactory host to avoid stale
502+ // tarball URLs from previous test runs (repo names include a unique suffix).
503+ artHost := strings .TrimPrefix (strings .TrimPrefix (serverDetails .GetArtifactoryUrl (), "https://" ), "http://" )
504+ artHost = strings .SplitN (artHost , "/" , 2 )[0 ]
505+ if homeDir , hErr := os .UserHomeDir (); hErr == nil {
506+ _ = os .RemoveAll (filepath .Join (homeDir , "Library" , "Caches" , "pnpm" , "metadata-v1.3" , artHost ))
507+ _ = os .RemoveAll (filepath .Join (homeDir , ".local" , "share" , "pnpm" , "store" , "v3" , "metadata" , artHost ))
508+ }
509+
495510 runJfrogCli (t , "pnpm" , "install" , "--store-dir=" + tempCacheDirPath ,
496511 "--build-name=" + tests .PnpmBuildName , "--build-number=" + rootBuildNumber )
497512
@@ -611,15 +626,18 @@ func TestPnpmInstallSubPackageBuildInfoFromEnvVars(t *testing.T) {
611626 inttestutils .DeleteBuild (serverDetails .ArtifactoryUrl , tests .PnpmBuildName , artHttpDetails )
612627}
613628
614- // TestPnpmInstallNoOptionalFlagForwardedToBuildInfo verifies that --no-optional
615- // is forwarded to the internal `pnpm ls` call so build-info excludes
616- // optionalDependencies that pnpm install also skipped.
629+ // TestPnpmInstallDevFlagForwardedToBuildInfo verifies that --dev is forwarded
630+ // to the internal `pnpm ls` call so build-info reflects what was actually
631+ // installed: only devDependencies, with regular dependencies filtered out.
632+ // This is the symmetric counterpart of --prod and locks the same forwarding
633+ // path against accidental regression.
617634//
618635// Fixture (see testdata/pnpm/pnpmworkspace):
619636//
620- // packages/nested2 -> dependency: xml@1.0.1 <- must remain
621- // optionalDependency: is-promise@2.2.2 <- must be ABSENT under --no-optional
622- func TestPnpmInstallNoOptionalFlagForwardedToBuildInfo (t * testing.T ) {
637+ // root (private) -> devDependency: json@9.0.6 <- must be PRESENT under --dev
638+ // packages/nested1 -> dependency: loadash@1.0.0 <- must be ABSENT under --dev
639+ // packages/nested2 -> dependency: xml@1.0.1 <- must be ABSENT under --dev
640+ func TestPnpmInstallDevFlagForwardedToBuildInfo (t * testing.T ) {
623641 initPnpmTest (t )
624642 defer cleanPnpmTest (t )
625643 wd , err := os .Getwd ()
@@ -633,7 +651,7 @@ func TestPnpmInstallNoOptionalFlagForwardedToBuildInfo(t *testing.T) {
633651 buildNumber := "655"
634652 clientTestUtils .ChangeDirAndAssert (t , pnpmWorkspacePath )
635653
636- runJfrogCli (t , "pnpm" , "install" , "--no-optional " , "--store-dir=" + tempCacheDirPath ,
654+ runJfrogCli (t , "pnpm" , "install" , "--dev " , "--store-dir=" + tempCacheDirPath ,
637655 "--build-name=" + tests .PnpmBuildName , "--build-number=" + buildNumber )
638656
639657 buildInfoService := build .CreateBuildInfoService ()
@@ -642,19 +660,22 @@ func TestPnpmInstallNoOptionalFlagForwardedToBuildInfo(t *testing.T) {
642660 bi , err := pnpmBuild .ToBuildInfo ()
643661 assert .NoError (t , err )
644662
645- foundXml := false
663+ foundJson := false
646664 for _ , mod := range bi .Modules {
647665 for _ , dep := range mod .Dependencies {
648- assert .False (t , strings .HasPrefix (dep .Id , "is-promise :" ),
649- "--no-optional must filter optionalDependencies from build-info (saw %s in module %s)" ,
666+ assert .False (t , strings .HasPrefix (dep .Id , "loadash :" ),
667+ "--dev must filter regular dependencies from build-info (saw %s in module %s)" ,
650668 dep .Id , mod .Id )
651- if strings .HasPrefix (dep .Id , "xml:" ) {
652- foundXml = true
669+ assert .False (t , strings .HasPrefix (dep .Id , "xml:" ),
670+ "--dev must filter regular dependencies from build-info (saw %s in module %s)" ,
671+ dep .Id , mod .Id )
672+ if strings .HasPrefix (dep .Id , "json:" ) {
673+ foundJson = true
653674 }
654675 }
655676 }
656- assert .True (t , foundXml ,
657- "regular dependency xml (nested2 ) must remain in build-info under --no-optional " )
677+ assert .True (t , foundJson ,
678+ "devDependency json (workspace root ) must remain in build-info under --dev " )
658679
659680 inttestutils .DeleteBuild (serverDetails .ArtifactoryUrl , tests .PnpmBuildName , artHttpDetails )
660681}
0 commit comments