@@ -35,11 +35,11 @@ def test_get_groupings_real_functionality(
3535 assert "children" in grouping
3636 assert isinstance (grouping ["children" ], list )
3737
38- def test_get_groupings_omits_parent_when_not_in_section (
39- self ,
40- lightweight_diffstix ,
41- sample_technique_object ,
42- sample_subtechnique_object ,
38+ def test_get_groupings_omits_parent_when_not_in_section (
39+ self ,
40+ lightweight_diffstix ,
41+ sample_technique_object ,
42+ sample_subtechnique_object ,
4343 sample_subtechnique_of_technique_relationship ,
4444 ):
4545 """Test groupings keep child context without rendering a parent outside the section."""
@@ -58,9 +58,58 @@ def test_get_groupings_omits_parent_when_not_in_section(
5858 domain = "enterprise-attack" ,
5959 )
6060
61- assert len (result ) == 1
62- assert result [0 ]["parent" ] is None
63- assert result [0 ]["children" ] == [sample_subtechnique_object ]
61+ assert len (result ) == 1
62+ assert result [0 ]["parent" ] is None
63+ assert result [0 ]["children" ] == [sample_subtechnique_object ]
64+
65+ def test_get_groupings_keeps_orphan_subtechnique_when_relationship_missing (
66+ self ,
67+ lightweight_diffstix ,
68+ sample_subtechnique_object ,
69+ ):
70+ """Test orphaned sub-techniques remain visible when no relationship exists."""
71+ lightweight_diffstix .data ["new" ]["enterprise-attack" ]["attack_objects" ]["techniques" ] = {
72+ sample_subtechnique_object ["id" ]: sample_subtechnique_object ,
73+ }
74+ lightweight_diffstix .data ["new" ]["enterprise-attack" ]["relationships" ]["subtechniques" ] = {}
75+
76+ result = lightweight_diffstix .get_groupings (
77+ object_type = "techniques" ,
78+ stix_objects = [sample_subtechnique_object ],
79+ section = "revocations" ,
80+ domain = "enterprise-attack" ,
81+ )
82+
83+ assert len (result ) == 1
84+ assert result [0 ]["parent" ] is None
85+ assert result [0 ]["children" ] == [sample_subtechnique_object ]
86+
87+ def test_get_groupings_does_not_duplicate_child_with_parent_relationship (
88+ self ,
89+ lightweight_diffstix ,
90+ sample_technique_object ,
91+ sample_subtechnique_object ,
92+ sample_subtechnique_of_technique_relationship ,
93+ ):
94+ """Test children grouped under a real parent are not re-added by fallback handling."""
95+ lightweight_diffstix .data ["new" ]["enterprise-attack" ]["attack_objects" ]["techniques" ] = {
96+ sample_technique_object ["id" ]: sample_technique_object ,
97+ sample_subtechnique_object ["id" ]: sample_subtechnique_object ,
98+ }
99+ lightweight_diffstix .data ["new" ]["enterprise-attack" ]["relationships" ]["subtechniques" ] = {
100+ sample_subtechnique_of_technique_relationship ["id" ]: sample_subtechnique_of_technique_relationship ,
101+ }
102+
103+ result = lightweight_diffstix .get_groupings (
104+ object_type = "techniques" ,
105+ stix_objects = [sample_technique_object , sample_subtechnique_object ],
106+ section = "additions" ,
107+ domain = "enterprise-attack" ,
108+ )
109+
110+ assert len (result ) == 1
111+ assert result [0 ]["parent" ] == sample_technique_object
112+ assert result [0 ]["children" ] == [sample_subtechnique_object ]
64113
65114 def test_update_contributors_real_functionality (self , lightweight_diffstix , mock_stix_object_factory ):
66115 """Test real contributor tracking."""
0 commit comments