@@ -62,6 +62,55 @@ def test_get_groupings_omits_parent_when_not_in_section(
6262 assert result [0 ]["parent" ] is None
6363 assert result [0 ]["children" ] == [sample_subtechnique_object ]
6464
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 ]
113+
65114 def test_update_contributors_real_functionality (self , lightweight_diffstix , mock_stix_object_factory ):
66115 """Test real contributor tracking."""
67116 # Create objects with contributors
0 commit comments