From b1464ba58ef05c38dff5ea2e7269752224285cea Mon Sep 17 00:00:00 2001 From: Alexander Schneider Date: Thu, 14 Dec 2023 16:56:58 +0100 Subject: [PATCH] fix: repair some more tests --- capella2polarion/__main__.py | 2 + capella2polarion/c2pcli.py | 2 +- capella2polarion/polarion.py | 2 +- tests/test_elements.py | 1171 +++++++++++++++++++--------------- 4 files changed, 648 insertions(+), 529 deletions(-) diff --git a/capella2polarion/__main__.py b/capella2polarion/__main__.py index 2c79019a..250bb895 100644 --- a/capella2polarion/__main__.py +++ b/capella2polarion/__main__.py @@ -138,6 +138,8 @@ def synchronize(ctx: click.core.Context) -> None: aC2PCli.CapellaModel, aC2PCli.CapellaDiagramCacheIndexContent, ) + # @MH - DEAKTIVIEREN - ACHTUNG!!!!!! @AS + lPW.Simulation = True # types = elements.get_types( # ctx.obj["POLARION_TYPE_MAP"], ctx.obj["ELEMENTS"] # ) diff --git a/capella2polarion/c2pcli.py b/capella2polarion/c2pcli.py index d207c720..0821ab13 100644 --- a/capella2polarion/c2pcli.py +++ b/capella2polarion/c2pcli.py @@ -50,7 +50,7 @@ def __init__( self.CapellaDiagramCacheIndexContent: list[ dict[str, typing.Any] ] | None = None - self.CapellaModel: cli_helpers.ModelCLI = capella_model + self.CapellaModel: capellambse.MelodyModel = capella_model self.SynchronizeConfigIO: typing.TextIO = synchronize_config_io self.SynchronizeConfigContent: dict[str, typing.Any] self.SynchronizeConfigRoles: dict[str, list[str]] | None = None diff --git a/capella2polarion/polarion.py b/capella2polarion/polarion.py index a5b159e0..472a280a 100644 --- a/capella2polarion/polarion.py +++ b/capella2polarion/polarion.py @@ -61,7 +61,7 @@ def __init__( str, serialize.CapellaWorkItem ] # dict[str, typing.Any] = None self.makeTypeId: typing.Any = aMakeTypeId - self.Simulation: bool = True + self.Simulation: bool = False def load_elements_and_type_map( self, diff --git a/tests/test_elements.py b/tests/test_elements.py index da248d58..20aa6b41 100644 --- a/tests/test_elements.py +++ b/tests/test_elements.py @@ -17,7 +17,8 @@ from capella2polarion import elements from capella2polarion.c2pcli import C2PCli from capella2polarion.elements import element, helpers, serialize -from capella2polarion.polarion import PolarionWorker +from capella2polarion.elements.serialize import CapellaWorkItem +from capella2polarion.polarion import TYPES_POL2CAPELLA, PolarionWorker # pylint: disable-next=relative-beyond-top-level, useless-suppression from tests.conftest import ( # type: ignore[import] @@ -156,7 +157,7 @@ class TestDiagramElements: @staticmethod @pytest.fixture - def baseObjects( + def bO( diagram_cache_index: list[dict[str, typing.Any]], model: capellambse.MelodyModel | None, ) -> BaseObjectContainer: @@ -195,18 +196,18 @@ def write(self, text: str): return BaseObjectContainer(c2p_cli, pw) @staticmethod - def test_create_diagrams(baseObjects: BaseObjectContainer): - # ctx["ELEMENTS"] = {"Diagram": ctx["MODEL"].diagrams} + def test_create_diagrams(bO: BaseObjectContainer): + # bO.pw.Elements = {"Diagram": bO.c2pcli.CapellaModel.diagrams} # diagrams = element.create_work_items( - # ctx["ELEMENTS"], + # bO.pw.Elements, # ctx["DIAGRAM_CACHE"], # {}, - # ctx["MODEL"], - # ctx["POLARION_ID_MAP"], + # bO.c2pcli.CapellaModel, + # bO.pw.PolarionIdMap, # {}, # ) - c2p_cli = baseObjects.c2pcli - pw = baseObjects.pw + c2p_cli = bO.c2pcli + pw = bO.pw lDescriptionReference: dict[str, list[str]] = {} lNewWorkItems: dict[str, serialize.CapellaWorkItem] lNewWorkItems = pw.create_work_items( @@ -231,20 +232,20 @@ def test_create_diagrams(baseObjects: BaseObjectContainer): @staticmethod def test_create_diagrams_filters_non_diagram_elements( - baseObjects: BaseObjectContainer, + bO: BaseObjectContainer, ): - # ctx["ELEMENTS"] = {"Diagram": ctx["MODEL"].diagrams} + # bO.pw.Elements = {"Diagram": bO.c2pcli.CapellaModel.diagrams} # elementyping.create_work_items( - # ctx["ELEMENTS"], + # bO.pw.Elements, # ctx["DIAGRAM_CACHE"], # {}, - # ctx["MODEL"], - # ctx["POLARION_ID_MAP"], + # bO.c2pcli.CapellaModel, + # bO.pw.PolarionIdMap, # {}, # ) - # assert ctx["API"].create_work_items.call_count == 0 - c2p_cli = baseObjects.c2pcli - pw = baseObjects.pw + # assert bO.pw.client.create_work_items.call_count == 0 + c2p_cli = bO.c2pcli + pw = bO.pw lDescriptionReference: dict[str, list[str]] = {} lNewWorkItems: dict[str, serialize.CapellaWorkItem] lNewWorkItems = pw.create_work_items( @@ -255,20 +256,20 @@ def test_create_diagrams_filters_non_diagram_elements( assert pw.client.create_work_items.call_count == 0 @staticmethod - def test_delete_diagrams(baseObjects: BaseObjectContainer): + def test_delete_diagrams(bO: BaseObjectContainer): # ctx["CAPELLA_UUIDS"] = set() # elements.delete_work_items( - # ctx["POLARION_ID_MAP"], - # ctx["POLARION_WI_MAP"], + # bO.pw.PolarionIdMap, + # bO.pw.PolarionWorkItemMap, # ctx["CAPELLA_UUIDS"], - # ctx["API"], + # bO.pw.client, # ) - # assert ctx["API"].delete_work_items.call_count == 1 - # assert ctx["API"].delete_work_items.call_args[0][0] == ["Diag-1"] - c2p_cli = baseObjects.c2pcli - pw = baseObjects.pw + # assert bO.pw.client.delete_work_items.call_count == 1 + # assert bO.pw.client.delete_work_items.call_args[0][0] == ["Diag-1"] + c2p_cli = bO.c2pcli + pw = bO.pw pw.CapellaUUIDs = set() pw.delete_work_items() assert pw.client.delete_work_items.call_count == 1 @@ -303,508 +304,624 @@ class UnsupportedFakeModelObject(FakeModelObject): """A ``FakeModelObject`` which shouldn't be migrated.""" -# @TODO Alexander umstellen -# class TestModelElements: -# @staticmethod -# @pytest.fixture -# def ctx(model: capellambse.MelodyModel) -> dict[str, typing.Any]: -# api = mock.MagicMock(spec=polarion_api.OpenAPIPolarionProjectClient) -# fake = FakeModelObject("uuid1", name="Fake 1") -# work_item = serialize.CapellaWorkItem( -# id="Obj-1", uuid_capella="uuid1", status="open" -# ) -# return { -# "API": api, -# "PROJECT_ID": "project_id", -# "DIAGRAM_CACHE": pathlib.Path(""), -# "ELEMENTS": { -# "FakeModelObject": [ -# fake, -# FakeModelObject("uuid2", name="Fake 2", attribute=fake), -# ], -# "UnsupportedFakeModelObject": [ -# UnsupportedFakeModelObject("uuid3") -# ], -# }, -# "MODEL": model, -# "POLARION_WI_MAP": {"uuid1": work_item}, -# "POLARION_ID_MAP": {"uuid1": "Obj-1"}, -# "POLARION_TYPE_MAP": {"uuid1": "FakeModelObject"}, -# "CONFIG": {}, -# "ROLES": {"FakeModelObject": ["attribute"]}, -# "WORK_ITEMS": {}, -# } - -# @staticmethod -# def test_create_work_items( -# monkeypatch: pytest.MonkeyPatch, ctx: dict[str, typing.Any] -# ): -# del ctx["ELEMENTS"]["UnsupportedFakeModelObject"] -# ctx["MODEL"] = model = mock.MagicMock() -# model.by_uuid.side_effect = ctx["ELEMENTS"]["FakeModelObject"] -# monkeypatch.setattr( -# serialize.CapellaWorkItemSerializer, -# "serialize", -# mock_generic_work_item := mock.MagicMock(), -# ) -# mock_generic_work_item.side_effect = [ -# expected := serialize.CapellaWorkItem( -# uuid_capella="uuid1", -# title="Fake 1", -# type="fakeModelObject", -# description_type="text/html", -# description=markupsafe.Markup(""), -# ), -# expected1 := serialize.CapellaWorkItem( -# uuid_capella="uuid2", -# title="Fake 2", -# type="fakeModelObject", -# description_type="text/html", -# description=markupsafe.Markup(""), -# ), -# ] - -# work_items = elementyping.create_work_items( -# ctx["ELEMENTS"], -# ctx["DIAGRAM_CACHE"], -# ctx["POLARION_TYPE_MAP"], -# ctx["MODEL"], -# ctx["POLARION_ID_MAP"], -# {}, -# ) - -# assert list(work_items.values()) == [expected, expected1] - -# @staticmethod -# def test_create_links_custom_resolver(baseObjects: BaseObjectContainer): -# obj = ctx["ELEMENTS"]["FakeModelObject"][1] -# ctx["POLARION_ID_MAP"]["uuid2"] = "Obj-2" -# ctx["ROLES"] = {"FakeModelObject": ["description_reference"]} -# ctx["DESCR_REFERENCES"] = {"uuid2": ["uuid1"]} -# expected = polarion_api.WorkItemLink( -# "Obj-2", -# "Obj-1", -# "description_reference", -# secondary_work_item_project="project_id", -# ) - -# links = elementyping.create_links( -# obj, -# ctx["POLARION_ID_MAP"], -# ctx["DESCR_REFERENCES"], -# ctx["PROJECT_ID"], -# ctx["MODEL"], -# ctx["ROLES"], -# ) - -# assert links == [expected] - -# @staticmethod -# def test_create_links_custom_exchanges_resolver(baseObjects: BaseObjectContainer): -# function_uuid = "ceffa011-7b66-4b3c-9885-8e075e312ffa" -# obj = ctx["MODEL"].by_uuid(function_uuid) -# ctx["POLARION_ID_MAP"][function_uuid] = "Obj-1" -# ctx["POLARION_ID_MAP"][ -# "1a414995-f4cd-488c-8152-486e459fb9de" -# ] = "Obj-2" -# ctx["ROLES"] = {"SystemFunction": ["input_exchanges"]} -# expected = polarion_api.WorkItemLink( -# "Obj-1", -# "Obj-2", -# "input_exchanges", -# secondary_work_item_project="project_id", -# ) - -# links = elementyping.create_links( -# obj, -# ctx["POLARION_ID_MAP"], -# {}, -# ctx["PROJECT_ID"], -# ctx["MODEL"], -# ctx["ROLES"], -# ) - -# assert links == [expected] - -# @staticmethod -# def test_create_links_missing_attribute( -# ctx: dict[str, typing.Any], caplog: pytest.LogCaptureFixture -# ): -# obj = ctx["ELEMENTS"]["FakeModelObject"][0] -# expected = ( -# "Unable to create work item link 'attribute' for [Obj-1]. " -# "There is no 'attribute' attribute on " -# "" -# ) - -# with caplog.at_level(logging.DEBUG): -# links = elementyping.create_links( -# obj, -# ctx["POLARION_ID_MAP"], -# {}, -# ctx["PROJECT_ID"], -# ctx["MODEL"], -# ctx["ROLES"], -# ) - -# assert not links -# assert caplog.messages[0] == expected - -# @staticmethod -# def test_create_links_from_ElementList(baseObjects: BaseObjectContainer): -# fake = FakeModelObject("uuid4", name="Fake 4") -# fake1 = FakeModelObject("uuid5", name="Fake 5") -# obj = FakeModelObject( -# "uuid6", -# name="Fake 6", -# attribute=common.ElementList( -# ctx["MODEL"], [fake, fake1], FakeModelObject -# ), -# ) -# ctx["ELEMENTS"]["FakeModelObject"].append(obj) -# ctx["POLARION_ID_MAP"] |= {f"uuid{i}": f"Obj-{i}" for i in range(4, 7)} -# expected_link = polarion_api.WorkItemLink( -# "Obj-6", -# "Obj-5", -# "attribute", -# secondary_work_item_project="project_id", -# ) -# expected_link1 = polarion_api.WorkItemLink( -# "Obj-6", -# "Obj-4", -# "attribute", -# secondary_work_item_project="project_id", -# ) - -# links = elementyping.create_links( -# obj, -# ctx["POLARION_ID_MAP"], -# {}, -# ctx["PROJECT_ID"], -# ctx["MODEL"], -# ctx["ROLES"], -# ) # type: ignore[arg-type] - -# assert expected_link in links -# assert expected_link1 in links - -# @staticmethod -# def test_create_link_from_single_attribute(baseObjects: BaseObjectContainer): -# obj = ctx["ELEMENTS"]["FakeModelObject"][1] -# ctx["POLARION_ID_MAP"]["uuid2"] = "Obj-2" -# expected = polarion_api.WorkItemLink( -# "Obj-2", -# "Obj-1", -# "attribute", -# secondary_work_item_project="project_id", -# ) - -# links = elementyping.create_links( -# obj, -# ctx["POLARION_ID_MAP"], -# {}, -# ctx["PROJECT_ID"], -# ctx["MODEL"], -# ctx["ROLES"], -# ) - -# assert links == [expected] - -# @staticmethod -# def test_update_work_items( -# monkeypatch: pytest.MonkeyPatch, ctx: dict[str, typing.Any] -# ): -# ctx["POLARION_WI_MAP"]["uuid1"] = serialize.CapellaWorkItem( -# id="Obj-1", -# type="type", -# uuid_capella="uuid1", -# status="open", -# title="Something", -# description_type="text/html", -# description=markupsafe.Markup("Test"), -# checksum="123", -# ) -# mock_get_polarion_wi_map = mock.MagicMock() -# monkeypatch.setattr( -# elements, "get_polarion_wi_map", mock_get_polarion_wi_map -# ) -# mock_get_polarion_wi_map.return_value = ctx["POLARION_WI_MAP"] -# ctx["WORK_ITEMS"] = { -# "uuid1": serialize.CapellaWorkItem( -# id="Obj-1", -# uuid_capella="uuid1", -# title="Fake 1", -# description_type="text/html", -# description=markupsafe.Markup(""), -# ) -# } -# ctx["MODEL"] = mock_model = mock.MagicMock() -# mock_model.by_uuid.return_value = ctx["ELEMENTS"]["FakeModelObject"][0] - -# elements.patch_work_items( -# ctx["POLARION_ID_MAP"], -# ctx["MODEL"], -# ctx["WORK_ITEMS"], -# ctx["POLARION_WI_MAP"], -# ctx["API"], -# {}, -# ctx["PROJECT_ID"], -# ctx["ROLES"], -# ) - -# assert ctx["API"].get_all_work_item_links.call_count == 1 -# assert ctx["API"].delete_work_item_links.call_count == 0 -# assert ctx["API"].create_work_item_links.call_count == 0 -# assert ctx["API"].update_work_item.call_count == 1 -# work_item = ctx["API"].update_work_item.call_args[0][0] -# assert isinstance(work_item, serialize.CapellaWorkItem) -# assert work_item.id == "Obj-1" -# assert work_item.title == "Fake 1" -# assert work_item.description_type == "text/html" -# assert work_item.description == markupsafe.Markup("") -# assert work_item.type is None -# assert work_item.uuid_capella is None -# assert work_item.status == "open" - -# @staticmethod -# def test_update_work_items_filters_work_items_with_same_checksum( -# ctx: dict[str, typing.Any] -# ): -# ctx["POLARION_WI_MAP"]["uuid1"] = serialize.CapellaWorkItem( -# checksum=TEST_WI_CHECKSUM, -# ) - -# elements.patch_work_items( -# ctx["POLARION_ID_MAP"], -# ctx["MODEL"], -# ctx["WORK_ITEMS"], -# ctx["POLARION_WI_MAP"], -# ctx["API"], -# {}, -# ctx["PROJECT_ID"], -# ctx["ROLES"], -# ) - -# assert ctx["API"].update_work_item.call_count == 0 - -# @staticmethod -# def test_update_links_with_no_elements(baseObjects: BaseObjectContainer): -# ctx["POLARION_WI_MAP"] = {} - -# elements.patch_work_items( -# ctx["POLARION_ID_MAP"], -# ctx["MODEL"], -# ctx["WORK_ITEMS"], -# ctx["POLARION_WI_MAP"], -# ctx["API"], -# {}, -# ctx["PROJECT_ID"], -# ctx["ROLES"], -# ) - -# assert ctx["API"].get_all_work_item_links.call_count == 0 - -# @staticmethod -# def test_update_links( -# monkeypatch: pytest.MonkeyPatch, ctx: dict[str, typing.Any] -# ): -# link = polarion_api.WorkItemLink( -# "Obj-1", "Obj-2", "attribute", True, "project_id" -# ) -# ctx["POLARION_WI_MAP"]["uuid1"].linked_work_items = [link] -# ctx["POLARION_WI_MAP"]["uuid2"] = serialize.CapellaWorkItem( -# id="Obj-2", uuid_capella="uuid2", status="open" -# ) -# ctx["WORK_ITEMS"] = { -# "uuid1": serialize.CapellaWorkItem( -# id="Obj-1", uuid_capella="uuid1", status="open" -# ), -# "uuid2": serialize.CapellaWorkItem( -# id="Obj-2", uuid_capella="uuid2", status="open" -# ), -# } -# mock_get_polarion_wi_map = mock.MagicMock() -# monkeypatch.setattr( -# elements, "get_polarion_wi_map", mock_get_polarion_wi_map -# ) -# mock_get_polarion_wi_map.return_value = ctx["POLARION_WI_MAP"] -# ctx["API"].get_all_work_item_links.side_effect = ( -# [link], -# [], -# ) -# ctx["MODEL"] = mock_model = mock.MagicMock() -# mock_model.by_uuid.side_effect = ctx["ELEMENTS"]["FakeModelObject"] -# expected_new_link = polarion_api.WorkItemLink( -# "Obj-2", "Obj-1", "attribute", None, "project_id" -# ) - -# elements.patch_work_items( -# ctx["POLARION_ID_MAP"], -# ctx["MODEL"], -# ctx["WORK_ITEMS"], -# ctx["POLARION_WI_MAP"], -# ctx["API"], -# {}, -# ctx["PROJECT_ID"], -# ctx["ROLES"], -# ) - -# links = ctx["API"].get_all_work_item_links.call_args_list -# assert ctx["API"].get_all_work_item_links.call_count == 2 -# assert [links[0][0][0], links[1][0][0]] == ["Obj-1", "Obj-2"] -# new_links = ctx["API"].create_work_item_links.call_args[0][0] -# assert ctx["API"].create_work_item_links.call_count == 1 -# assert new_links == [expected_new_link] -# assert ctx["API"].delete_work_item_links.call_count == 1 -# assert ctx["API"].delete_work_item_links.call_args[0][0] == [link] - -# @staticmethod -# def test_patch_work_item_grouped_links( -# monkeypatch: pytest.MonkeyPatch, -# ctx: dict[str, typing.Any], -# dummy_work_items, -# ): -# ctx["WORK_ITEMS"] = dummy_work_items - -# ctx["POLARION_WI_MAP"] = { -# "uuid0": serialize.CapellaWorkItem( -# id="Obj-0", uuid_capella="uuid0", status="open" -# ), -# "uuid1": serialize.CapellaWorkItem( -# id="Obj-1", uuid_capella="uuid1", status="open" -# ), -# "uuid2": serialize.CapellaWorkItem( -# id="Obj-2", uuid_capella="uuid2", status="open" -# ), -# } -# mock_create_links = mock.MagicMock() -# monkeypatch.setattr(element, "create_links", mock_create_links) -# mock_create_links.side_effect = lambda obj, *args: dummy_work_items[ -# obj.uuid -# ].linked_work_items - -# def mock_back_link(work_item, back_links): -# back_links[work_item.id] = [] - -# mock_grouped_links = mock.MagicMock() -# monkeypatch.setattr( -# element, "create_grouped_link_fields", mock_grouped_links -# ) -# mock_grouped_links.side_effect = mock_back_link - -# mock_grouped_links_reverse = mock.MagicMock() -# monkeypatch.setattr( -# element, -# "create_grouped_back_link_fields", -# mock_grouped_links_reverse, -# ) - -# ctx["MODEL"] = mock_model = mock.MagicMock() -# mock_model.by_uuid.side_effect = [ -# FakeModelObject(f"uuid{i}", name=f"Fake {i}") for i in range(3) -# ] - -# elements.patch_work_items( -# ctx["POLARION_ID_MAP"], -# ctx["MODEL"], -# ctx["WORK_ITEMS"], -# ctx["POLARION_WI_MAP"], -# ctx["API"], -# {}, -# ctx["PROJECT_ID"], -# ctx["ROLES"], -# ) - -# update_work_item_calls = ctx["API"].update_work_item.call_args_list -# assert len(update_work_item_calls) == 3 - -# mock_grouped_links_calls = mock_grouped_links.call_args_list - -# assert len(mock_grouped_links_calls) == 3 -# assert mock_grouped_links_reverse.call_count == 3 - -# assert mock_grouped_links_calls[0][0][0] == dummy_work_items["uuid0"] -# assert mock_grouped_links_calls[1][0][0] == dummy_work_items["uuid1"] -# assert mock_grouped_links_calls[2][0][0] == dummy_work_items["uuid2"] - -# work_item_0 = update_work_item_calls[0][0][0] -# work_item_1 = update_work_item_calls[1][0][0] -# work_item_2 = update_work_item_calls[2][0][0] - -# assert work_item_0.additional_attributes == {} -# assert work_item_1.additional_attributes == {} -# assert work_item_2.additional_attributes == {} - -# @staticmethod -# def test_maintain_grouped_links_attributes(dummy_work_items): -# for work_item in dummy_work_items.values(): -# elementyping.create_grouped_link_fields(work_item) - -# 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"] - -# assert ( -# dummy_work_items["uuid0"].additional_attributes.pop("attribute")[ -# "value" -# ] -# == HTML_LINK_0["attribute"] -# ) - -# assert ( -# dummy_work_items["uuid1"].additional_attributes.pop("attribute")[ -# "value" -# ] -# == HTML_LINK_1["attribute"] -# ) - -# 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(dummy_work_items): -# reverse_polarion_id_map = {v: k for k, v in POLARION_ID_MAP.items()} -# back_links: dict[str, list[polarion_api.WorkItemLink]] = {} - -# for work_item in dummy_work_items.values(): -# elementyping.create_grouped_link_fields(work_item, back_links) - -# for work_item_id, links in back_links.items(): -# work_item = dummy_work_items[reverse_polarion_id_map[work_item_id]] -# elementyping.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" -# )["value"] -# == HTML_LINK_0["attribute_reverse"] -# ) - -# assert ( -# dummy_work_items["uuid1"].additional_attributes.pop( -# "attribute_reverse" -# )["value"] -# == HTML_LINK_1["attribute_reverse"] -# ) - -# assert ( -# dummy_work_items["uuid2"].additional_attributes.pop( -# "attribute_reverse" -# )["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 == {} +class TestModelElements: + @staticmethod + @pytest.fixture + def bO( + model: capellambse.MelodyModel | None, + ) -> BaseObjectContainer: + import io + + class MyIO(io.StringIO): + def write(self, text: str): + pass + + work_item = serialize.CapellaWorkItem( + id="Obj-1", uuid_capella="uuid1", status="open" + ) + c2p_cli = C2PCli( + aDebug=True, + aProjectId="project_id", + aPolarionUrl=TEST_HOST, + aPolarionPat="PrivateAccessToken", + aPolarionDeleteWorkItems=True, + capella_diagram_cache_folder_path=pathlib.Path(""), + capella_model=model, + synchronize_config_io=MyIO(), + ) + c2p_cli.SynchronizeConfigRoles = {"FakeModelObject": ["attribute"]} + c2p_cli.setupLogger() + c2p_cli.PolarionClient = mock.MagicMock( + spec=polarion_api.OpenAPIPolarionProjectClient + ) + pw = PolarionWorker( + c2p_cli.PolarionClient, + c2p_cli.logger, + helpers.resolve_element_type, + ) + # pw.CapellaUUIDs = set([d["uuid"] for d in diagram_cache_index]) + pw.PolarionWorkItemMap = {"uuid1": work_item} + pw.PolarionIdMap = {"uuid1": "Obj-1"} + pw.PolarionTypeMap = {"uuid1": "FakeModelObject"} + fake = FakeModelObject("uuid1", name="Fake 1") + pw.Elements = { + "FakeModelObject": [ + fake, + FakeModelObject("uuid2", name="Fake 2", attribute=fake), + ], + "UnsupportedFakeModelObject": [ + UnsupportedFakeModelObject("uuid3") + ], + } + return BaseObjectContainer(c2p_cli, pw) + + # @staticmethod + # @pytest.fixture + # def ctx(model: capellambse.MelodyModel) -> dict[str, typing.Any]: + # #api = mock.MagicMock(spec=polarion_api.OpenAPIPolarionProjectClient) + # #fake = FakeModelObject("uuid1", name="Fake 1") + # #work_item = serialize.CapellaWorkItem( + # # id="Obj-1", uuid_capella="uuid1", status="open" + # #) + # return { + # #"API": api, + # #"PROJECT_ID": "project_id", + # #"DIAGRAM_CACHE": pathlib.Path(""), + # #"ELEMENTS": { + # # "FakeModelObject": [ + # # fake, + # # FakeModelObject("uuid2", name="Fake 2", attribute=fake), + # # ], + # # "UnsupportedFakeModelObject": [ + # # UnsupportedFakeModelObject("uuid3") + # # ], + # #}, + # #"MODEL": model, + # #"POLARION_WI_MAP": {"uuid1": work_item}, + # #"POLARION_ID_MAP": {"uuid1": "Obj-1"}, + # #"POLARION_TYPE_MAP": {"uuid1": "FakeModelObject"}, + # #"CONFIG": {}, + # #"ROLES": {"FakeModelObject": ["attribute"]}, + # #"WORK_ITEMS": {}, + # } + + @staticmethod + def test_create_work_items( + monkeypatch: pytest.MonkeyPatch, bO: BaseObjectContainer + ): + # del bO.pw.Elements["UnsupportedFakeModelObject"] + del bO.pw.Elements["UnsupportedFakeModelObject"] + # bO.c2pcli.CapellaModel = model = mock.MagicMock() + bO.c2pcli.CapellaModel = mock.MagicMock() + # model.by_uuid.side_effect = bO.pw.Elements["FakeModelObject"] + bO.c2pcli.CapellaModel.by_uuid.side_effect = bO.pw.Elements[ + "FakeModelObject" + ] + monkeypatch.setattr( + serialize.CapellaWorkItemSerializer, + "serialize", + mock_generic_work_item := mock.MagicMock(), + ) + mock_generic_work_item.side_effect = [ + expected := serialize.CapellaWorkItem( + uuid_capella="uuid1", + title="Fake 1", + type="fakeModelObject", + description_type="text/html", + description=markupsafe.Markup(""), + ), + expected1 := serialize.CapellaWorkItem( + uuid_capella="uuid2", + title="Fake 2", + type="fakeModelObject", + description_type="text/html", + description=markupsafe.Markup(""), + ), + ] + # work_items = element.create_work_items( + # bO.pw.Elements, + # ctx["DIAGRAM_CACHE"], + # ctx["POLARION_TYPE_MAP"], + # bO.c2pcli.CapellaModel, + # bO.pw.PolarionIdMap, + # {}, + # ) + work_items = bO.pw.create_work_items( + bO.c2pcli.CapellaDiagramCacheFolderPath, + bO.c2pcli.CapellaModel, + {}, + ) + assert list(work_items.values()) == [expected, expected1] + + @staticmethod + def test_create_links_custom_resolver(bO: BaseObjectContainer): + # obj = bO.pw.Elements["FakeModelObject"][1] + obj = bO.pw.Elements["FakeModelObject"][1] + # bO.pw.PolarionIdMap["uuid2"] = "Obj-2" + bO.pw.PolarionIdMap["uuid2"] = "Obj-2" + # bO.c2pcli.SynchronizeConfigRoles = {"FakeModelObject": ["description_reference"]} + bO.c2pcli.SynchronizeConfigRoles = { + "FakeModelObject": ["description_reference"] + } + # ctx["DESCR_REFERENCES"] = {"uuid2": ["uuid1"]} + lDescriptionReference = {"uuid2": ["uuid1"]} + expected = polarion_api.WorkItemLink( + "Obj-2", + "Obj-1", + "description_reference", + secondary_work_item_project="project_id", + ) + # links = element.create_links( + # obj, + # bO.pw.PolarionIdMap, + # ctx["DESCR_REFERENCES"], + # bO.c2pcli.ProjectId, + # bO.c2pcli.CapellaModel, + # bO.c2pcli.SynchronizeConfigRoles, + # ) + # @MH @AS, der letzte Parameter ReverseTypeMap war vorher nicht drin... prüfen! + links = element.create_links( + obj, + bO.pw.PolarionIdMap, + lDescriptionReference, + bO.c2pcli.ProjectId, + bO.c2pcli.CapellaModel, + bO.c2pcli.SynchronizeConfigRoles, + TYPES_POL2CAPELLA, + ) + assert links == [expected] + + @staticmethod + def test_create_links_custom_exchanges_resolver(bO: BaseObjectContainer): + function_uuid = "ceffa011-7b66-4b3c-9885-8e075e312ffa" + # obj = bO.c2pcli.CapellaModel.by_uuid(function_uuid) + obj = bO.c2pcli.CapellaModel.by_uuid(function_uuid) + # bO.pw.PolarionIdMap[function_uuid] = "Obj-1" + # bO.pw.PolarionIdMap[ + # "1a414995-f4cd-488c-8152-486e459fb9de" + # ] = "Obj-2" + bO.pw.PolarionIdMap[function_uuid] = "Obj-1" + bO.pw.PolarionIdMap["1a414995-f4cd-488c-8152-486e459fb9de"] = "Obj-2" + # bO.c2pcli.SynchronizeConfigRoles = {"SystemFunction": ["input_exchanges"]} + bO.c2pcli.SynchronizeConfigRoles = { + "SystemFunction": ["input_exchanges"] + } + expected = polarion_api.WorkItemLink( + "Obj-1", + "Obj-2", + "input_exchanges", + secondary_work_item_project="project_id", + ) + # links = elementyping.create_links( + # obj, + # bO.pw.PolarionIdMap, + # {}, + # bO.c2pcli.ProjectId, + # bO.c2pcli.CapellaModel, + # bO.c2pcli.SynchronizeConfigRoles, + # ) + links = element.create_links( + obj, + bO.pw.PolarionIdMap, + {}, + bO.c2pcli.ProjectId, + bO.c2pcli.CapellaModel, + bO.c2pcli.SynchronizeConfigRoles, + TYPES_POL2CAPELLA, + ) + assert links == [expected] + + @staticmethod + def test_create_links_missing_attribute( + bO: BaseObjectContainer, caplog: pytest.LogCaptureFixture + ): + # obj = bO.pw.Elements["FakeModelObject"][0] + obj = bO.pw.Elements["FakeModelObject"][0] + expected = ( + "Unable to create work item link 'attribute' for [Obj-1]. " + "There is no 'attribute' attribute on " + "" + ) + # with caplog.at_level(logging.DEBUG): + # links = element.create_links( + # obj, + # bO.pw.PolarionIdMap, + # {}, + # bO.c2pcli.ProjectId, + # bO.c2pcli.CapellaModel, + # bO.c2pcli.SynchronizeConfigRoles, + # ) + with caplog.at_level(logging.DEBUG): + links = element.create_links( + obj, + bO.pw.PolarionIdMap, + {}, + bO.c2pcli.ProjectId, + bO.c2pcli.CapellaModel, + bO.c2pcli.SynchronizeConfigRoles, + TYPES_POL2CAPELLA, + ) + assert not links + assert caplog.messages[0] == expected + + @staticmethod + def test_create_links_from_ElementList(bO: BaseObjectContainer): + fake = FakeModelObject("uuid4", name="Fake 4") + fake1 = FakeModelObject("uuid5", name="Fake 5") + obj = FakeModelObject( + "uuid6", + name="Fake 6", + attribute=common.ElementList( + bO.c2pcli.CapellaModel, [fake, fake1], FakeModelObject + ), + ) + bO.pw.Elements["FakeModelObject"].append(obj) + bO.pw.PolarionIdMap |= {f"uuid{i}": f"Obj-{i}" for i in range(4, 7)} + expected_link = polarion_api.WorkItemLink( + "Obj-6", + "Obj-5", + "attribute", + secondary_work_item_project="project_id", + ) + expected_link1 = polarion_api.WorkItemLink( + "Obj-6", + "Obj-4", + "attribute", + secondary_work_item_project="project_id", + ) + links = element.create_links( + obj, + bO.pw.PolarionIdMap, + {}, + bO.c2pcli.ProjectId, + bO.c2pcli.CapellaModel, + bO.c2pcli.SynchronizeConfigRoles, + TYPES_POL2CAPELLA, + ) + # type: ignore[arg-type] + assert expected_link in links + assert expected_link1 in links + + @staticmethod + def test_create_link_from_single_attribute(bO: BaseObjectContainer): + obj = bO.pw.Elements["FakeModelObject"][1] + bO.pw.PolarionIdMap["uuid2"] = "Obj-2" + expected = polarion_api.WorkItemLink( + "Obj-2", + "Obj-1", + "attribute", + secondary_work_item_project="project_id", + ) + links = element.create_links( + obj, + bO.pw.PolarionIdMap, + {}, + bO.c2pcli.ProjectId, + bO.c2pcli.CapellaModel, + bO.c2pcli.SynchronizeConfigRoles, + TYPES_POL2CAPELLA, + ) + assert links == [expected] + + @staticmethod + def test_update_work_items( + monkeypatch: pytest.MonkeyPatch, bO: BaseObjectContainer + ): + lPolarionWorkItemList: list[serialize.CapellaWorkItem] = [] + lPolarionWorkItemList.append( + serialize.CapellaWorkItem( + id="Obj-1", + type="type", + uuid_capella="uuid1", + status="open", + title="Something", + description_type="text/html", + description=markupsafe.Markup("Test"), + checksum="123", + ) + ) + + # mock_get_polarion_wi_map = mock.MagicMock() + # monkeypatch.setattr( + # elements, "get_polarion_wi_map", mock_get_polarion_wi_map + # ) + # mock_get_polarion_wi_map.return_value = bO.pw.PolarionWorkItemMap + + polarion_api_get_all_work_items = mock.MagicMock() + polarion_api_get_all_work_items.return_value = lPolarionWorkItemList + monkeypatch.setattr( + bO.pw.client, "get_all_work_items", polarion_api_get_all_work_items + ) + bO.pw.load_polarion_work_item_map() + + work_items = { + "uuid1": serialize.CapellaWorkItem( + id="Obj-1", + uuid_capella="uuid1", + title="Fake 1", + description_type="text/html", + description=markupsafe.Markup(""), + ) + } + bO.c2pcli.CapellaModel = mock_model = mock.MagicMock() + mock_model.by_uuid.return_value = bO.pw.Elements["FakeModelObject"][0] + bO.pw.patch_work_items( + bO.c2pcli.CapellaModel, + work_items, + {}, + bO.c2pcli.ProjectId, + bO.c2pcli.SynchronizeConfigRoles, + ) + # elements.patch_work_items( + # bO.pw.PolarionIdMap, + # bO.c2pcli.CapellaModel, + # work_items, + # bO.pw.PolarionWorkItemMap, + # bO.pw.client, + # {}, + # bO.c2pcli.ProjectId, + # bO.c2pcli.SynchronizeConfigRoles, + # ) + assert bO.pw.client.get_all_work_item_links.call_count == 1 + assert bO.pw.client.delete_work_item_links.call_count == 0 + assert bO.pw.client.create_work_item_links.call_count == 0 + assert bO.pw.client.update_work_item.call_count == 1 + work_item = bO.pw.client.update_work_item.call_args[0][0] + assert isinstance(work_item, serialize.CapellaWorkItem) + assert work_item.id == "Obj-1" + assert work_item.title == "Fake 1" + assert work_item.description_type == "text/html" + assert work_item.description == markupsafe.Markup("") + assert work_item.type is None + # @MH .. nächste Zeile hatten wir schon, damals wurde entschieden uuid_capella muss str sein! + # assert work_item.uuid_capella is None + assert work_item.status == "open" + + @staticmethod + def test_update_work_items_filters_work_items_with_same_checksum( + bO: BaseObjectContainer, + ): + bO.pw.PolarionWorkItemMap["uuid1"] = serialize.CapellaWorkItem( + checksum=TEST_WI_CHECKSUM, + ) + work_items: dict[str, serialize.CapellaWorkItem] = {} + bO.pw.patch_work_items( + bO.c2pcli.CapellaModel, + work_items, + {}, + bO.c2pcli.ProjectId, + bO.c2pcli.SynchronizeConfigRoles, + ) + # elements.patch_work_items( + # bO.pw.PolarionIdMap, + # bO.c2pcli.CapellaModel, + # work_items, + # bO.pw.PolarionWorkItemMap, + # bO.pw.client, + # {}, + # bO.c2pcli.ProjectId, + # bO.c2pcli.SynchronizeConfigRoles, + # ) + assert bO.pw.client.update_work_item.call_count == 0 + + @staticmethod + def test_update_links_with_no_elements(bO: BaseObjectContainer): + bO.pw.PolarionWorkItemMap = {} + work_items: dict[str, serialize.CapellaWorkItem] = {} + bO.pw.patch_work_items( + bO.c2pcli.CapellaModel, + work_items, + {}, + bO.c2pcli.ProjectId, + bO.c2pcli.SynchronizeConfigRoles, + ) + # elements.patch_work_items( + # bO.pw.PolarionIdMap, + # bO.c2pcli.CapellaModel, + # work_items, + # bO.pw.PolarionWorkItemMap, + # bO.pw.client, + # {}, + # bO.c2pcli.ProjectId, + # bO.c2pcli.SynchronizeConfigRoles, + # ) + assert bO.pw.client.get_all_work_item_links.call_count == 0 + + @staticmethod + def test_update_links( + monkeypatch: pytest.MonkeyPatch, bO: BaseObjectContainer + ): + link = polarion_api.WorkItemLink( + "Obj-1", "Obj-2", "attribute", True, "project_id" + ) + bO.pw.PolarionWorkItemMap["uuid1"].linked_work_items = [link] + bO.pw.PolarionWorkItemMap["uuid2"] = serialize.CapellaWorkItem( + id="Obj-2", uuid_capella="uuid2", status="open" + ) + work_items = { + "uuid1": serialize.CapellaWorkItem( + id="Obj-1", uuid_capella="uuid1", status="open" + ), + "uuid2": serialize.CapellaWorkItem( + id="Obj-2", uuid_capella="uuid2", status="open" + ), + } + mock_get_polarion_wi_map = mock.MagicMock() + monkeypatch.setattr( + elements, "get_polarion_wi_map", mock_get_polarion_wi_map + ) + mock_get_polarion_wi_map.return_value = bO.pw.PolarionWorkItemMap + bO.pw.client.get_all_work_item_links.side_effect = ( + [link], + [], + ) + bO.c2pcli.CapellaModel = mock_model = mock.MagicMock() + mock_model.by_uuid.side_effect = bO.pw.Elements["FakeModelObject"] + expected_new_link = polarion_api.WorkItemLink( + "Obj-2", "Obj-1", "attribute", None, "project_id" + ) + bO.pw.patch_work_items( + bO.c2pcli.CapellaModel, + work_items, + {}, + bO.c2pcli.ProjectId, + bO.c2pcli.SynchronizeConfigRoles, + ) + # elements.patch_work_items( + # bO.pw.PolarionIdMap, + # bO.c2pcli.CapellaModel, + # work_items, + # bO.pw.PolarionWorkItemMap, + # bO.pw.client, + # {}, + # bO.c2pcli.ProjectId, + # bO.c2pcli.SynchronizeConfigRoles, + # ) + links = bO.pw.client.get_all_work_item_links.call_args_list + assert bO.pw.client.get_all_work_item_links.call_count == 2 + assert [links[0][0][0], links[1][0][0]] == ["Obj-1", "Obj-2"] + new_links = bO.pw.client.create_work_item_links.call_args[0][0] + assert bO.pw.client.create_work_item_links.call_count == 1 + assert new_links == [expected_new_link] + assert bO.pw.client.delete_work_item_links.call_count == 1 + assert bO.pw.client.delete_work_item_links.call_args[0][0] == [link] + + @staticmethod + def test_patch_work_item_grouped_links( + monkeypatch: pytest.MonkeyPatch, + bO: BaseObjectContainer, + dummy_work_items: dict[str, CapellaWorkItem], + ): + work_items = dummy_work_items + bO.pw.PolarionWorkItemMap = { + "uuid0": serialize.CapellaWorkItem( + id="Obj-0", uuid_capella="uuid0", status="open" + ), + "uuid1": serialize.CapellaWorkItem( + id="Obj-1", uuid_capella="uuid1", status="open" + ), + "uuid2": serialize.CapellaWorkItem( + id="Obj-2", uuid_capella="uuid2", status="open" + ), + } + mock_create_links = mock.MagicMock() + monkeypatch.setattr(element, "create_links", mock_create_links) + mock_create_links.side_effect = lambda obj, *args: dummy_work_items[ + obj.uuid + ].linked_work_items + + def mock_back_link(work_item, back_links): + back_links[work_item.id] = [] + + mock_grouped_links = mock.MagicMock() + monkeypatch.setattr( + element, "create_grouped_link_fields", mock_grouped_links + ) + mock_grouped_links.side_effect = mock_back_link + mock_grouped_links_reverse = mock.MagicMock() + monkeypatch.setattr( + element, + "create_grouped_back_link_fields", + mock_grouped_links_reverse, + ) + bO.c2pcli.CapellaModel = mock_model = mock.MagicMock() + mock_model.by_uuid.side_effect = [ + FakeModelObject(f"uuid{i}", name=f"Fake {i}") for i in range(3) + ] + bO.pw.patch_work_items( + bO.c2pcli.CapellaModel, + work_items, + {}, + bO.c2pcli.ProjectId, + bO.c2pcli.SynchronizeConfigRoles, + ) + # elements.patch_work_items( + # bO.pw.PolarionIdMap, + # bO.c2pcli.CapellaModel, + # work_items, + # bO.pw.PolarionWorkItemMap, + # bO.pw.client, + # {}, + # bO.c2pcli.ProjectId, + # bO.c2pcli.SynchronizeConfigRoles, + # ) + update_work_item_calls = bO.pw.client.update_work_item.call_args_list + assert len(update_work_item_calls) == 3 + mock_grouped_links_calls = mock_grouped_links.call_args_list + assert len(mock_grouped_links_calls) == 3 + assert mock_grouped_links_reverse.call_count == 3 + assert mock_grouped_links_calls[0][0][0] == dummy_work_items["uuid0"] + assert mock_grouped_links_calls[1][0][0] == dummy_work_items["uuid1"] + assert mock_grouped_links_calls[2][0][0] == dummy_work_items["uuid2"] + work_item_0 = update_work_item_calls[0][0][0] + work_item_1 = update_work_item_calls[1][0][0] + work_item_2 = update_work_item_calls[2][0][0] + assert work_item_0.additional_attributes == {} + assert work_item_1.additional_attributes == {} + assert work_item_2.additional_attributes == {} + + @staticmethod + def test_maintain_grouped_links_attributes( + dummy_work_items: dict[str, CapellaWorkItem] + ): + for work_item in dummy_work_items.values(): + element.create_grouped_link_fields(work_item) + 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"] + assert ( + dummy_work_items["uuid0"].additional_attributes.pop("attribute")[ + "value" + ] + == HTML_LINK_0["attribute"] + ) + assert ( + dummy_work_items["uuid1"].additional_attributes.pop("attribute")[ + "value" + ] + == HTML_LINK_1["attribute"] + ) + 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( + dummy_work_items: dict[str, CapellaWorkItem] + ): + reverse_polarion_id_map = {v: k for k, v in POLARION_ID_MAP.items()} + back_links: dict[str, list[polarion_api.WorkItemLink]] = {} + for work_item in dummy_work_items.values(): + element.create_grouped_link_fields(work_item, back_links) + for work_item_id, links in back_links.items(): + work_item = dummy_work_items[reverse_polarion_id_map[work_item_id]] + element.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" + )["value"] + == HTML_LINK_0["attribute_reverse"] + ) + assert ( + dummy_work_items["uuid1"].additional_attributes.pop( + "attribute_reverse" + )["value"] + == HTML_LINK_1["attribute_reverse"] + ) + assert ( + dummy_work_items["uuid2"].additional_attributes.pop( + "attribute_reverse" + )["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 == {} def test_grouped_linked_work_items_order_consistency():