From 5706951d4525d98033b30bd16698ad91127619e7 Mon Sep 17 00:00:00 2001 From: ewuerger <ernst.wuerger@gmail.com> Date: Tue, 20 Aug 2024 10:41:49 +0200 Subject: [PATCH 1/6] fix: Remove obsolete link serializers --- capella2polarion/converters/link_converter.py | 25 +++---------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/capella2polarion/converters/link_converter.py b/capella2polarion/converters/link_converter.py index 7a16dddc..2b9141a8 100644 --- a/capella2polarion/converters/link_converter.py +++ b/capella2polarion/converters/link_converter.py @@ -23,7 +23,7 @@ TYPE_RESOLVERS = {"Part": lambda obj: obj.type.uuid} _Serializer: t.TypeAlias = cabc.Callable[ - [common.GenericElement, str, str, str, dict[str, t.Any]], + [common.GenericElement, str, str, dict[str, t.Any]], list[polarion_api.WorkItemLink], ] @@ -48,8 +48,6 @@ def __init__( self.serializers: dict[str, _Serializer] = { converter_config.DESCRIPTION_REFERENCE_SERIALIZER: self._handle_description_reference_links, # pylint: disable=line-too-long converter_config.DIAGRAM_ELEMENTS_SERIALIZER: self._handle_diagram_reference_links, # pylint: disable=line-too-long - "input_exchanges": self._handle_exchanges, - "output_exchanges": self._handle_exchanges, } def create_links_for_work_item( @@ -60,6 +58,7 @@ def create_links_for_work_item( obj = converter_data.capella_element work_item = converter_data.work_item assert work_item is not None + assert work_item.id is not None new_links: list[polarion_api.WorkItemLink] = [] link_errors: list[str] = [] for link_config in converter_data.type_config.links: @@ -71,7 +70,7 @@ def create_links_for_work_item( try: if serializer: new_links.extend( - serializer(obj, work_item.id, role_id, attr_id, {}) + serializer(obj, work_item.id, role_id, {}) ) else: refs = _resolve_attribute(obj, attr_id) @@ -137,10 +136,8 @@ def _handle_description_reference_links( obj: common.GenericElement, work_item_id: str, role_id: str, - attr_id: str, links: dict[str, polarion_api.WorkItemLink], ) -> list[polarion_api.WorkItemLink]: - del attr_id refs = self.converter_session[obj.uuid].description_references ref_set = set(self._get_work_item_ids(work_item_id, refs, role_id)) return self._create(work_item_id, role_id, ref_set, links) @@ -150,10 +147,8 @@ def _handle_diagram_reference_links( obj: diag.Diagram, work_item_id: str, role_id: str, - attr_id: str, links: dict[str, polarion_api.WorkItemLink], ) -> list[polarion_api.WorkItemLink]: - del attr_id try: refs = set(self._collect_uuids(obj.nodes)) refs = set(self._get_work_item_ids(work_item_id, refs, role_id)) @@ -199,20 +194,6 @@ def _create( ] return list(filter(None, _new_links)) - def _handle_exchanges( - self, - obj: fa.Function, - work_item_id: str, - role_id: str, - attr_id: str, - links: dict[str, polarion_api.WorkItemLink], - ) -> list[polarion_api.WorkItemLink]: - exchanges: list[str] = [] - objs = _resolve_attribute(obj, attr_id) - exs = self._get_work_item_ids(work_item_id, objs.by_uuid, role_id) - exchanges.extend(set(exs)) - return self._create(work_item_id, role_id, exchanges, links) - def create_grouped_link_fields( self, data: data_session.ConverterData, From 318b9597ef8a2163db154fdb5b2071563bcdabf4 Mon Sep 17 00:00:00 2001 From: ewuerger <ernst.wuerger@gmail.com> Date: Tue, 20 Aug 2024 10:42:02 +0200 Subject: [PATCH 2/6] test: Fix CLI test --- tests/test_cli.py | 32 ++++++++++++++++++++++---------- tests/test_elements.py | 4 ++-- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/tests/test_cli.py b/tests/test_cli.py index 2620374d..30e7b79a 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -11,7 +11,8 @@ from click import testing import capella2polarion.__main__ as main -from capella2polarion.connectors.polarion_worker import CapellaPolarionWorker +from capella2polarion.connectors import polarion_worker +from capella2polarion.converters import model_converter # pylint: disable-next=relative-beyond-top-level, useless-suppression from .conftest import ( # type: ignore[import] @@ -26,25 +27,31 @@ def test_migrate_model_elements(monkeypatch: pytest.MonkeyPatch): monkeypatch.setattr(polarion_api, "OpenAPIPolarionProjectClient", mock_api) mock_get_polarion_wi_map = mock.MagicMock() monkeypatch.setattr( - CapellaPolarionWorker, + polarion_worker.CapellaPolarionWorker, "load_polarion_work_item_map", mock_get_polarion_wi_map, ) + mock_generate_work_items = mock.MagicMock() + monkeypatch.setattr( + model_converter.ModelConverter, + "generate_work_items", + mock_generate_work_items, + ) mock_delete_work_items = mock.MagicMock() monkeypatch.setattr( - CapellaPolarionWorker, + polarion_worker.CapellaPolarionWorker, "delete_orphaned_work_items", mock_delete_work_items, ) mock_post_work_items = mock.MagicMock() monkeypatch.setattr( - CapellaPolarionWorker, + polarion_worker.CapellaPolarionWorker, "create_missing_work_items", mock_post_work_items, ) mock_patch_work_items = mock.MagicMock() monkeypatch.setattr( - CapellaPolarionWorker, + polarion_worker.CapellaPolarionWorker, "compare_and_update_work_items", mock_patch_work_items, ) @@ -68,6 +75,11 @@ def test_migrate_model_elements(monkeypatch: pytest.MonkeyPatch): assert result.exit_code == 0 assert mock_get_polarion_wi_map.call_count == 1 + assert mock_generate_work_items.call_count == 2 + assert mock_generate_work_items.call_args_list[1][1] == { + "generate_links": True, + "generate_attachments": True, + } assert mock_delete_work_items.call_count == 1 assert mock_patch_work_items.call_count == 1 assert mock_post_work_items.call_count == 1 @@ -78,7 +90,7 @@ def test_render_documents(monkeypatch: pytest.MonkeyPatch): monkeypatch.setattr(polarion_api, "OpenAPIPolarionProjectClient", mock_api) mock_get_polarion_wi_map = mock.MagicMock() monkeypatch.setattr( - CapellaPolarionWorker, + polarion_worker.CapellaPolarionWorker, "load_polarion_work_item_map", mock_get_polarion_wi_map, ) @@ -96,25 +108,25 @@ def test_render_documents(monkeypatch: pytest.MonkeyPatch): else None ) monkeypatch.setattr( - CapellaPolarionWorker, + polarion_worker.CapellaPolarionWorker, "get_document", mock_get_document, ) mock_post_documents = mock.MagicMock() monkeypatch.setattr( - CapellaPolarionWorker, + polarion_worker.CapellaPolarionWorker, "post_documents", mock_post_documents, ) mock_update_documents = mock.MagicMock() monkeypatch.setattr( - CapellaPolarionWorker, + polarion_worker.CapellaPolarionWorker, "update_documents", mock_update_documents, ) mock_update_work_items = mock.MagicMock() monkeypatch.setattr( - CapellaPolarionWorker, + polarion_worker.CapellaPolarionWorker, "update_work_items", mock_update_work_items, ) diff --git a/tests/test_elements.py b/tests/test_elements.py index 2c7682ba..ec74f1c4 100644 --- a/tests/test_elements.py +++ b/tests/test_elements.py @@ -474,7 +474,7 @@ def error(): assert False link_serializer.serializers["invalid_role"] = ( - lambda obj, work_item_id, role_id, attr_id, links: error() + lambda obj, work_item_id, role_id, links: error() ) with caplog.at_level(logging.ERROR): @@ -550,7 +550,7 @@ def error(): assert False link_serializer.serializers["invalid_role"] = ( - lambda obj, work_item_id, role_id, attr_id, links: error() + lambda obj, work_item_id, role_id, links: error() ) with caplog.at_level(logging.WARNING): From f60aafa8d88a5bd2d38d26d8c6e639d2c396343f Mon Sep 17 00:00:00 2001 From: ewuerger <ernst.wuerger@gmail.com> Date: Tue, 20 Aug 2024 13:49:50 +0200 Subject: [PATCH 3/6] ci: Please pylint and mypy --- capella2polarion/converters/converter_config.py | 6 +++--- capella2polarion/converters/document_renderer.py | 6 ++++-- tests/test_cli.py | 3 ++- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/capella2polarion/converters/converter_config.py b/capella2polarion/converters/converter_config.py index b037fcc5..9f45d67c 100644 --- a/capella2polarion/converters/converter_config.py +++ b/capella2polarion/converters/converter_config.py @@ -37,7 +37,7 @@ class LinkConfig: """ capella_attr: str - polarion_role: str | None = None + polarion_role: str include: dict[str, str] = dataclasses.field(default_factory=dict) @@ -288,9 +288,9 @@ def _filter_links( for link in links: cappela_attr = link.capella_attr.split(".")[0] if ( - cappela_attr == DESCRIPTION_REFERENCE_SERIALIZER + cappela_attr.endswith(DESCRIPTION_REFERENCE_SERIALIZER) or ( - cappela_attr == DIAGRAM_ELEMENTS_SERIALIZER + cappela_attr.endswith(DIAGRAM_ELEMENTS_SERIALIZER) and c_class == diagram.Diagram ) or hasattr(c_class, cappela_attr) diff --git a/capella2polarion/converters/document_renderer.py b/capella2polarion/converters/document_renderer.py index 04d3bc3c..7b012754 100644 --- a/capella2polarion/converters/document_renderer.py +++ b/capella2polarion/converters/document_renderer.py @@ -433,7 +433,8 @@ def _render_full_authority_documents( ) except Exception as e: logger.error( - "Rendering for document %s/%s failed with the following error", + "Rendering for document %s/%s failed with the " + "following error", instance.polarion_space, instance.polarion_name, exc_info=e, @@ -456,7 +457,8 @@ def _render_full_authority_documents( ) except Exception as e: logger.error( - "Rendering for document %s/%s failed with the following error", + "Rendering for document %s/%s failed with the " + "following error", instance.polarion_space, instance.polarion_name, exc_info=e, diff --git a/tests/test_cli.py b/tests/test_cli.py index 30e7b79a..6d7516f6 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -101,7 +101,8 @@ def test_render_documents(monkeypatch: pytest.MonkeyPatch): module_name=name, home_page_content=polarion_api.TextContent( "text/html", - '<h1 id="polarion_wiki macro name=module-workitem;params=id=TEST-123></h1>', + '<h1 id="polarion_wiki macro name=module-workitem;' + 'params=id=TEST-123"></h1>', ), ) if name == "id1236" From f39bf54f861f6c1beda2d480ee8b301746570095 Mon Sep 17 00:00:00 2001 From: ewuerger <ernst.wuerger@gmail.com> Date: Tue, 20 Aug 2024 13:50:13 +0200 Subject: [PATCH 4/6] fix: Role-prefix bug in LinkConverter --- capella2polarion/converters/link_converter.py | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/capella2polarion/converters/link_converter.py b/capella2polarion/converters/link_converter.py index 2b9141a8..4e4d46b1 100644 --- a/capella2polarion/converters/link_converter.py +++ b/capella2polarion/converters/link_converter.py @@ -12,7 +12,6 @@ import polarion_rest_api_client as polarion_api from capellambse.model import common from capellambse.model import diagram as diag -from capellambse.model.crosslayer import fa import capella2polarion.converters.polarion_html_helper from capella2polarion import data_models @@ -64,7 +63,7 @@ def create_links_for_work_item( for link_config in converter_data.type_config.links: assert (role_id := link_config.polarion_role) is not None attr_id = link_config.capella_attr or "" - serializer = self.serializers.get(role_id) + serializer = self.serializers.get(attr_id) if self.role_prefix: role_id = f"{self.role_prefix}_{role_id}" try: @@ -228,11 +227,12 @@ def create_grouped_link_fields( config = link_config break + role_id = role + if self.role_prefix: + role_id = role.removeprefix(f"{self.role_prefix}_") + self._create_link_fields( - work_item, - role.removeprefix(f"{self.role_prefix}_"), - grouped_links, - config=config, + work_item, role_id, grouped_links, config=config ) def _create_link_fields( @@ -315,12 +315,11 @@ def create_grouped_back_link_fields( List of links referencing work_item as secondary """ for role, grouped_links in _group_by("role", links).items(): - self._create_link_fields( - work_item, - role.removeprefix(f"{self.role_prefix}_"), - grouped_links, - True, - ) + role_id = role + if self.role_prefix: + role_id = role.removeprefix(f"{self.role_prefix}_") + + self._create_link_fields(work_item, role_id, grouped_links, True) def _group_by( From a1947768c56011a78a853594a69481b1af0ab079 Mon Sep 17 00:00:00 2001 From: ewuerger <ernst.wuerger@gmail.com> Date: Tue, 20 Aug 2024 13:50:34 +0200 Subject: [PATCH 5/6] test: Add tests for role-prefix --- tests/test_elements.py | 129 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 117 insertions(+), 12 deletions(-) diff --git a/tests/test_elements.py b/tests/test_elements.py index ec74f1c4..a594b8b3 100644 --- a/tests/test_elements.py +++ b/tests/test_elements.py @@ -1081,7 +1081,11 @@ def test_maintain_grouped_links_attributes( ): config = converter_config.CapellaTypeConfig( "fakeModelObject", - links=[converter_config.LinkConfig("attribute")], + links=[ + converter_config.LinkConfig( + capella_attr="attribute", polarion_role="attribute" + ) + ], ) mock_model = mock.MagicMock() fake_2 = FakeModelObject("uuid2", "Fale 2") @@ -1123,6 +1127,48 @@ def test_maintain_grouped_links_attributes( assert dummy_work_items["uuid1"].additional_attributes == {} assert dummy_work_items["uuid2"].additional_attributes == {} + @staticmethod + def test_maintain_grouped_links_attributes_with_role_prefix( + base_object: BaseObjectContainer, + dummy_work_items: dict[str, data_models.CapellaWorkItem], + ): + config = converter_config.CapellaTypeConfig( + "fakeModelObject", + links=[ + converter_config.LinkConfig( + capella_attr="attribute", polarion_role="attribute" + ) + ], + ) + mock_model = mock.MagicMock() + fake_2 = FakeModelObject("uuid2", "Fale 2") + fake_1 = FakeModelObject("uuid1", "Fake 1") + fake_0 = FakeModelObject("uuid0", "Fake 0", attribute=[fake_1, fake_2]) + fake_1.attribute = [fake_0, fake_2] + mock_model.by_uuid.side_effect = lambda uuid: { + "uuid0": fake_0, + "uuid1": fake_1, + "uuid2": fake_2, + }[uuid] + for link in dummy_work_items["uuid0"].linked_work_items: + link.role = f"_C2P_{link.role}" + link_serializer = link_converter.LinkSerializer( + base_object.pw.polarion_data_repo, + base_object.mc.converter_session, + base_object.pw.polarion_params.project_id, + mock_model, + role_prefix="_C2P", + ) + + for work_item in dummy_work_items.values(): + converter_data = data_session.ConverterData( + "test", config, [], work_item + ) + link_serializer.create_grouped_link_fields(converter_data) + + assert "attribute" in dummy_work_items["uuid0"].additional_attributes + assert "attribute" in dummy_work_items["uuid1"].additional_attributes + @staticmethod def test_grouped_links_attributes_with_includes( base_object: BaseObjectContainer, model: capellambse.MelodyModel @@ -1212,7 +1258,11 @@ def test_maintain_reverse_grouped_links_attributes( back_links: dict[str, list[polarion_api.WorkItemLink]] = {} config = converter_config.CapellaTypeConfig( "fakeModelObject", - links=[converter_config.LinkConfig("attribute")], + links=[ + converter_config.LinkConfig( + capella_attr="attribute", polarion_role="attribute" + ) + ], ) mock_model = mock.MagicMock() fake_2 = FakeModelObject("uuid2", "Fake 2") @@ -1268,6 +1318,61 @@ def test_maintain_reverse_grouped_links_attributes( assert dummy_work_items["uuid1"].additional_attributes == {} assert dummy_work_items["uuid2"].additional_attributes == {} + @staticmethod + def test_maintain_reverse_grouped_links_attributes_with_role_prefix( + base_object: BaseObjectContainer, + dummy_work_items: dict[str, data_models.CapellaWorkItem], + ): + reverse_polarion_id_map = {v: k for k, v in POLARION_ID_MAP.items()} + back_links: dict[str, list[polarion_api.WorkItemLink]] = {} + config = converter_config.CapellaTypeConfig( + "fakeModelObject", + links=[ + converter_config.LinkConfig( + capella_attr="attribute", polarion_role="attribute" + ) + ], + ) + mock_model = mock.MagicMock() + fake_2 = FakeModelObject("uuid2", "Fake 2") + fake_1 = FakeModelObject("uuid1", "Fake 1") + fake_0 = FakeModelObject("uuid0", "Fake 0", attribute=[fake_1, fake_2]) + fake_1.attribute = [fake_0, fake_2] + mock_model.by_uuid.side_effect = lambda uuid: { + "uuid0": fake_0, + "uuid1": fake_1, + "uuid2": fake_2, + }[uuid] + for link in dummy_work_items["uuid0"].linked_work_items: + link.role = f"_C2P_{link.role}" + link_serializer = link_converter.LinkSerializer( + base_object.pw.polarion_data_repo, + base_object.mc.converter_session, + base_object.pw.polarion_params.project_id, + mock_model, + role_prefix="_C2P", + ) + for work_item in dummy_work_items.values(): + converter_data = data_session.ConverterData( + "test", config, [], work_item + ) + link_serializer.create_grouped_link_fields( + converter_data, back_links + ) + + for work_item_id, links in back_links.items(): + work_item = dummy_work_items[reverse_polarion_id_map[work_item_id]] + link_serializer.create_grouped_back_link_fields(work_item, links) + + assert ( + "attribute_reverse" + in dummy_work_items["uuid0"].additional_attributes + ) + assert ( + "attribute_reverse" + in dummy_work_items["uuid1"].additional_attributes + ) + def test_grouped_linked_work_items_order_consistency( base_object: BaseObjectContainer, @@ -1755,6 +1860,15 @@ def test_read_config_with_custom_params(model: capellambse.MelodyModel): def test_read_config_links(caplog: pytest.LogCaptureFixture): caplog.set_level("DEBUG") config = converter_config.ConverterConfig() + expected = ( + "capella2polarion.converters.converter_config", + 20, + "Global link parent is not available on Capella type diagram", + "capella2polarion.converters.converter_config", + 40, + "Link exchanged_items is not available on Capella type " + "FunctionalExchange", + ) with open(TEST_MODEL_ELEMENTS_CONFIG, "r", encoding="utf8") as f: config.read_config_file(f) @@ -1764,13 +1878,4 @@ def test_read_config_links(caplog: pytest.LogCaptureFixture): for link in config.diagram_config.links if link.capella_attr == "parent" ) - assert caplog.record_tuples[0][1] == 20 - assert ( - caplog.record_tuples[0][2] - == "Global link parent is not available on Capella type diagram" - ) - assert caplog.record_tuples[1][1] == 40 - assert ( - caplog.record_tuples[1][2] - == "Link exchanged_items is not available on Capella type FunctionalExchange" - ) + assert caplog.record_tuples[0] + caplog.record_tuples[1] == expected From 654eca90ea226f970832b32a089b3fe3f2b8ce51 Mon Sep 17 00:00:00 2001 From: ewuerger <ernst.wuerger@gmail.com> Date: Tue, 20 Aug 2024 16:10:25 +0200 Subject: [PATCH 6/6] fix: Apply changes from code review --- .../converters/converter_config.py | 16 +-- capella2polarion/converters/link_converter.py | 31 ++-- tests/test_elements.py | 136 +++++++++--------- 3 files changed, 93 insertions(+), 90 deletions(-) diff --git a/capella2polarion/converters/converter_config.py b/capella2polarion/converters/converter_config.py index 9f45d67c..d81ab52c 100644 --- a/capella2polarion/converters/converter_config.py +++ b/capella2polarion/converters/converter_config.py @@ -286,27 +286,25 @@ def _filter_links( available_links = [] for link in links: - cappela_attr = link.capella_attr.split(".")[0] + capella_attr = link.capella_attr.split(".")[0] + is_diagram_elements = capella_attr == DIAGRAM_ELEMENTS_SERIALIZER if ( - cappela_attr.endswith(DESCRIPTION_REFERENCE_SERIALIZER) - or ( - cappela_attr.endswith(DIAGRAM_ELEMENTS_SERIALIZER) - and c_class == diagram.Diagram - ) - or hasattr(c_class, cappela_attr) + capella_attr == DESCRIPTION_REFERENCE_SERIALIZER + or (is_diagram_elements and c_class == diagram.Diagram) + or hasattr(c_class, capella_attr) ): available_links.append(link) else: if is_global: logger.info( "Global link %s is not available on Capella type %s", - cappela_attr, + capella_attr, c_type, ) else: logger.error( "Link %s is not available on Capella type %s", - cappela_attr, + capella_attr, c_type, ) return available_links diff --git a/capella2polarion/converters/link_converter.py b/capella2polarion/converters/link_converter.py index 4e4d46b1..34256173 100644 --- a/capella2polarion/converters/link_converter.py +++ b/capella2polarion/converters/link_converter.py @@ -61,9 +61,8 @@ def create_links_for_work_item( new_links: list[polarion_api.WorkItemLink] = [] link_errors: list[str] = [] for link_config in converter_data.type_config.links: - assert (role_id := link_config.polarion_role) is not None - attr_id = link_config.capella_attr or "" - serializer = self.serializers.get(attr_id) + serializer = self.serializers.get(link_config.capella_attr) + role_id = link_config.polarion_role if self.role_prefix: role_id = f"{self.role_prefix}_{role_id}" try: @@ -72,7 +71,7 @@ def create_links_for_work_item( serializer(obj, work_item.id, role_id, {}) ) else: - refs = _resolve_attribute(obj, attr_id) + refs = _resolve_attribute(obj, link_config.capella_attr) new: cabc.Iterable[str] if isinstance(refs, common.ElementList): new = refs.by_uuid # type: ignore[assignment] @@ -87,9 +86,14 @@ def create_links_for_work_item( self._create(work_item.id, role_id, new, {}) ) except Exception as error: - request_text = f"Requested attribute: {attr_id}" error_text = f"{type(error).__name__} {str(error)}" - link_errors.extend([request_text, error_text, "--------"]) + link_errors.extend( + [ + f"Requested attribute: {link_config.capella_attr}", + error_text, + "--------", + ] + ) if link_errors: for link_error in link_errors: @@ -227,10 +231,7 @@ def create_grouped_link_fields( config = link_config break - role_id = role - if self.role_prefix: - role_id = role.removeprefix(f"{self.role_prefix}_") - + role_id = self._remove_prefix(role) self._create_link_fields( work_item, role_id, grouped_links, config=config ) @@ -315,12 +316,14 @@ def create_grouped_back_link_fields( List of links referencing work_item as secondary """ for role, grouped_links in _group_by("role", links).items(): - role_id = role - if self.role_prefix: - role_id = role.removeprefix(f"{self.role_prefix}_") - + role_id = self._remove_prefix(role) self._create_link_fields(work_item, role_id, grouped_links, True) + def _remove_prefix(self, role: str) -> str: + if self.role_prefix: + return role.removeprefix(f"{self.role_prefix}_") + return role + def _group_by( attr: str, diff --git a/tests/test_elements.py b/tests/test_elements.py index a594b8b3..f3e48604 100644 --- a/tests/test_elements.py +++ b/tests/test_elements.py @@ -162,6 +162,55 @@ DIAGRAM_CONFIG = converter_config.CapellaTypeConfig("diagram", "diagram") +class GroupedLinksBaseObject(t.TypedDict): + link_serializer: link_converter.LinkSerializer + work_items: dict[str, data_models.CapellaWorkItem] + back_links: dict[str, list[polarion_api.WorkItemLink]] + reverse_polarion_id_map: dict[str, str] + config: converter_config.CapellaTypeConfig + + +# pylint: disable=redefined-outer-name +@pytest.fixture() +def grouped_links_base_object( + base_object: BaseObjectContainer, + dummy_work_items: dict[str, data_models.CapellaWorkItem], +) -> GroupedLinksBaseObject: + reverse_polarion_id_map = {v: k for k, v in POLARION_ID_MAP.items()} + back_links: dict[str, list[polarion_api.WorkItemLink]] = {} + config = converter_config.CapellaTypeConfig( + "fakeModelObject", + links=[ + converter_config.LinkConfig( + capella_attr="attribute", polarion_role="attribute" + ) + ], + ) + mock_model = mock.MagicMock() + fake_2 = FakeModelObject("uuid2", "Fake 2") + fake_1 = FakeModelObject("uuid1", "Fake 1") + fake_0 = FakeModelObject("uuid0", "Fake 0", attribute=[fake_1, fake_2]) + fake_1.attribute = [fake_0, fake_2] + mock_model.by_uuid.side_effect = lambda uuid: { + "uuid0": fake_0, + "uuid1": fake_1, + "uuid2": fake_2, + }[uuid] + link_serializer = link_converter.LinkSerializer( + base_object.pw.polarion_data_repo, + base_object.mc.converter_session, + base_object.pw.polarion_params.project_id, + mock_model, + ) + return { + "link_serializer": link_serializer, + "work_items": dummy_work_items, + "back_links": back_links, + "reverse_polarion_id_map": reverse_polarion_id_map, + "config": config, + } + + class TestDiagramElements: @staticmethod @pytest.fixture @@ -1251,35 +1300,16 @@ def test_grouped_links_attributes_with_includes( @staticmethod def test_maintain_reverse_grouped_links_attributes( - base_object: BaseObjectContainer, - dummy_work_items: dict[str, data_models.CapellaWorkItem], + grouped_links_base_object: GroupedLinksBaseObject, ): - reverse_polarion_id_map = {v: k for k, v in POLARION_ID_MAP.items()} - back_links: dict[str, list[polarion_api.WorkItemLink]] = {} - config = converter_config.CapellaTypeConfig( - "fakeModelObject", - links=[ - converter_config.LinkConfig( - capella_attr="attribute", polarion_role="attribute" - ) - ], - ) - mock_model = mock.MagicMock() - fake_2 = FakeModelObject("uuid2", "Fake 2") - fake_1 = FakeModelObject("uuid1", "Fake 1") - fake_0 = FakeModelObject("uuid0", "Fake 0", attribute=[fake_1, fake_2]) - fake_1.attribute = [fake_0, fake_2] - mock_model.by_uuid.side_effect = lambda uuid: { - "uuid0": fake_0, - "uuid1": fake_1, - "uuid2": fake_2, - }[uuid] - link_serializer = link_converter.LinkSerializer( - base_object.pw.polarion_data_repo, - base_object.mc.converter_session, - base_object.pw.polarion_params.project_id, - mock_model, - ) + link_serializer = grouped_links_base_object["link_serializer"] + dummy_work_items = grouped_links_base_object["work_items"] + reverse_polarion_id_map = grouped_links_base_object[ + "reverse_polarion_id_map" + ] + back_links = grouped_links_base_object["back_links"] + config = grouped_links_base_object["config"] + for work_item in dummy_work_items.values(): converter_data = data_session.ConverterData( "test", config, [], work_item @@ -1287,15 +1317,10 @@ def test_maintain_reverse_grouped_links_attributes( link_serializer.create_grouped_link_fields( converter_data, back_links ) - for work_item_id, links in back_links.items(): work_item = dummy_work_items[reverse_polarion_id_map[work_item_id]] link_serializer.create_grouped_back_link_fields(work_item, links) - del dummy_work_items["uuid0"].additional_attributes["uuid_capella"] - del dummy_work_items["uuid1"].additional_attributes["uuid_capella"] - del dummy_work_items["uuid2"].additional_attributes["uuid_capella"] - del dummy_work_items["uuid0"].additional_attributes["attribute"] - del dummy_work_items["uuid1"].additional_attributes["attribute"] + assert ( dummy_work_items["uuid0"].additional_attributes.pop( "attribute_reverse" @@ -1314,44 +1339,22 @@ def test_maintain_reverse_grouped_links_attributes( )["value"] == HTML_LINK_2["attribute_reverse"] ) - assert dummy_work_items["uuid0"].additional_attributes == {} - assert dummy_work_items["uuid1"].additional_attributes == {} - assert dummy_work_items["uuid2"].additional_attributes == {} @staticmethod def test_maintain_reverse_grouped_links_attributes_with_role_prefix( - base_object: BaseObjectContainer, - dummy_work_items: dict[str, data_models.CapellaWorkItem], + grouped_links_base_object: GroupedLinksBaseObject, ): - reverse_polarion_id_map = {v: k for k, v in POLARION_ID_MAP.items()} - back_links: dict[str, list[polarion_api.WorkItemLink]] = {} - config = converter_config.CapellaTypeConfig( - "fakeModelObject", - links=[ - converter_config.LinkConfig( - capella_attr="attribute", polarion_role="attribute" - ) - ], - ) - mock_model = mock.MagicMock() - fake_2 = FakeModelObject("uuid2", "Fake 2") - fake_1 = FakeModelObject("uuid1", "Fake 1") - fake_0 = FakeModelObject("uuid0", "Fake 0", attribute=[fake_1, fake_2]) - fake_1.attribute = [fake_0, fake_2] - mock_model.by_uuid.side_effect = lambda uuid: { - "uuid0": fake_0, - "uuid1": fake_1, - "uuid2": fake_2, - }[uuid] + link_serializer = grouped_links_base_object["link_serializer"] + dummy_work_items = grouped_links_base_object["work_items"] + reverse_polarion_id_map = grouped_links_base_object[ + "reverse_polarion_id_map" + ] + back_links = grouped_links_base_object["back_links"] + config = grouped_links_base_object["config"] for link in dummy_work_items["uuid0"].linked_work_items: link.role = f"_C2P_{link.role}" - link_serializer = link_converter.LinkSerializer( - base_object.pw.polarion_data_repo, - base_object.mc.converter_session, - base_object.pw.polarion_params.project_id, - mock_model, - role_prefix="_C2P", - ) + link_serializer.role_prefix = "_C2P" + for work_item in dummy_work_items.values(): converter_data = data_session.ConverterData( "test", config, [], work_item @@ -1359,7 +1362,6 @@ def test_maintain_reverse_grouped_links_attributes_with_role_prefix( link_serializer.create_grouped_link_fields( converter_data, back_links ) - for work_item_id, links in back_links.items(): work_item = dummy_work_items[reverse_polarion_id_map[work_item_id]] link_serializer.create_grouped_back_link_fields(work_item, links)