diff --git a/capella2polarion/__main__.py b/capella2polarion/__main__.py index 437588b3..a9e93ea6 100644 --- a/capella2polarion/__main__.py +++ b/capella2polarion/__main__.py @@ -169,7 +169,7 @@ def render_documents( projects_document_data = renderer.render_documents(configs, documents) for project, project_data in projects_document_data.items(): - polarion_worker.post_documents(project_data.new_docs, project) + polarion_worker.create_documents(project_data.new_docs, project) polarion_worker.update_documents(project_data.updated_docs, project) diff --git a/capella2polarion/connectors/polarion_worker.py b/capella2polarion/connectors/polarion_worker.py index aabb6df5..48f80580 100644 --- a/capella2polarion/connectors/polarion_worker.py +++ b/capella2polarion/connectors/polarion_worker.py @@ -461,7 +461,7 @@ def compare_and_update_work_items( if uuid in self.polarion_data_repo and data.work_item is not None: self.compare_and_update_work_item(data) - def post_documents( + def create_documents( self, document_datas: list[data_models.DocumentData], document_project: str | None = None, diff --git a/capella2polarion/converters/polarion_html_helper.py b/capella2polarion/converters/polarion_html_helper.py index a611c70b..0a684a74 100644 --- a/capella2polarion/converters/polarion_html_helper.py +++ b/capella2polarion/converters/polarion_html_helper.py @@ -165,44 +165,6 @@ def extract_work_items( return work_items -def insert_text_work_items( - document: polarion_api.Document, - text_work_items: dict[str, polarion_api.WorkItem], - text_work_item_type: str, -): - """Insert text work items into the given document.""" - if not text_work_items: - return - - assert document.home_page_content is not None - layout_index = get_layout_index( - "paragraph", document.rendering_layouts, text_work_item_type - ) - html_fragments = ensure_fragments(document.home_page_content.value) - new_content = [] - last_match = -1 - for index, element in enumerate(html_fragments): - if isinstance(element, html.HtmlComment): - continue - - if element.tag == "workitem": - new_content += html_fragments[last_match + 1 : index] - last_match = index - if work_item := text_work_items.get(element.get("id")): - new_content.append( - html.fromstring( - POLARION_WORK_ITEM_DOCUMENT.format( - pid=work_item.id, lid=layout_index, custom_info="" - ) - ) - ) - - new_content += html_fragments[last_match + 1 :] - document.home_page_content.value = "\n".join( - [html.tostring(element).decode("utf-8") for element in new_content] - ) - - def get_layout_index( default_layouter: str, rendering_layouts: list[polarion_api.RenderingLayout], diff --git a/capella2polarion/converters/text_work_item_provider.py b/capella2polarion/converters/text_work_item_provider.py index ae9a7455..4bae1845 100644 --- a/capella2polarion/converters/text_work_item_provider.py +++ b/capella2polarion/converters/text_work_item_provider.py @@ -90,6 +90,7 @@ def insert_text_work_items( return assert document.home_page_content is not None + assert document.rendering_layouts is not None layout_index = html_helper.get_layout_index( "paragraph", document.rendering_layouts, self.text_work_item_type ) diff --git a/tests/conftest.py b/tests/conftest.py index 2d5afc09..296cd368 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -186,3 +186,7 @@ def empty_polarion_worker(monkeypatch: pytest.MonkeyPatch): delete_work_items=True, ) yield polarion_worker.CapellaPolarionWorker(polarion_params) + + +DOCUMENT_TEMPLATES = TEST_DOCUMENT_ROOT / "templates" +DOCUMENT_TEXT_WORK_ITEMS = "document_work_items.html.j2" diff --git a/tests/data/documents/sections/section1.html.j2 b/tests/data/documents/sections/section1.html.j2 index 575220b9..13b1afb7 100644 --- a/tests/data/documents/sections/section1.html.j2 +++ b/tests/data/documents/sections/section1.html.j2 @@ -6,3 +6,4 @@ {{ heading(3, "New Heading", session) }}

{{ global_param }}

{{ local_param }}

+TestContent diff --git a/tests/data/documents/sections/section2.html.j2 b/tests/data/documents/sections/section2.html.j2 index ec7a3fb7..0e0630a0 100644 --- a/tests/data/documents/sections/section2.html.j2 +++ b/tests/data/documents/sections/section2.html.j2 @@ -6,3 +6,4 @@ {{ heading(3, "Keep Heading", session) }}

Overwritten: {{ global_param }}

{{ local_param }}

+TestContent diff --git a/tests/data/documents/templates/document_work_items.html.j2 b/tests/data/documents/templates/document_work_items.html.j2 new file mode 100644 index 00000000..aecd905a --- /dev/null +++ b/tests/data/documents/templates/document_work_items.html.j2 @@ -0,0 +1,10 @@ + + +This is Text in a text workitem + +Text +
12
+
diff --git a/tests/test_cli.py b/tests/test_cli.py index b102592a..7894f405 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -117,11 +117,11 @@ def test_render_documents(monkeypatch: pytest.MonkeyPatch): "get_document", mock_get_document, ) - mock_post_documents = mock.MagicMock() + mock_create_documents = mock.MagicMock() monkeypatch.setattr( polarion_worker.CapellaPolarionWorker, - "post_documents", - mock_post_documents, + "create_documents", + mock_create_documents, ) mock_update_documents = mock.MagicMock() monkeypatch.setattr( @@ -161,11 +161,11 @@ def test_render_documents(monkeypatch: pytest.MonkeyPatch): "TestProject", ] - assert mock_post_documents.call_count == 2 - assert len(mock_post_documents.call_args_list[0].args[0]) == 1 - assert len(mock_post_documents.call_args_list[1].args[0]) == 1 - assert mock_post_documents.call_args_list[0].args[1] is None - assert mock_post_documents.call_args_list[1].args[1] == "TestProject" + assert mock_create_documents.call_count == 2 + assert len(mock_create_documents.call_args_list[0].args[0]) == 1 + assert len(mock_create_documents.call_args_list[1].args[0]) == 1 + assert mock_create_documents.call_args_list[0].args[1] is None + assert mock_create_documents.call_args_list[1].args[1] == "TestProject" assert mock_update_documents.call_count == 2 assert len(mock_update_documents.call_args_list[0].args[0]) == 1 diff --git a/tests/test_documents.py b/tests/test_documents.py index fb55d68f..1faa13ce 100644 --- a/tests/test_documents.py +++ b/tests/test_documents.py @@ -7,8 +7,17 @@ from capella2polarion import data_models as dm from capella2polarion.connectors import polarion_worker -from capella2polarion.converters import document_config, document_renderer -from tests.conftest import TEST_COMBINED_DOCUMENT_CONFIG, TEST_DOCUMENT_ROOT +from capella2polarion.converters import ( + document_config, + document_renderer, + text_work_item_provider, +) +from tests.conftest import ( + DOCUMENT_TEMPLATES, + DOCUMENT_TEXT_WORK_ITEMS, + TEST_COMBINED_DOCUMENT_CONFIG, + TEST_DOCUMENT_ROOT, +) CLASSES_TEMPLATE = "test-classes.html.j2" JUPYTER_TEMPLATE_FOLDER = "jupyter-notebooks/document_templates" @@ -231,30 +240,162 @@ def test_mixed_authority_document( "global_param": "Overwrite global param", }, }, + text_work_item_provider=text_work_item_provider.TextWorkItemProvider( + "MyField", + "MyType", + [ + polarion_api.WorkItem( + id="EXISTING", additional_attributes={"MyField": "id1"} + ) + ], + ), ) content: list[etree._Element] = html.fromstring( document_data.document.home_page_content.value ) - assert len(content) == 15 + assert len(document_data.text_work_item_provider.new_text_work_items) == 2 + assert ( + document_data.text_work_item_provider.new_text_work_items["id1"].id + is None + ) + assert ( + document_data.text_work_item_provider.new_text_work_items["id2"].id + is None + ) + assert len(content) == 17 assert [c.tag for c in content[:3]] == ["h1", "p", "p"] assert (c4 := content[4]).tag == "h3" and c4.text == "New Heading" assert content[5].text == "Global Test" assert content[6].text == "Local Test section 1" - assert content[8].text == "This will be kept." - assert content[10].get("id") == ( + assert content[9].text == "This will be kept." + assert content[11].get("id") == ( "polarion_wiki macro name=module-workitem;params=id=ATSY-18305" ) - assert content[10].tag == "h3" - assert content[11].text == "Overwritten: Overwrite global param" - assert content[12].text == "Local Test section 2" - assert content[14].text == "Some postfix stuff" + assert content[11].tag == "h3" + assert content[12].text == "Overwritten: Overwrite global param" + assert content[13].text == "Local Test section 2" + assert content[16].text == "Some postfix stuff" assert len(document_data.headings) == 1 assert document_data.headings[0].id == "ATSY-18305" assert document_data.headings[0].title == "Keep Heading" +def test_create_full_authority_document_text_work_items( + empty_polarion_worker: polarion_worker.CapellaPolarionWorker, + model: capellambse.MelodyModel, +): + renderer = document_renderer.DocumentRenderer( + empty_polarion_worker.polarion_data_repo, model + ) + + document_data = renderer.render_document( + DOCUMENT_TEMPLATES, + DOCUMENT_TEXT_WORK_ITEMS, + "_default", + "TEST-DOC", + text_work_item_provider=text_work_item_provider.TextWorkItemProvider( + "MyField", + "MyType", + ), + ) + + assert len(document_data.text_work_item_provider.new_text_work_items) == 2 + assert ( + document_data.text_work_item_provider.new_text_work_items["id1"].id + is None + ) + assert ( + document_data.text_work_item_provider.new_text_work_items["id1"].type + == "MyType" + ) + assert ( + document_data.text_work_item_provider.new_text_work_items[ + "id1" + ].additional_attributes["MyField"] + == "id1" + ) + assert ( + document_data.text_work_item_provider.new_text_work_items["id2"].id + is None + ) + assert ( + document_data.text_work_item_provider.new_text_work_items["id2"].type + == "MyType" + ) + assert ( + document_data.text_work_item_provider.new_text_work_items[ + "id2" + ].additional_attributes["MyField"] + == "id2" + ) + + +def test_update_full_authority_document_text_work_items( + empty_polarion_worker: polarion_worker.CapellaPolarionWorker, + model: capellambse.MelodyModel, +): + renderer = document_renderer.DocumentRenderer( + empty_polarion_worker.polarion_data_repo, model + ) + old_doc = polarion_api.Document( + module_folder="_default", + module_name="TEST-DOC", + home_page_content=polarion_api.TextContent( + type="text/html", + value="", + ), + ) + + document_data = renderer.render_document( + DOCUMENT_TEMPLATES, + DOCUMENT_TEXT_WORK_ITEMS, + "_default", + "TEST-DOC", + document=old_doc, + text_work_item_provider=text_work_item_provider.TextWorkItemProvider( + "MyField", + "MyType", + [ + polarion_api.WorkItem( + id="EXISTING", additional_attributes={"MyField": "id1"} + ) + ], + ), + ) + + assert len(document_data.text_work_item_provider.new_text_work_items) == 2 + assert ( + document_data.text_work_item_provider.new_text_work_items["id1"].id + == "EXISTING" + ) + assert ( + document_data.text_work_item_provider.new_text_work_items["id1"].type + is None + ) + assert ( + document_data.text_work_item_provider.new_text_work_items[ + "id1" + ].additional_attributes["MyField"] + == "id1" + ) + assert ( + document_data.text_work_item_provider.new_text_work_items["id2"].id + is None + ) + assert ( + document_data.text_work_item_provider.new_text_work_items["id2"].type + == "MyType" + ) + assert ( + document_data.text_work_item_provider.new_text_work_items[ + "id2" + ].additional_attributes["MyField"] + == "id2" + ) + + def test_render_all_documents_partially_successfully( empty_polarion_worker: polarion_worker.CapellaPolarionWorker, model: capellambse.MelodyModel, diff --git a/tests/test_polarion_worker_documents.py b/tests/test_polarion_worker_documents.py new file mode 100644 index 00000000..561c9fc3 --- /dev/null +++ b/tests/test_polarion_worker_documents.py @@ -0,0 +1,178 @@ +# Copyright DB InfraGO AG and contributors +# SPDX-License-Identifier: Apache-2.0 + +import polarion_rest_api_client as polarion_api + +from capella2polarion import data_models +from capella2polarion.connectors import polarion_worker +from capella2polarion.converters import text_work_item_provider + +from .conftest import DOCUMENT_TEMPLATES, DOCUMENT_TEXT_WORK_ITEMS + + +def _set_work_item_id(work_items: list[polarion_api.WorkItem]): + for index, work_item in enumerate(work_items): + work_item.id = f"id{index}" + + +def test_update_document( + empty_polarion_worker: polarion_worker.CapellaPolarionWorker, +): + path = DOCUMENT_TEMPLATES / DOCUMENT_TEXT_WORK_ITEMS + document = polarion_api.Document( + module_folder="_default", + module_name="TEST-DOC", + rendering_layouts=[], + home_page_content=polarion_api.TextContent( + type="text/html", + value=path.read_text("utf-8"), + ), + ) + document_data = data_models.DocumentData( + document, + [], + text_work_item_provider.TextWorkItemProvider( + "MyField", + "MyType", + [ + polarion_api.WorkItem( + id="EXISTING", additional_attributes={"MyField": "id1"} + ), + ], + ), + ) + document_data.text_work_item_provider.generate_text_work_items( + document.home_page_content.value + ) + empty_polarion_worker.project_client.work_items.create.side_effect = ( + _set_work_item_id + ) + + empty_polarion_worker.update_documents([document_data]) + + assert document.home_page_content.value.endswith( + '
\n' + '
' + ) + assert ( + empty_polarion_worker.project_client.documents.update.call_count == 1 + ) + assert ( + empty_polarion_worker.project_client.documents.update.call_args.args[0] + == [document] + ) + assert ( + empty_polarion_worker.project_client.work_items.create.call_count == 1 + ) + assert ( + len( + empty_polarion_worker.project_client.work_items.create.call_args.args[ + 0 + ] + ) + == 1 + ) + assert ( + empty_polarion_worker.project_client.work_items.update.call_count == 2 + ) + assert ( + len( + empty_polarion_worker.project_client.work_items.update.call_args_list[ + 0 + ].args[ + 0 + ] + ) + == 1 + ) + assert ( + len( + empty_polarion_worker.project_client.work_items.update.call_args_list[ + 1 + ].args[ + 0 + ] + ) + == 0 + ) + + +def test_create_document( + empty_polarion_worker: polarion_worker.CapellaPolarionWorker, +): + path = DOCUMENT_TEMPLATES / DOCUMENT_TEXT_WORK_ITEMS + document = polarion_api.Document( + module_folder="_default", + module_name="TEST-DOC", + rendering_layouts=[], + home_page_content=polarion_api.TextContent( + type="text/html", + value=path.read_text("utf-8"), + ), + ) + document_data = data_models.DocumentData( + document, + [], + text_work_item_provider.TextWorkItemProvider( + "MyField", + "MyType", + ), + ) + document_data.text_work_item_provider.generate_text_work_items( + document.home_page_content.value + ) + empty_polarion_worker.project_client.work_items.create.side_effect = ( + _set_work_item_id + ) + + empty_polarion_worker.update_documents([document_data]) + + assert document.home_page_content.value.endswith( + '
\n' + '
' + ) + assert ( + empty_polarion_worker.project_client.documents.update.call_count == 1 + ) + assert ( + empty_polarion_worker.project_client.documents.update.call_args.args[0] + == [document] + ) + assert ( + empty_polarion_worker.project_client.work_items.create.call_count == 1 + ) + assert ( + len( + empty_polarion_worker.project_client.work_items.create.call_args.args[ + 0 + ] + ) + == 2 + ) + assert ( + empty_polarion_worker.project_client.work_items.update.call_count == 2 + ) + assert ( + len( + empty_polarion_worker.project_client.work_items.update.call_args_list[ + 0 + ].args[ + 0 + ] + ) + == 0 + ) + assert ( + len( + empty_polarion_worker.project_client.work_items.update.call_args_list[ + 1 + ].args[ + 0 + ] + ) + == 0 + )