github.com/ouraigua/jenkins-library@v0.0.0-20231028010029-fbeaf2f3aa9b/pkg/whitesource/scanNPM_test.go (about) 1 //go:build unit 2 // +build unit 3 4 package whitesource 5 6 import ( 7 "encoding/json" 8 "fmt" 9 "path/filepath" 10 "testing" 11 12 "github.com/SAP/jenkins-library/pkg/mock" 13 "github.com/stretchr/testify/assert" 14 "github.com/stretchr/testify/require" 15 ) 16 17 func TestExecuteScanNPM(t *testing.T) { 18 config := ScanOptions{ 19 ScanType: "npm", 20 OrgToken: "org-token", 21 UserToken: "user-token", 22 ProductName: "mock-product", 23 ProjectName: "mock-project", 24 } 25 26 t.Parallel() 27 28 t.Run("happy path NPM", func(t *testing.T) { 29 // init 30 utilsMock := NewScanUtilsMock() 31 utilsMock.AddFile("package.json", []byte(`{"name":"my-module-name"}`)) 32 scan := newTestScan(&config) 33 // test 34 err := scan.ExecuteNpmScan(&config, utilsMock) 35 // assert 36 require.NoError(t, err) 37 expectedCalls := []mock.ExecCall{ 38 { 39 Exec: "npm", 40 Params: []string{ 41 "ls", 42 }, 43 }, 44 { 45 Exec: "npx", 46 Params: []string{ 47 "whitesource", 48 "run", 49 }, 50 }, 51 } 52 assert.Equal(t, expectedCalls, utilsMock.Calls) 53 assert.True(t, utilsMock.HasWrittenFile(whiteSourceConfig)) 54 assert.True(t, utilsMock.HasRemovedFile(whiteSourceConfig)) 55 }) 56 t.Run("happy path with excluded modules", func(t *testing.T) { 57 // init 58 utilsMock := NewScanUtilsMock() 59 utilsMock.AddFile("package.json", []byte(`{"name":"my-module-name"}`)) 60 utilsMock.AddFile("sub/package.json", []byte(`{"name":"my-sub-module-name"}`)) 61 utilsMock.AddFile("deep/sub/package.json", []byte(`{"name":"my-deep-sub-module-name"}`)) 62 63 config := ScanOptions{ 64 ScanType: "npm", 65 OrgToken: "org-token", 66 UserToken: "user-token", 67 ProductName: "mock-product", 68 ProjectName: "mock-project", 69 BuildDescriptorExcludeList: []string{"unrelated/pom.xml", "sub/package.json", "deep/sub/package.json"}, 70 } 71 72 scan := newTestScan(&config) 73 // test 74 err := scan.ExecuteNpmScan(&config, utilsMock) 75 // assert 76 require.NoError(t, err) 77 expectedCalls := []mock.ExecCall{ 78 { 79 Exec: "npm", 80 Params: []string{ 81 "ls", 82 }, 83 }, 84 { 85 Exec: "npx", 86 Params: []string{ 87 "whitesource", 88 "run", 89 }, 90 }, 91 } 92 assert.Equal(t, expectedCalls, utilsMock.Calls) 93 assert.True(t, utilsMock.HasWrittenFile(whiteSourceConfig)) 94 assert.True(t, utilsMock.HasRemovedFile(whiteSourceConfig)) 95 assert.False(t, utilsMock.HasWrittenFile(filepath.Join("sub", whiteSourceConfig))) 96 assert.False(t, utilsMock.HasWrittenFile(filepath.Join("deep", "sub", whiteSourceConfig))) 97 }) 98 t.Run("no NPM modules", func(t *testing.T) { 99 // init 100 utilsMock := NewScanUtilsMock() 101 scan := newTestScan(&config) 102 // test 103 err := scan.ExecuteNpmScan(&config, utilsMock) 104 // assert 105 assert.EqualError(t, err, "found no NPM modules to scan. Configured excludes: []") 106 assert.Len(t, utilsMock.Calls, 0) 107 assert.False(t, utilsMock.HasWrittenFile(whiteSourceConfig)) 108 }) 109 t.Run("package.json needs name", func(t *testing.T) { 110 // init 111 utilsMock := NewScanUtilsMock() 112 utilsMock.AddFile("package.json", []byte(`{"key":"value"}`)) 113 scan := newTestScan(&config) 114 // test 115 err := scan.ExecuteNpmScan(&config, utilsMock) 116 // assert 117 assert.EqualError(t, err, "failed to scan NPM module 'package.json': the file 'package.json' must configure a name") 118 }) 119 t.Run("npm ls fails", func(t *testing.T) { 120 // init 121 utilsMock := NewScanUtilsMock() 122 utilsMock.AddFile("package.json", []byte(`{"name":"my-module-name"}`)) 123 utilsMock.AddFile(filepath.Join("app", "package.json"), []byte(`{"name":"my-app-module-name"}`)) 124 utilsMock.AddFile("package-lock.json", []byte("dummy")) 125 126 utilsMock.ShouldFailOnCommand = make(map[string]error) 127 utilsMock.ShouldFailOnCommand["npm ls"] = fmt.Errorf("mock failure") 128 scan := newTestScan(&config) 129 // test 130 err := scan.ExecuteNpmScan(&config, utilsMock) 131 // assert 132 assert.NoError(t, err) 133 expectedNpmInstalls := []NpmInstall{ 134 {CurrentDir: "app", PackageJSON: []string{"package.json"}}, 135 {CurrentDir: "", PackageJSON: []string{"package.json"}}, 136 } 137 assert.Equal(t, expectedNpmInstalls, utilsMock.NpmInstalledModules) 138 assert.True(t, utilsMock.HasRemovedFile("package-lock.json")) 139 }) 140 } 141 142 func TestWriteWhitesourceConfigJSON(t *testing.T) { 143 config := &ScanOptions{ 144 OrgToken: "org-token", 145 UserToken: "user-token", 146 ProductName: "mock-product", 147 ProductVersion: "product-version", 148 ProjectName: "mock-project", 149 ProductToken: "mock-product-token", 150 } 151 152 expected := make(map[string]interface{}) 153 expected["apiKey"] = "org-token" 154 expected["userKey"] = "user-token" 155 expected["checkPolicies"] = true 156 expected["forceUpdate"] = true 157 expected["productName"] = "mock-product" 158 expected["projectName"] = "mock-project" 159 expected["productToken"] = "mock-product-token" 160 expected["productVer"] = "product-version" 161 expected["devDep"] = true 162 expected["ignoreNpmLsErrors"] = true 163 164 t.Parallel() 165 166 t.Run("write config from scratch", func(t *testing.T) { 167 // init 168 utils := NewScanUtilsMock() 169 scan := newTestScan(config) 170 // test 171 err := scan.writeWhitesourceConfigJSON(config, utils, true, true) 172 // assert 173 if assert.NoError(t, err) && assert.True(t, utils.HasWrittenFile(whiteSourceConfig)) { 174 contents, _ := utils.FileRead(whiteSourceConfig) 175 actual := make(map[string]interface{}) 176 _ = json.Unmarshal(contents, &actual) 177 assert.Equal(t, expected, actual) 178 } 179 }) 180 181 t.Run("extend and merge config", func(t *testing.T) { 182 // init 183 initial := make(map[string]interface{}) 184 initial["checkPolicies"] = false 185 initial["productName"] = "mock-product" 186 initial["productVer"] = "41" 187 initial["unknown"] = "preserved" 188 encoded, _ := json.Marshal(initial) 189 190 utils := NewScanUtilsMock() 191 utils.AddFile(whiteSourceConfig, encoded) 192 193 scan := newTestScan(config) 194 195 // test 196 err := scan.writeWhitesourceConfigJSON(config, utils, true, true) 197 // assert 198 if assert.NoError(t, err) && assert.True(t, utils.HasWrittenFile(whiteSourceConfig)) { 199 contents, _ := utils.FileRead(whiteSourceConfig) 200 actual := make(map[string]interface{}) 201 _ = json.Unmarshal(contents, &actual) 202 203 mergedExpected := expected 204 mergedExpected["unknown"] = "preserved" 205 206 assert.Equal(t, mergedExpected, actual) 207 } 208 }) 209 210 t.Run("extend and merge config, omit productToken", func(t *testing.T) { 211 // init 212 initial := make(map[string]interface{}) 213 initial["checkPolicies"] = false 214 initial["productName"] = "mock-product" 215 initial["productVer"] = "41" 216 initial["unknown"] = "preserved" 217 initial["projectToken"] = "mock-project-token" 218 encoded, _ := json.Marshal(initial) 219 220 utils := NewScanUtilsMock() 221 utils.AddFile(whiteSourceConfig, encoded) 222 223 scan := newTestScan(config) 224 225 // test 226 err := scan.writeWhitesourceConfigJSON(config, utils, true, true) 227 // assert 228 if assert.NoError(t, err) && assert.True(t, utils.HasWrittenFile(whiteSourceConfig)) { 229 contents, _ := utils.FileRead(whiteSourceConfig) 230 actual := make(map[string]interface{}) 231 _ = json.Unmarshal(contents, &actual) 232 233 mergedExpected := expected 234 mergedExpected["unknown"] = "preserved" 235 mergedExpected["projectToken"] = "mock-project-token" 236 delete(mergedExpected, "productToken") 237 238 assert.Equal(t, mergedExpected, actual) 239 } 240 }) 241 }