Skip to content

Commit 3faf529

Browse files
authored
test: smartlink critical edge-case regression tests (#946)
Closes #945. Follow-up to #938.
1 parent 08387f0 commit 3faf529

1 file changed

Lines changed: 81 additions & 0 deletions

File tree

application/tests/web_main_test.py

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,87 @@ def test_smartlink(self) -> None:
634634
)
635635
self.assertEqual(302, response.status_code)
636636

637+
def _smartlink_redirect_location(self, client, path: str) -> tuple[int, str]:
638+
response = client.get(path, headers={"Content-Type": "application/json"})
639+
location = ""
640+
for head in response.headers:
641+
if head[0] == "Location":
642+
location = head[1]
643+
return response.status_code, location
644+
645+
def test_smartlink_critical_edge_cases(self) -> None:
646+
"""Critical smartlink paths from #945 — multi-CRE, unlinked node, ntype, version."""
647+
collection = db.Node_collection().with_graph()
648+
with self.app.test_client() as client:
649+
# Multiple CREs → standard-section node page (preserved by #938).
650+
cwe_multi = defs.Standard(name="CWEmulti", sectionID="789")
651+
ce = defs.CRE(id="444-444", description="CE", name="CE", tags=[])
652+
cf = defs.CRE(id="555-555", description="CF", name="CF", tags=[])
653+
dcwe_multi = collection.add_node(cwe_multi)
654+
dce = collection.add_cre(ce)
655+
dcf = collection.add_cre(cf)
656+
collection.add_link(dce, dcwe_multi, ltype=defs.LinkTypes.LinkedTo)
657+
collection.add_link(dcf, dcwe_multi, ltype=defs.LinkTypes.LinkedTo)
658+
659+
status, location = self._smartlink_redirect_location(
660+
client, "/smartlink/standard/CWEmulti/789"
661+
)
662+
self.assertEqual(status, 302)
663+
self.assertEqual(location, "/node/standard/CWEmulti/sectionid/789")
664+
665+
# Local standard with no CRE links → MITRE external redirect, not node page.
666+
orphan = defs.Standard(name="CWE", sectionID="8888")
667+
collection.add_node(orphan)
668+
status, location = self._smartlink_redirect_location(
669+
client, "/smartlink/standard/CWE/8888"
670+
)
671+
self.assertEqual(status, 302)
672+
self.assertEqual(
673+
location, "https://cwe.mitre.org/data/definitions/8888.html"
674+
)
675+
676+
# Case-insensitive ntype still resolves the standard node.
677+
cwe_std = defs.Standard(name="CWE", sectionID="456")
678+
cre_a = defs.CRE(id="222-222", description="CD", name="CD", tags=[])
679+
cre_b = defs.CRE(id="223-223", description="CE", name="CE", tags=[])
680+
dcwe = collection.add_node(cwe_std)
681+
dcre_a = collection.add_cre(cre_a)
682+
dcre_b = collection.add_cre(cre_b)
683+
collection.add_link(dcre_a, dcwe, ltype=defs.LinkTypes.LinkedTo)
684+
collection.add_link(dcre_b, dcwe, ltype=defs.LinkTypes.LinkedTo)
685+
686+
status, location = self._smartlink_redirect_location(
687+
client, "/smartlink/STANDARD/CWE/456"
688+
)
689+
self.assertEqual(status, 302)
690+
self.assertEqual(location, "/node/STANDARD/CWE/sectionid/456")
691+
692+
# version query param selects the matching standard row (multi-CRE → node page).
693+
std_v1 = defs.Standard(name="VERSTD", sectionID="100", version="1.0")
694+
std_v2 = defs.Standard(name="VERSTD", sectionID="200", version="2.0")
695+
cre_v1a = defs.CRE(id="100-100", description="v1a", name="V1A", tags=[])
696+
cre_v1b = defs.CRE(id="100-101", description="v1b", name="V1B", tags=[])
697+
cre_v2a = defs.CRE(id="200-200", description="v2a", name="V2A", tags=[])
698+
cre_v2b = defs.CRE(id="200-201", description="v2b", name="V2B", tags=[])
699+
dstd_v1 = collection.add_node(std_v1)
700+
dstd_v2 = collection.add_node(std_v2)
701+
for cre in (cre_v1a, cre_v1b, cre_v2a, cre_v2b):
702+
dcre = collection.add_cre(cre)
703+
target = dstd_v1 if cre.id.startswith("100") else dstd_v2
704+
collection.add_link(dcre, target, ltype=defs.LinkTypes.LinkedTo)
705+
706+
status, location = self._smartlink_redirect_location(
707+
client, "/smartlink/standard/VERSTD/100?version=1.0"
708+
)
709+
self.assertEqual(status, 302)
710+
self.assertEqual(location, "/node/standard/VERSTD/sectionid/100")
711+
712+
status, location = self._smartlink_redirect_location(
713+
client, "/smartlink/standard/VERSTD/200?version=2.0"
714+
)
715+
self.assertEqual(status, 302)
716+
self.assertEqual(location, "/node/standard/VERSTD/sectionid/200")
717+
637718
@patch.object(redis, "from_url")
638719
@patch.object(db, "Node_collection")
639720
def test_gap_analysis_from_cache_full_response(

0 commit comments

Comments
 (0)