diff --git a/tests/conftest.py b/tests/conftest.py index 18c12189..b444bcf7 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -171,7 +171,9 @@ def test_rule() -> TrestleRule: ), check=Check(name="test_check", description="test check"), profile=Profile( - description="test", href="test", include_controls=[Control(id="ac-1")] + description="test", + href="test", + include_controls=[Control(id="ac-1"), Control(id="ac-2")], ), ) return test_trestle_rule diff --git a/tests/data/yaml/test_complete_rule_multiple_controls.yaml b/tests/data/yaml/test_complete_rule_multiple_controls.yaml new file mode 100644 index 00000000..022e1d74 --- /dev/null +++ b/tests/data/yaml/test_complete_rule_multiple_controls.yaml @@ -0,0 +1,21 @@ +x-trestle-rule-info: + name: example_rule_3 + description: My rule description for example rule 3 + parameter: + name: prm_1 + description: prm_1 description + alternative-values: {'default': '5%', '5pc': '5%', '10pc': '10%', '15pc': '15%', '20pc': '20%'} + default-value: '5%' + check: + name: my_check + description: My check description + profile: + description: Simple NIST Profile + href: profiles/simplified_nist_profile/profile.json + include-controls: + - id: ac-1 + - id: ac-1_smt.a +x-trestle-component-info: + name: Component 1 + description: Component 1 description + type: service diff --git a/tests/testutils.py b/tests/testutils.py index f8b19c1a..bd757552 100644 --- a/tests/testutils.py +++ b/tests/testutils.py @@ -263,6 +263,8 @@ def setup_rules_view( load_from_yaml(comp_dir, "test_complete_rule") # Load a complete rule with only required fields load_from_yaml(comp_dir, "test_complete_rule_no_params") + # Load a complete rule with multiple controls + load_from_yaml(comp_dir, "test_complete_rule_multiple_controls") def replace_string_in_file(file_path: str, old_string: str, new_string: str) -> None: diff --git a/tests/trestlebot/tasks/test_rule_transform_task.py b/tests/trestlebot/tasks/test_rule_transform_task.py index 2ff7e56a..cb8b7a37 100644 --- a/tests/trestlebot/tasks/test_rule_transform_task.py +++ b/tests/trestlebot/tasks/test_rule_transform_task.py @@ -62,11 +62,15 @@ def test_rule_transform_task(tmp_trestle_dir: str) -> None: assert component is not None assert component.props is not None - assert len(component.props) == 7 - assert component.props[0].name == RULE_ID - assert component.props[0].value == "example_rule_1" - assert component.props[1].name == RULE_DESCRIPTION - assert component.props[1].value == "My rule description for example rule 1" + assert len(component.props) == 14 + + prop_values = [prop.value for prop in component.props] + assert "example_rule_1" in prop_values + assert "My rule description for example rule 1" in prop_values + assert "example_rule_3" in prop_values + assert "My rule description for example rule 3" in prop_values + assert "my_check" in prop_values + assert "My check description" in prop_values def test_rule_transform_task_with_no_rules(tmp_trestle_dir: str) -> None: diff --git a/tests/trestlebot/transformers/test_csv_transformer.py b/tests/trestlebot/transformers/test_csv_transformer.py index dbeaba4b..c9136eb6 100644 --- a/tests/trestlebot/transformers/test_csv_transformer.py +++ b/tests/trestlebot/transformers/test_csv_transformer.py @@ -31,7 +31,7 @@ def test_csv_builder(test_rule: TrestleRule, tmp_trestle_dir: str) -> None: assert row["Component_Title"] == test_rule.component.name assert row["Component_Type"] == test_rule.component.type assert row["Component_Description"] == test_rule.component.description - assert row["Control_Id_List"] == "ac-1" + assert row["Control_Id_List"] == "ac-1 ac-2" assert row["Parameter_Id"] == test_rule.parameter.name # type: ignore assert row["Parameter_Description"] == test_rule.parameter.description # type: ignore assert row["Parameter_Value_Alternatives"] == "{}" diff --git a/trestlebot/transformers/csv_transformer.py b/trestlebot/transformers/csv_transformer.py index 965a7d15..d7ca5c9f 100644 --- a/trestlebot/transformers/csv_transformer.py +++ b/trestlebot/transformers/csv_transformer.py @@ -88,7 +88,7 @@ def _extract_rule_info(self, row: Dict[str, str]) -> Dict[str, str]: def _extract_profile(self, row: Dict[str, str]) -> Profile: """Extract profile information from a CSV row.""" - controls_list = row.get(csv_to_oscal_cd.CONTROL_ID_LIST, "").split(", ") + controls_list = row.get(csv_to_oscal_cd.CONTROL_ID_LIST, "").split(" ") return Profile( description=row.get(csv_to_oscal_cd.PROFILE_DESCRIPTION, ""), href=row.get(csv_to_oscal_cd.PROFILE_SOURCE, ""), @@ -170,7 +170,7 @@ def _add_profile(self, profile: Profile) -> Dict[str, str]: profile_dict: Dict[str, str] = { PROFILE_DESCRIPTION: profile.description, PROFILE_SOURCE: profile.href, - CONTROL_ID_LIST: ", ".join(controls_list), + CONTROL_ID_LIST: " ".join(controls_list), } return profile_dict