@@ -3417,3 +3417,151 @@ def test_product_portfolio_vulnerability_analysis_form_view(self):
34173417 self .assertEqual (product_package , analysis .product_package )
34183418 self .assertEqual (vulnerability1 , analysis .vulnerability )
34193419 self .assertEqual ("resolved" , analysis .state )
3420+
3421+ def test_product_portfolio_tab_compliance_view_empty (self ):
3422+ self .client .login (username = "nexb_user" , password = "secret" )
3423+ url = self .product1 .get_url ("tab_compliance" )
3424+ response = self .client .get (url )
3425+ self .assertEqual (200 , response .status_code )
3426+ self .assertEqual (0 , response .context ["total_packages" ])
3427+ self .assertEqual (100 , response .context ["license_compliance_pct" ])
3428+ self .assertEqual (100 , response .context ["license_coverage_pct" ])
3429+ self .assertEqual (0 , response .context ["vulnerability_count" ])
3430+
3431+ def test_product_portfolio_tab_compliance_view_package_compliance (self ):
3432+ self .client .login (username = "nexb_user" , password = "secret" )
3433+
3434+ owner1 = Owner .objects .create (name = "Owner1" , dataspace = self .dataspace )
3435+ license1 = License .objects .create (
3436+ key = "l1" , name = "L1" , short_name = "L1" , owner = owner1 , dataspace = self .dataspace
3437+ )
3438+ package_policy = UsagePolicy .objects .create (
3439+ label = "PackagePolicy" ,
3440+ icon = "icon" ,
3441+ content_type = ContentType .objects .get_for_model (Package ),
3442+ compliance_alert = UsagePolicy .Compliance .ERROR ,
3443+ dataspace = self .dataspace ,
3444+ )
3445+
3446+ package2 = make_package (self .dataspace , usage_policy = package_policy )
3447+ package3 = make_package (self .dataspace )
3448+
3449+ # package2 has a policy issue, package3 does not
3450+ ProductPackage .objects .create (
3451+ product = self .product1 ,
3452+ package = package2 ,
3453+ dataspace = self .dataspace ,
3454+ license_expression = license1 .key ,
3455+ )
3456+ ProductPackage .objects .create (
3457+ product = self .product1 ,
3458+ package = package3 ,
3459+ dataspace = self .dataspace ,
3460+ )
3461+
3462+ url = self .product1 .get_url ("tab_compliance" )
3463+ response = self .client .get (url )
3464+ self .assertEqual (2 , response .context ["total_packages" ])
3465+ self .assertEqual (1 , response .context ["package_issues_count" ])
3466+ # One package without license expression
3467+ self .assertEqual (1 , response .context ["package_without_license_count" ])
3468+ self .assertEqual (50 , response .context ["license_coverage_pct" ])
3469+
3470+ def test_product_portfolio_tab_compliance_view_license_compliance (self ):
3471+ self .client .login (username = "nexb_user" , password = "secret" )
3472+
3473+ owner1 = Owner .objects .create (name = "Owner1" , dataspace = self .dataspace )
3474+ license_policy_error = UsagePolicy .objects .create (
3475+ label = "LicensePolicyError" ,
3476+ icon = "icon" ,
3477+ content_type = ContentType .objects .get_for_model (License ),
3478+ compliance_alert = UsagePolicy .Compliance .ERROR ,
3479+ dataspace = self .dataspace ,
3480+ )
3481+ license_policy_warning = UsagePolicy .objects .create (
3482+ label = "LicensePolicyWarning" ,
3483+ icon = "icon" ,
3484+ content_type = ContentType .objects .get_for_model (License ),
3485+ compliance_alert = UsagePolicy .Compliance .WARNING ,
3486+ dataspace = self .dataspace ,
3487+ )
3488+ license1 = License .objects .create (
3489+ key = "l1" ,
3490+ name = "L1" ,
3491+ short_name = "L1" ,
3492+ owner = owner1 ,
3493+ usage_policy = license_policy_error ,
3494+ dataspace = self .dataspace ,
3495+ )
3496+ license2 = License .objects .create (
3497+ key = "l2" ,
3498+ name = "L2" ,
3499+ short_name = "L2" ,
3500+ owner = owner1 ,
3501+ usage_policy = license_policy_warning ,
3502+ dataspace = self .dataspace ,
3503+ )
3504+
3505+ package2 = make_package (self .dataspace )
3506+ package3 = make_package (self .dataspace )
3507+ ProductPackage .objects .create (
3508+ product = self .product1 ,
3509+ package = package2 ,
3510+ dataspace = self .dataspace ,
3511+ license_expression = license1 .key ,
3512+ )
3513+ ProductPackage .objects .create (
3514+ product = self .product1 ,
3515+ package = package3 ,
3516+ dataspace = self .dataspace ,
3517+ license_expression = license2 .key ,
3518+ )
3519+
3520+ url = self .product1 .get_url ("tab_compliance" )
3521+ response = self .client .get (url )
3522+ self .assertEqual (2 , response .context ["license_issues_count" ])
3523+ self .assertEqual (1 , response .context ["license_error_count" ])
3524+ self .assertEqual (1 , response .context ["license_warning_count" ])
3525+ # Both packages have license issues, so 0% compliance
3526+ self .assertEqual (0 , response .context ["license_compliance_pct" ])
3527+
3528+ def test_product_portfolio_tab_compliance_view_security_compliance (self ):
3529+ self .client .login (username = "nexb_user" , password = "secret" )
3530+
3531+ p1 = make_package (self .dataspace )
3532+ p2 = make_package (self .dataspace )
3533+ p3 = make_package (self .dataspace )
3534+ make_vulnerability (self .dataspace , affecting = [p1 ], risk_score = 9.0 )
3535+ make_vulnerability (self .dataspace , affecting = [p2 ], risk_score = 6.5 )
3536+ make_vulnerability (self .dataspace , affecting = [p3 ], risk_score = 2.0 )
3537+
3538+ product1 = make_product (self .dataspace , inventory = [p1 , p2 , p3 ])
3539+ url = product1 .get_url ("tab_compliance" )
3540+ response = self .client .get (url )
3541+
3542+ self .assertEqual (3 , response .context ["vulnerability_count" ])
3543+ self .assertEqual (3 , response .context ["above_threshold_count" ])
3544+ self .assertEqual ("critical" , response .context ["max_vulnerability_severity" ])
3545+ self .assertEqual (1 , response .context ["critical_count" ])
3546+ self .assertEqual (1 , response .context ["high_count" ])
3547+ self .assertEqual (0 , response .context ["medium_count" ])
3548+ self .assertEqual (1 , response .context ["low_count" ])
3549+
3550+ def test_product_portfolio_tab_compliance_view_security_with_risk_threshold (self ):
3551+ self .client .login (username = "nexb_user" , password = "secret" )
3552+
3553+ p1 = make_package (self .dataspace )
3554+ p2 = make_package (self .dataspace )
3555+ make_vulnerability (self .dataspace , affecting = [p1 ], risk_score = 9.0 )
3556+ make_vulnerability (self .dataspace , affecting = [p2 ], risk_score = 2.0 )
3557+
3558+ product1 = make_product (self .dataspace , inventory = [p1 , p2 ])
3559+ product1 .update (vulnerabilities_risk_threshold = 6.0 )
3560+
3561+ url = product1 .get_url ("tab_compliance" )
3562+ response = self .client .get (url )
3563+
3564+ self .assertEqual (2 , response .context ["vulnerability_count" ])
3565+ self .assertEqual (1 , response .context ["above_threshold_count" ])
3566+ self .assertEqual ("high" , response .context ["risk_threshold" ])
3567+ self .assertEqual (6.0 , response .context ["risk_threshold_number" ])
0 commit comments