|
4 | 4 | import pytest |
5 | 5 | from socketdev import socketdev |
6 | 6 |
|
7 | | -from socketsecurity.core import Core |
| 7 | +from socketsecurity.core import Core, _humanize_alert_type |
8 | 8 | from socketsecurity.core.classes import Issue, Package |
9 | 9 | from socketsecurity.core.socket_config import SocketConfig |
10 | 10 |
|
@@ -166,6 +166,62 @@ def test_add_package_alerts_basic(self, core): |
166 | 166 | assert alert.type == "networkAccess" |
167 | 167 | assert alert.severity == "high" |
168 | 168 |
|
| 169 | + def test_gpt_did_you_mean_gets_typosquat_title(self, core): |
| 170 | + """gptDidYouMean alerts must render a non-empty title (CUS2-2).""" |
| 171 | + package = self.make_package( |
| 172 | + alerts=[{ |
| 173 | + "type": "gptDidYouMean", |
| 174 | + "key": "gpt-did-you-mean-alert", |
| 175 | + "severity": "middle", |
| 176 | + }], |
| 177 | + topLevelAncestors=[], |
| 178 | + ) |
| 179 | + |
| 180 | + result = core.add_package_alerts_to_collection( |
| 181 | + package, alerts_collection={}, packages={package.id: package} |
| 182 | + ) |
| 183 | + |
| 184 | + alert = result["gpt-did-you-mean-alert"][0] |
| 185 | + assert alert.type == "gptDidYouMean" |
| 186 | + assert alert.title, "title should not be empty for gptDidYouMean" |
| 187 | + assert "typosquat" in alert.title.lower() |
| 188 | + |
| 189 | + def test_unknown_alert_type_falls_back_to_humanized_title(self, core): |
| 190 | + """Any alert type not present in the SDK should still render a non-empty title.""" |
| 191 | + package = self.make_package( |
| 192 | + alerts=[{ |
| 193 | + "type": "someBrandNewAlertType", |
| 194 | + "key": "future-alert", |
| 195 | + "severity": "low", |
| 196 | + }], |
| 197 | + topLevelAncestors=[], |
| 198 | + ) |
| 199 | + |
| 200 | + result = core.add_package_alerts_to_collection( |
| 201 | + package, alerts_collection={}, packages={package.id: package} |
| 202 | + ) |
| 203 | + |
| 204 | + alert = result["future-alert"][0] |
| 205 | + assert alert.title == "Some Brand New Alert Type" |
| 206 | + |
| 207 | + def test_license_spdx_disj_keeps_explicit_title(self, core): |
| 208 | + """licenseSpdxDisj must keep its hard-coded fallback (regression guard for CUS2-2 fix).""" |
| 209 | + package = self.make_package( |
| 210 | + alerts=[{ |
| 211 | + "type": "licenseSpdxDisj", |
| 212 | + "key": "license-alert", |
| 213 | + "severity": "high", |
| 214 | + }], |
| 215 | + topLevelAncestors=[], |
| 216 | + ) |
| 217 | + |
| 218 | + result = core.add_package_alerts_to_collection( |
| 219 | + package, alerts_collection={}, packages={package.id: package} |
| 220 | + ) |
| 221 | + |
| 222 | + alert = result["license-alert"][0] |
| 223 | + assert alert.title == "License Policy Violation" |
| 224 | + |
169 | 225 |
|
170 | 226 |
|
171 | 227 | def test_get_capabilities_for_added_packages(self, core): |
@@ -266,3 +322,22 @@ def test_get_license_text_via_purl_uses_org_scoped_endpoint(self, core, mock_sdk |
266 | 322 | ) |
267 | 323 | assert result["npm/lodash@4.18.1"].licenseAttrib == [{"name": "MIT"}] |
268 | 324 | assert result["npm/lodash@4.18.1"].licenseDetails == [{"license": "MIT"}] |
| 325 | + |
| 326 | + |
| 327 | +class TestHumanizeAlertType: |
| 328 | + def test_humanizes_camel_case(self): |
| 329 | + assert _humanize_alert_type("gptDidYouMean") == "Gpt Did You Mean" |
| 330 | + |
| 331 | + def test_humanizes_single_word(self): |
| 332 | + assert _humanize_alert_type("malware") == "Malware" |
| 333 | + |
| 334 | + def test_humanizes_pascal_case(self): |
| 335 | + assert _humanize_alert_type("UnsafeShellAccess") == "Unsafe Shell Access" |
| 336 | + |
| 337 | + def test_empty_input_returns_empty_string(self): |
| 338 | + assert _humanize_alert_type("") == "" |
| 339 | + |
| 340 | + def test_handles_acronyms_conservatively(self): |
| 341 | + """Adjacent capitals are kept together: SQLInjection -> 'SQL Injection'.""" |
| 342 | + assert _humanize_alert_type("SQLInjection") == "SQL Injection" |
| 343 | + |
0 commit comments