@@ -28,7 +28,8 @@ func TestUVClient_ExportSBOM_Success(t *testing.T) {
2828 "component": {
2929 "type": "library",
3030 "bom-ref": "test-project-1",
31- "name": "test-project"
31+ "name": "test-project",
32+ "version": "1.2.3"
3233 }
3334 }
3435 }`
@@ -46,7 +47,11 @@ func TestUVClient_ExportSBOM_Success(t *testing.T) {
4647 result , err := client .ExportSBOM ("/test/dir" )
4748
4849 assert .NoError (t , err )
50+ require .NotNil (t , result )
4951 assert .JSONEq (t , validSBOM , string (result .Sbom ))
52+ assert .Equal (t , "pip" , result .Metadata .PackageManager )
53+ assert .Equal (t , "test-project" , result .Metadata .Name )
54+ assert .Equal (t , "1.2.3" , result .Metadata .Version )
5055}
5156
5257func TestUVClient_ExportSBOM_Error (t * testing.T ) {
@@ -159,47 +164,106 @@ func TestParseAndValidateVersion_UnparseableOutput(t *testing.T) {
159164
160165func TestValidateSBOM_Success (t * testing.T ) {
161166 tests := []struct {
162- name string
163- sbom string
167+ name string
168+ sbom string
169+ expectedName string
170+ expectedVersion string
164171 }{
165172 {
166- name : "valid SBOM with component" ,
173+ name : "valid SBOM with full component" ,
167174 sbom : `{
168175 "bomFormat": "CycloneDX",
169176 "specVersion": "1.5",
170177 "metadata": {
171178 "component": {
172179 "type": "library",
173180 "name": "test-project",
181+ "version": "1.0.0",
174182 "bom-ref": "test-project-1"
175183 }
176184 }
177185 }` ,
186+ expectedName : "test-project" ,
187+ expectedVersion : "1.0.0" ,
178188 },
179189 {
180190 name : "valid SBOM with minimal component" ,
181191 sbom : `{
182192 "metadata": {
183193 "component": {
184- "name": "my-project"
194+ "name": "my-project",
195+ "version": "0.1.0"
185196 }
186197 }
187198 }` ,
199+ expectedName : "my-project" ,
200+ expectedVersion : "0.1.0" ,
201+ },
202+ {
203+ name : "component without version" ,
204+ sbom : `{
205+ "bomFormat": "CycloneDX",
206+ "specVersion": "1.5",
207+ "metadata": {
208+ "component": {
209+ "name": "project-no-version"
210+ }
211+ }
212+ }` ,
213+ expectedName : "project-no-version" ,
214+ expectedVersion : "" ,
215+ },
216+ {
217+ name : "component with empty version string" ,
218+ sbom : `{
219+ "metadata": {
220+ "component": {
221+ "name": "project-empty-version",
222+ "version": ""
223+ }
224+ }
225+ }` ,
226+ expectedName : "project-empty-version" ,
227+ expectedVersion : "" ,
228+ },
229+ {
230+ name : "component with additional fields" ,
231+ sbom : `{
232+ "bomFormat": "CycloneDX",
233+ "specVersion": "1.5",
234+ "metadata": {
235+ "component": {
236+ "type": "application",
237+ "name": "complex-project",
238+ "version": "3.0.0",
239+ "bom-ref": "pkg:pypi/[email protected] ", 240+ "description": "A complex project",
241+ "licenses": []
242+ }
243+ }
244+ }` ,
245+ expectedName : "complex-project" ,
246+ expectedVersion : "3.0.0" ,
188247 },
189248 }
190249
191250 for _ , tt := range tests {
192251 t .Run (tt .name , func (t * testing.T ) {
193- err := validateSBOM ([]byte (tt .sbom ))
252+ metadata , err := validateSBOM ([]byte (tt .sbom ))
194253 assert .NoError (t , err )
254+ require .NotNil (t , metadata )
255+ assert .Equal (t , "pip" , metadata .PackageManager )
256+ assert .Equal (t , tt .expectedName , metadata .Name )
257+ assert .Equal (t , tt .expectedVersion , metadata .Version )
195258 })
196259 }
197260}
198261
199262func TestValidateSBOM_MissingComponent (t * testing.T ) {
200263 tests := []struct {
201- name string
202- sbom string
264+ name string
265+ sbom string
266+ expectedErrMessage string
203267 }{
204268 {
205269 name : "missing component field" ,
@@ -210,29 +274,47 @@ func TestValidateSBOM_MissingComponent(t *testing.T) {
210274 "timestamp": "2025-11-17T16:20:47.525804000Z"
211275 }
212276 }` ,
277+ expectedErrMessage : "SBOM missing root component at metadata.component" ,
213278 },
214279 {
215280 name : "missing metadata" ,
216281 sbom : `{
217282 "bomFormat": "CycloneDX",
218283 "specVersion": "1.5"
219284 }` ,
285+ expectedErrMessage : "SBOM missing root component at metadata.component" ,
286+ },
287+ {
288+ name : "component with empty name" ,
289+ sbom : `{
290+ "bomFormat": "CycloneDX",
291+ "specVersion": "1.5",
292+ "metadata": {
293+ "component": {
294+ "name": "",
295+ "version": "1.0.0"
296+ }
297+ }
298+ }` ,
299+ expectedErrMessage : "SBOM root component missing name" ,
220300 },
221301 }
222302
223303 for _ , tt := range tests {
224304 t .Run (tt .name , func (t * testing.T ) {
225- err := validateSBOM ([]byte (tt .sbom ))
305+ metadata , err := validateSBOM ([]byte (tt .sbom ))
306+ assert .Nil (t , metadata )
226307 require .Error (t , err )
227308 var catalogErr snyk_errors.Error
228309 assert .True (t , errors .As (err , & catalogErr ), "error should be a catalog error" )
229- assert .Contains (t , catalogErr .Detail , "SBOM missing root component at metadata.component" )
310+ assert .Contains (t , catalogErr .Detail , tt . expectedErrMessage )
230311 })
231312 }
232313}
233314
234315func TestValidateSBOM_InvalidJSON (t * testing.T ) {
235- err := validateSBOM ([]byte ("invalid json" ))
316+ metadata , err := validateSBOM ([]byte ("invalid json" ))
317+ assert .Nil (t , metadata )
236318 require .Error (t , err )
237319 var catalogErr snyk_errors.Error
238320 assert .True (t , errors .As (err , & catalogErr ), "error should be a catalog error" )
0 commit comments