From 19fa87bc26d40a41839434323da37dcad4ebaf33 Mon Sep 17 00:00:00 2001 From: attiasas Date: Wed, 9 Oct 2024 15:01:47 +0300 Subject: [PATCH 1/7] Show pnpm install cmd log If error occur --- commands/audit/sca/pnpm/pnpm.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/commands/audit/sca/pnpm/pnpm.go b/commands/audit/sca/pnpm/pnpm.go index b2197392..347b4006 100644 --- a/commands/audit/sca/pnpm/pnpm.go +++ b/commands/audit/sca/pnpm/pnpm.go @@ -119,7 +119,10 @@ func installProjectIfNeeded(pnpmExecPath, workingDir string) (dirForDependencies err = fmt.Errorf("failed copying project to temp dir: %w", err) return } - err = getPnpmCmd(pnpmExecPath, dirForDependenciesCalculation, "install", npm.IgnoreScriptsFlag).GetCmd().Run() + output, err := getPnpmCmd(pnpmExecPath, dirForDependenciesCalculation, "install", npm.IgnoreScriptsFlag).GetCmd().CombinedOutput() + if err != nil { + err = fmt.Errorf("failed to install project: %w\n%s", err, string(output)) + } return } From 48377bf3a918eff0f904e97a61a653f0ade74dda Mon Sep 17 00:00:00 2001 From: attiasas Date: Thu, 10 Oct 2024 15:54:26 +0300 Subject: [PATCH 2/7] fix test --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f2d55ea4..d5cfc80a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -51,7 +51,7 @@ jobs: - name: Install dotnet uses: actions/setup-dotnet@v3 with: - dotnet-version: '6.x' + dotnet-version: 6.0.425 - name: Setup Python3 uses: actions/setup-python@v4 with: From a58241e010827930a0db3047ea849e65d3c7844c Mon Sep 17 00:00:00 2001 From: attiasas Date: Sun, 13 Oct 2024 09:09:14 +0300 Subject: [PATCH 3/7] Add option to control the depth of the pnpm dependency tree --- cli/docs/flags.go | 27 +++++++++++++++------------ cli/scancommands.go | 1 + commands/audit/sca/pnpm/pnpm.go | 2 +- utils/auditbasicparams.go | 12 ++++++++++++ 4 files changed, 29 insertions(+), 13 deletions(-) diff --git a/cli/docs/flags.go b/cli/docs/flags.go index bf9643e7..77f4feac 100644 --- a/cli/docs/flags.go +++ b/cli/docs/flags.go @@ -2,9 +2,10 @@ package docs import ( "fmt" - "github.com/jfrog/jfrog-cli-security/commands/git" "strings" + "github.com/jfrog/jfrog-cli-security/commands/git" + "github.com/jfrog/jfrog-cli-core/v2/common/cliutils" pluginsCommon "github.com/jfrog/jfrog-cli-core/v2/plugins/common" "github.com/jfrog/jfrog-cli-core/v2/plugins/components" @@ -114,6 +115,7 @@ const ( useWrapperAudit = auditPrefix + UseWrapper ExcludeTestDeps = "exclude-test-deps" DepType = "dep-type" + MaxTreeDepth = "max-tree-depth" ThirdPartyContextualAnalysis = "third-party-contextual-analysis" RequirementsFile = "requirements-file" WorkingDirs = "working-dirs" @@ -236,17 +238,18 @@ var flagsMap = map[string]components.Flag{ "List of exclusions separated by semicolons, utilized to skip sub-projects from undergoing an audit. These exclusions may incorporate the * and ? wildcards.", components.WithStrDefaultValue(strings.Join(utils.DefaultScaExcludePatterns, ";")), ), - Mvn: components.NewBoolFlag(Mvn, "Set to true to request audit for a Maven project."), - Gradle: components.NewBoolFlag(Gradle, "Set to true to request audit for a Gradle project."), - Npm: components.NewBoolFlag(Npm, "Set to true to request audit for a npm project."), - Pnpm: components.NewBoolFlag(Pnpm, "Set to true to request audit for a Pnpm project."), - Yarn: components.NewBoolFlag(Yarn, "Set to true to request audit for a Yarn project."), - Nuget: components.NewBoolFlag(Nuget, "Set to true to request audit for a .NET project."), - Pip: components.NewBoolFlag(Pip, "Set to true to request audit for a Pip project."), - Pipenv: components.NewBoolFlag(Pipenv, "Set to true to request audit for a Pipenv project."), - Poetry: components.NewBoolFlag(Poetry, "Set to true to request audit for a Poetry project."), - Go: components.NewBoolFlag(Go, "Set to true to request audit for a Go project."), - DepType: components.NewStringFlag(DepType, "[npm] Defines npm dependencies type. Possible values are: all, devOnly and prodOnly."), + Mvn: components.NewBoolFlag(Mvn, "Set to true to request audit for a Maven project."), + Gradle: components.NewBoolFlag(Gradle, "Set to true to request audit for a Gradle project."), + Npm: components.NewBoolFlag(Npm, "Set to true to request audit for a npm project."), + Pnpm: components.NewBoolFlag(Pnpm, "Set to true to request audit for a Pnpm project."), + Yarn: components.NewBoolFlag(Yarn, "Set to true to request audit for a Yarn project."), + Nuget: components.NewBoolFlag(Nuget, "Set to true to request audit for a .NET project."), + Pip: components.NewBoolFlag(Pip, "Set to true to request audit for a Pip project."), + Pipenv: components.NewBoolFlag(Pipenv, "Set to true to request audit for a Pipenv project."), + Poetry: components.NewBoolFlag(Poetry, "Set to true to request audit for a Poetry project."), + Go: components.NewBoolFlag(Go, "Set to true to request audit for a Go project."), + DepType: components.NewStringFlag(DepType, "[npm] Defines npm dependencies type. Possible values are: all, devOnly and prodOnly."), + MaxTreeDepth: components.NewStringFlag(MaxTreeDepth, "[pnpm] Max depth of the generated dependencies tree for SCA scan.", components.WithStrDefaultValue("Infinity")), ThirdPartyContextualAnalysis: components.NewBoolFlag( ThirdPartyContextualAnalysis, "[npm] when set, the Contextual Analysis scan also uses the code of the project dependencies to determine the applicability of the vulnerability.", diff --git a/cli/scancommands.go b/cli/scancommands.go index fcd620e3..9029343f 100644 --- a/cli/scancommands.go +++ b/cli/scancommands.go @@ -494,6 +494,7 @@ func CreateAuditCmd(c *components.Context) (*audit.AuditCommand, error) { SetInsecureTls(c.GetBoolFlagValue(flags.InsecureTls)). SetNpmScope(c.GetStringFlagValue(flags.DepType)). SetPipRequirementsFile(c.GetStringFlagValue(flags.RequirementsFile)). + SetMaxTreeDepth(c.GetStringFlagValue(flags.MaxTreeDepth)). SetExclusions(pluginsCommon.GetStringsArrFlagValue(c, flags.Exclusions)) return auditCmd, err } diff --git a/commands/audit/sca/pnpm/pnpm.go b/commands/audit/sca/pnpm/pnpm.go index 347b4006..5886f195 100644 --- a/commands/audit/sca/pnpm/pnpm.go +++ b/commands/audit/sca/pnpm/pnpm.go @@ -128,7 +128,7 @@ func installProjectIfNeeded(pnpmExecPath, workingDir string) (dirForDependencies // Run 'pnpm ls ...' command (project must be installed) and parse the returned result to create a dependencies trees for the projects. func calculateDependencies(executablePath, workingDir string, params utils.AuditParams) (dependencyTrees []*xrayUtils.GraphNode, uniqueDeps []string, err error) { - lsArgs := append([]string{"--depth", "Infinity", "--json", "--long"}, params.Args()...) + lsArgs := append([]string{"--depth", params.MaxTreeDepth(), "--json", "--long"}, params.Args()...) npmLsCmdContent, err := getPnpmCmd(executablePath, workingDir, "ls", lsArgs...).RunWithOutput() if err != nil { return diff --git a/utils/auditbasicparams.go b/utils/auditbasicparams.go index df3a23fd..d906ad58 100644 --- a/utils/auditbasicparams.go +++ b/utils/auditbasicparams.go @@ -27,6 +27,8 @@ type AuditParams interface { InstallCommandName() string InstallCommandArgs() []string SetNpmScope(depType string) *AuditBasicParams + SetMaxTreeDepth(maxTreeDepth string) *AuditBasicParams + MaxTreeDepth() string OutputFormat() format.OutputFormat DepsRepo() string SetDepsRepo(depsRepo string) *AuditBasicParams @@ -53,6 +55,7 @@ type AuditBasicParams struct { ignoreConfigFile bool isMavenDepTreeInstalled bool isCurationCmd bool + maxTreeDepth string pipRequirementsFile string depsRepo string installCommandName string @@ -102,6 +105,15 @@ func (abp *AuditBasicParams) UseJas() bool { return abp.useJas } +func (abp *AuditBasicParams) MaxTreeDepth() string { + return abp.maxTreeDepth +} + +func (abp *AuditBasicParams) SetMaxTreeDepth(maxTreeDepth string) *AuditBasicParams { + abp.maxTreeDepth = maxTreeDepth + return abp +} + func (abp *AuditBasicParams) PipRequirementsFile() string { return abp.pipRequirementsFile } From 7f5ed22f2f38511ee7cc58be6100283cc582a607 Mon Sep 17 00:00:00 2001 From: attiasas Date: Mon, 14 Oct 2024 13:48:42 +0300 Subject: [PATCH 4/7] CR change --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d5cfc80a..30f906df 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -47,11 +47,11 @@ jobs: - name: Install NuGet uses: nuget/setup-nuget@v2 with: - nuget-version: 6.11.0 + nuget-version: 6.x - name: Install dotnet uses: actions/setup-dotnet@v3 with: - dotnet-version: 6.0.425 + dotnet-version: '6.x' - name: Setup Python3 uses: actions/setup-python@v4 with: From 01eebd0355a7eb970bc0929aafc13cdeb857072d Mon Sep 17 00:00:00 2001 From: attiasas Date: Sun, 1 Dec 2024 11:41:04 +0200 Subject: [PATCH 5/7] add tests --- commands/audit/sca/pnpm/pnpm.go | 1 + commands/audit/sca/pnpm/pnpm_test.go | 65 ++++++++++++++++++- .../npm/npm-big-tree/package.json | 20 ++++++ 3 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 tests/testdata/projects/package-managers/npm/npm-big-tree/package.json diff --git a/commands/audit/sca/pnpm/pnpm.go b/commands/audit/sca/pnpm/pnpm.go index 2e0395f2..54e15dcb 100644 --- a/commands/audit/sca/pnpm/pnpm.go +++ b/commands/audit/sca/pnpm/pnpm.go @@ -133,6 +133,7 @@ func installProjectIfNeeded(pnpmExecPath, workingDir string) (dirForDependencies // Run 'pnpm ls ...' command (project must be installed) and parse the returned result to create a dependencies trees for the projects. func calculateDependencies(executablePath, workingDir string, params utils.AuditParams) (dependencyTrees []*xrayUtils.GraphNode, uniqueDeps []string, err error) { lsArgs := append([]string{"--depth", params.MaxTreeDepth(), "--json", "--long"}, params.Args()...) + log.Debug("Running Pnpm ls command with args:", lsArgs) npmLsCmdContent, err := getPnpmCmd(executablePath, workingDir, "ls", lsArgs...).RunWithOutput() if err != nil { return diff --git a/commands/audit/sca/pnpm/pnpm_test.go b/commands/audit/sca/pnpm/pnpm_test.go index e04ba84f..42ab230b 100644 --- a/commands/audit/sca/pnpm/pnpm_test.go +++ b/commands/audit/sca/pnpm/pnpm_test.go @@ -1,11 +1,14 @@ package pnpm import ( - "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" - "github.com/jfrog/jfrog-client-go/utils/io/fileutils" + "fmt" "path/filepath" "testing" + "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" + "github.com/jfrog/jfrog-client-go/utils/io/fileutils" + "github.com/jfrog/jfrog-client-go/utils/log" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -16,6 +19,64 @@ import ( "github.com/jfrog/jfrog-cli-security/utils" ) +func TestBuildDependencyTreeLimitedDepth(t *testing.T) { + // Create and change directory to test workspace + _, cleanUp := sca.CreateTestWorkspace(t, filepath.Join("projects", "package-managers", "npm", "npm-big-tree")) + defer cleanUp() + testCases := []struct { + name string + treeDepth string + expectedUniqueDeps []string + expectedTree *xrayUtils.GraphNode + }{ + { + name: "Only direct dependencies", + treeDepth: "0", + expectedUniqueDeps: []string{ + "npm://zen-website:1.0.0", + "npm://balaganjs:1.0.0", + }, + expectedTree: &xrayUtils.GraphNode{ + Id: "npm://zen-website:1.0.0", + Nodes: []*xrayUtils.GraphNode{{Id: "npm://balaganjs:1.0.0"}}, + }, + }, + { + name: "With transitive dependencies", + treeDepth: "1", + expectedUniqueDeps: []string{ + "npm://zen-website:1.0.0", + "npm://balaganjs:1.0.0", + "npm://axios:1.7.8", + }, + expectedTree: &xrayUtils.GraphNode{ + Id: "npm://zen-website:1.0.0", + Nodes: []*xrayUtils.GraphNode{{Id: "npm://balaganjs:1.0.0", Nodes: []*xrayUtils.GraphNode{{Id: "npm://axios:1.7.8"}}}}, + }, + }, + } + + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + // Build dependency tree + params := &utils.AuditBasicParams{} + rootNode, uniqueDeps, err := BuildDependencyTree(params.SetMaxTreeDepth(testCase.treeDepth)) + require.NoError(t, err) + // Validations + assert.ElementsMatch(t, uniqueDeps, testCase.expectedUniqueDeps, "First is actual, Second is Expected") + if assert.Len(t, rootNode, 1) { + assert.Equal(t, rootNode[0].Id, testCase.expectedTree.Id) + if !tests.CompareTree(testCase.expectedTree, rootNode[0]) { + str, err := utils.GetAsJsonString(rootNode[0], true, true) + assert.NoError(t, err) + log.Info(str) + t.Error(fmt.Sprintf("expected: %v got: %v", testCase.expectedTree.Nodes, rootNode[0].Nodes)) + } + } + }) + } +} + func TestBuildDependencyTree(t *testing.T) { // Create and change directory to test workspace _, cleanUp := sca.CreateTestWorkspace(t, filepath.Join("projects", "package-managers", "npm", "npm-no-lock")) diff --git a/tests/testdata/projects/package-managers/npm/npm-big-tree/package.json b/tests/testdata/projects/package-managers/npm/npm-big-tree/package.json new file mode 100644 index 00000000..f632961f --- /dev/null +++ b/tests/testdata/projects/package-managers/npm/npm-big-tree/package.json @@ -0,0 +1,20 @@ +{ + "name": "zen-website", + "version": "1.0.0", + "description": "", + "main": "index.js", + "publishConfig": { + "registry": "http://artifactory-unified.soleng-us.jfrog.team/artifactory/api/npm/npm/" + }, + "scripts": { + "dev": "nodemon ./index.js", + "ui": "browser-sync start --config bs-config.js" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "balaganjs": "1.0.0" + } + } + \ No newline at end of file From 6013d9f4256563402e789a83bff43841cb39e693 Mon Sep 17 00:00:00 2001 From: attiasas Date: Sun, 1 Dec 2024 12:11:11 +0200 Subject: [PATCH 6/7] fix bug --- commands/audit/sca/pnpm/pnpm.go | 24 ++++++---------- commands/audit/sca/pnpm/pnpm_test.go | 41 ++++++++++++++-------------- 2 files changed, 29 insertions(+), 36 deletions(-) diff --git a/commands/audit/sca/pnpm/pnpm.go b/commands/audit/sca/pnpm/pnpm.go index 54e15dcb..b6edca23 100644 --- a/commands/audit/sca/pnpm/pnpm.go +++ b/commands/audit/sca/pnpm/pnpm.go @@ -10,9 +10,6 @@ import ( "github.com/jfrog/gofrog/datastructures" "github.com/jfrog/gofrog/io" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" - "golang.org/x/exp/maps" - "golang.org/x/exp/slices" - "github.com/jfrog/jfrog-cli-security/commands/audit/sca" "github.com/jfrog/jfrog-cli-security/commands/audit/sca/npm" "github.com/jfrog/jfrog-cli-security/utils" @@ -21,6 +18,7 @@ import ( "github.com/jfrog/jfrog-client-go/utils/errorutils" "github.com/jfrog/jfrog-client-go/utils/io/fileutils" "github.com/jfrog/jfrog-client-go/utils/log" + "golang.org/x/exp/maps" biutils "github.com/jfrog/build-info-go/utils" xrayUtils "github.com/jfrog/jfrog-client-go/xray/services/utils" @@ -167,13 +165,13 @@ func createProjectDependenciesTree(project pnpmLsProject) map[string]xray.DepTre for depName, dependency := range project.Dependencies { directDependency := getDependencyId(depName, dependency.Version) directDependencies = append(directDependencies, directDependency) - appendTransitiveDependencies(directDependency, dependency.Dependencies, treeMap) + appendTransitiveDependencies(directDependency, dependency.Dependencies, &treeMap) } // Handle dev-dependencies for depName, dependency := range project.DevDependencies { directDependency := getDependencyId(depName, dependency.Version) directDependencies = append(directDependencies, directDependency) - appendTransitiveDependencies(directDependency, dependency.Dependencies, treeMap) + appendTransitiveDependencies(directDependency, dependency.Dependencies, &treeMap) } if len(directDependencies) > 0 { treeMap[getDependencyId(project.Name, project.Version)] = xray.DepTreeNode{Children: directDependencies} @@ -186,21 +184,15 @@ func getDependencyId(depName, version string) string { return techutils.Npm.GetPackageTypeId() + depName + ":" + version } -func appendTransitiveDependencies(parent string, dependencies map[string]pnpmLsDependency, result map[string]xray.DepTreeNode) { +func appendTransitiveDependencies(parent string, dependencies map[string]pnpmLsDependency, result *map[string]xray.DepTreeNode) { for depName, dependency := range dependencies { dependencyId := getDependencyId(depName, dependency.Version) - if node, ok := result[parent]; ok { - node.Children = appendUniqueChild(node.Children, dependencyId) + if node, ok := (*result)[parent]; ok { + node.Children = append(node.Children, dependencyId) + (*result)[parent] = node } else { - result[parent] = xray.DepTreeNode{Children: []string{dependencyId}} + (*result)[parent] = xray.DepTreeNode{Children: []string{dependencyId}} } appendTransitiveDependencies(dependencyId, dependency.Dependencies, result) } } - -func appendUniqueChild(children []string, candidateDependency string) []string { - if slices.Contains(children, candidateDependency) { - return children - } - return append(children, candidateDependency) -} diff --git a/commands/audit/sca/pnpm/pnpm_test.go b/commands/audit/sca/pnpm/pnpm_test.go index 42ab230b..b0865dd3 100644 --- a/commands/audit/sca/pnpm/pnpm_test.go +++ b/commands/audit/sca/pnpm/pnpm_test.go @@ -1,13 +1,11 @@ package pnpm import ( - "fmt" "path/filepath" "testing" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" "github.com/jfrog/jfrog-client-go/utils/io/fileutils" - "github.com/jfrog/jfrog-client-go/utils/log" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -29,18 +27,18 @@ func TestBuildDependencyTreeLimitedDepth(t *testing.T) { expectedUniqueDeps []string expectedTree *xrayUtils.GraphNode }{ - { - name: "Only direct dependencies", - treeDepth: "0", - expectedUniqueDeps: []string{ - "npm://zen-website:1.0.0", - "npm://balaganjs:1.0.0", - }, - expectedTree: &xrayUtils.GraphNode{ - Id: "npm://zen-website:1.0.0", - Nodes: []*xrayUtils.GraphNode{{Id: "npm://balaganjs:1.0.0"}}, - }, - }, + // { + // name: "Only direct dependencies", + // treeDepth: "0", + // expectedUniqueDeps: []string{ + // "npm://zen-website:1.0.0", + // "npm://balaganjs:1.0.0", + // }, + // expectedTree: &xrayUtils.GraphNode{ + // Id: "npm://zen-website:1.0.0", + // Nodes: []*xrayUtils.GraphNode{{Id: "npm://balaganjs:1.0.0"}}, + // }, + // }, { name: "With transitive dependencies", treeDepth: "1", @@ -48,10 +46,16 @@ func TestBuildDependencyTreeLimitedDepth(t *testing.T) { "npm://zen-website:1.0.0", "npm://balaganjs:1.0.0", "npm://axios:1.7.8", + "npm://yargs:13.3.0", }, expectedTree: &xrayUtils.GraphNode{ - Id: "npm://zen-website:1.0.0", - Nodes: []*xrayUtils.GraphNode{{Id: "npm://balaganjs:1.0.0", Nodes: []*xrayUtils.GraphNode{{Id: "npm://axios:1.7.8"}}}}, + Id: "npm://zen-website:1.0.0", + Nodes: []*xrayUtils.GraphNode{ + { + Id: "npm://balaganjs:1.0.0", + Nodes: []*xrayUtils.GraphNode{{Id: "npm://axios:1.7.8"}, {Id: "npm://yargs:13.3.0"}}, + }, + }, }, }, } @@ -67,10 +71,7 @@ func TestBuildDependencyTreeLimitedDepth(t *testing.T) { if assert.Len(t, rootNode, 1) { assert.Equal(t, rootNode[0].Id, testCase.expectedTree.Id) if !tests.CompareTree(testCase.expectedTree, rootNode[0]) { - str, err := utils.GetAsJsonString(rootNode[0], true, true) - assert.NoError(t, err) - log.Info(str) - t.Error(fmt.Sprintf("expected: %v got: %v", testCase.expectedTree.Nodes, rootNode[0].Nodes)) + t.Error("expected:", testCase.expectedTree.Nodes, "got:", rootNode[0].Nodes) } } }) From 7eaa9133b9c4ee5ca14702fd8e10b688c35f7d87 Mon Sep 17 00:00:00 2001 From: attiasas Date: Sun, 15 Dec 2024 11:32:20 +0200 Subject: [PATCH 7/7] fix tests --- commands/audit/sca/pnpm/pnpm_test.go | 34 ++++++++++++++++------------ 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/commands/audit/sca/pnpm/pnpm_test.go b/commands/audit/sca/pnpm/pnpm_test.go index b0865dd3..dad31f7e 100644 --- a/commands/audit/sca/pnpm/pnpm_test.go +++ b/commands/audit/sca/pnpm/pnpm_test.go @@ -2,6 +2,7 @@ package pnpm import ( "path/filepath" + "sort" "testing" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" @@ -27,33 +28,33 @@ func TestBuildDependencyTreeLimitedDepth(t *testing.T) { expectedUniqueDeps []string expectedTree *xrayUtils.GraphNode }{ - // { - // name: "Only direct dependencies", - // treeDepth: "0", - // expectedUniqueDeps: []string{ - // "npm://zen-website:1.0.0", - // "npm://balaganjs:1.0.0", - // }, - // expectedTree: &xrayUtils.GraphNode{ - // Id: "npm://zen-website:1.0.0", - // Nodes: []*xrayUtils.GraphNode{{Id: "npm://balaganjs:1.0.0"}}, - // }, - // }, + { + name: "Only direct dependencies", + treeDepth: "0", + expectedUniqueDeps: []string{ + "npm://zen-website:1.0.0", + "npm://balaganjs:1.0.0", + }, + expectedTree: &xrayUtils.GraphNode{ + Id: "npm://zen-website:1.0.0", + Nodes: []*xrayUtils.GraphNode{{Id: "npm://balaganjs:1.0.0"}}, + }, + }, { name: "With transitive dependencies", treeDepth: "1", expectedUniqueDeps: []string{ - "npm://zen-website:1.0.0", + "npm://axios:1.7.9", "npm://balaganjs:1.0.0", - "npm://axios:1.7.8", "npm://yargs:13.3.0", + "npm://zen-website:1.0.0", }, expectedTree: &xrayUtils.GraphNode{ Id: "npm://zen-website:1.0.0", Nodes: []*xrayUtils.GraphNode{ { Id: "npm://balaganjs:1.0.0", - Nodes: []*xrayUtils.GraphNode{{Id: "npm://axios:1.7.8"}, {Id: "npm://yargs:13.3.0"}}, + Nodes: []*xrayUtils.GraphNode{{Id: "npm://axios:1.7.9"}, {Id: "npm://yargs:13.3.0"}}, }, }, }, @@ -66,6 +67,9 @@ func TestBuildDependencyTreeLimitedDepth(t *testing.T) { params := &utils.AuditBasicParams{} rootNode, uniqueDeps, err := BuildDependencyTree(params.SetMaxTreeDepth(testCase.treeDepth)) require.NoError(t, err) + sort.Slice(uniqueDeps, func(i, j int) bool { + return uniqueDeps[i] < uniqueDeps[j] + }) // Validations assert.ElementsMatch(t, uniqueDeps, testCase.expectedUniqueDeps, "First is actual, Second is Expected") if assert.Len(t, rootNode, 1) {