diff --git a/capella2polarion/__main__.py b/capella2polarion/__main__.py index a0fd6105..6bd86257 100644 --- a/capella2polarion/__main__.py +++ b/capella2polarion/__main__.py @@ -115,6 +115,12 @@ def print_cli_state(capella2polarion_cli: Capella2PolarionCli) -> None: is_flag=True, default=True, ) +@click.option( + "--generate-figure-captions", + envvar="CAPELLA2POLARION_GENERATE_FIGURE_CAPTIONS", + is_flag=True, + default=False, +) @click.pass_context def synchronize( ctx: click.core.Context, @@ -123,6 +129,7 @@ def synchronize( type_prefix: str, role_prefix: str, grouped_links_custom_fields: bool, + generate_figure_captions: bool, ) -> None: """Synchronise model elements.""" capella_to_polarion_cli: Capella2PolarionCli = ctx.obj @@ -159,6 +166,7 @@ def synchronize( generate_links=True, generate_attachments=True, generate_grouped_links_custom_fields=grouped_links_custom_fields, + generate_figure_captions=generate_figure_captions, ) polarion_worker.compare_and_update_work_items(converter.converter_session) diff --git a/capella2polarion/converters/element_converter.py b/capella2polarion/converters/element_converter.py index 237e8f7d..56b94096 100644 --- a/capella2polarion/converters/element_converter.py +++ b/capella2polarion/converters/element_converter.py @@ -19,7 +19,7 @@ from capellambse import helpers as chelpers from capellambse import model as m from capellambse_context_diagrams import context -from lxml import etree +from lxml import etree, html from capella2polarion import data_model from capella2polarion.connectors import polarion_repo @@ -69,11 +69,13 @@ def __init__( capella_polarion_mapping: polarion_repo.PolarionDataRepository, converter_session: data_session.ConverterSession, generate_attachments: bool, + generate_figure_captions: bool = False, ): self.model = model self.capella_polarion_mapping = capella_polarion_mapping self.converter_session = converter_session self.generate_attachments = generate_attachments + self.generate_figure_captions = generate_figure_captions self.jinja_envs: dict[str, jinja2.Environment] = {} def serialize_all(self) -> list[data_model.CapellaWorkItem]: @@ -144,6 +146,7 @@ def _draw_diagram_svg( max_width: int, cls: str, render_params: dict[str, t.Any] | None = None, + caption: tuple[str, str] | None = None, ) -> tuple[str, data_model.CapellaDiagramAttachment | None]: file_name = f"{C2P_IMAGE_PREFIX}{file_name}.svg" @@ -161,7 +164,7 @@ def _draw_diagram_svg( return ( polarion_html_helper.generate_image_html( - title, file_name, max_width, cls + title, file_name, max_width, cls, caption ), attachment, ) @@ -201,6 +204,7 @@ def __insert_diagram( file_name: str, render_params: dict[str, t.Any] | None = None, max_width: int = 800, + caption: tuple[str, str] | None = None, ): if attachment := next( ( @@ -216,6 +220,7 @@ def __insert_diagram( attachment.file_name, max_width, JINJA_RENDERED_IMG_CLS, + caption, ) diagram_html, attachment = self._draw_diagram_svg( @@ -246,6 +251,11 @@ def _draw_additional_attributes_diagram( 650, "additional-attributes-diagram", render_params, + ( + ("Figure", f"{title} of {work_item.title}") + if self.generate_figure_captions + else None + ), ) if attachment: self._add_attachment(work_item, attachment) @@ -325,6 +335,17 @@ def repair_images(node: etree._Element) -> None: # We use the filename here as the ID is unknown here # This needs to be refactored after updating attachments node.attrib["src"] = f"workitemimg:{file_name}" + if self.generate_figure_captions: + caption = node.get( + "alt", f'Image "{file_url.stem}" of {obj.name}' + ) + node.addnext( + html.fromstring( + polarion_html_helper.POLARION_CAPTION.format( + label="Figure", caption=caption + ) + ) + ) except FileNotFoundError: self.converter_session[obj.uuid].errors.add( @@ -432,7 +453,17 @@ def _diagram( work_item_id = converter_data.work_item.id diagram_html, attachment = self._draw_diagram_svg( - diagram, "diagram", "Diagram", 750, "diagram", render_params + diagram, + "diagram", + "Diagram", + 750, + "diagram", + render_params, + ( + ("Figure", f"Diagram {diagram.name}") + if self.generate_figure_captions + else None + ), ) converter_data.work_item = data_model.CapellaWorkItem( diff --git a/capella2polarion/converters/model_converter.py b/capella2polarion/converters/model_converter.py index 13edbf62..07204c35 100644 --- a/capella2polarion/converters/model_converter.py +++ b/capella2polarion/converters/model_converter.py @@ -84,6 +84,7 @@ def generate_work_items( generate_links: bool = False, generate_attachments: bool = False, generate_grouped_links_custom_fields: bool = False, + generate_figure_captions: bool = False, ) -> dict[str, data_model.CapellaWorkItem]: """Return a work items mapping from model elements for Polarion. @@ -104,12 +105,15 @@ def generate_work_items( generate_grouped_links_custom_fields A boolean flag to control grouped links custom fields generation. + generate_figure_captions + A boolean flag to enable the generation of figure captions """ serializer = element_converter.CapellaWorkItemSerializer( self.model, polarion_data_repo, self.converter_session, generate_attachments, + generate_figure_captions, ) work_items = serializer.serialize_all() for work_item in work_items: diff --git a/capella2polarion/converters/polarion_html_helper.py b/capella2polarion/converters/polarion_html_helper.py index 1d26a058..8fa58bba 100644 --- a/capella2polarion/converters/polarion_html_helper.py +++ b/capella2polarion/converters/polarion_html_helper.py @@ -37,6 +37,11 @@ "params=id={pid}|layout={lid}|{custom_info}external=true" '|project={project}">' ) +POLARION_CAPTION = ( + '

\n ' + '{label} # {caption}\n

' +) RE_DESCR_DELETED_PATTERN = re.compile( f"<deleted element ({chelpers.RE_VALID_UUID.pattern})>" ) @@ -52,7 +57,11 @@ def strike_through(string: str) -> str: def generate_image_html( - title: str, attachment_id: str, max_width: int, cls: str + title: str, + attachment_id: str, + max_width: int, + cls: str, + caption: tuple[str, str] | None = None, ) -> str: """Generate an image as HTMl with the given source.""" description = ( @@ -60,6 +69,10 @@ def generate_image_html( f'src="workitemimg:{attachment_id}" ' f'style="max-width: {max_width}px;"/>' ) + if caption: + description += POLARION_CAPTION.format( + label=caption[0], caption=caption[1] + ) return description diff --git a/tests/data/model/Melody Model Test.afm b/tests/data/model/Melody Model Test.afm index 02f4486c..ca9e0093 100644 --- a/tests/data/model/Melody Model Test.afm +++ b/tests/data/model/Melody Model Test.afm @@ -1,6 +1,6 @@ - - - + + + diff --git a/tests/data/model/Melody Model Test.aird b/tests/data/model/Melody Model Test.aird index 513cb8f7..6e389c75 100644 --- a/tests/data/model/Melody Model Test.aird +++ b/tests/data/model/Melody Model Test.aird @@ -1,6 +1,6 @@ - - + + Melody%20Model%20Test.afm Melody%20Model%20Test.capella @@ -8,74 +8,74 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - +
@@ -83,7 +83,7 @@ - +
@@ -97,19 +97,19 @@ - + - + - + - + @@ -119,38 +119,38 @@ - + - + - + - + - + - + - + - +
@@ -158,15 +158,15 @@ - + - + - +
@@ -174,7 +174,7 @@ - + @@ -1583,6 +1583,7 @@ + @@ -1868,6 +1869,7 @@ + @@ -2884,7 +2886,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -2896,7 +2898,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -2915,7 +2917,7 @@ - + @@ -2927,7 +2929,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -2935,7 +2937,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -2950,7 +2952,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -2958,7 +2960,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -2985,7 +2987,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -2997,7 +2999,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -3019,7 +3021,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -3031,7 +3033,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -3039,7 +3041,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + italic @@ -3057,7 +3059,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -3069,7 +3071,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -3078,7 +3080,7 @@ - + @@ -3101,7 +3103,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -3109,7 +3111,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -3128,7 +3130,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -3147,7 +3149,7 @@ - + @@ -3155,7 +3157,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -3167,7 +3169,7 @@ - + @@ -3175,7 +3177,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -3192,7 +3194,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -3211,7 +3213,7 @@ - + @@ -3219,7 +3221,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + uid @@ -3235,7 +3237,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -3243,7 +3245,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -3280,7 +3282,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -3292,7 +3294,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -3301,7 +3303,7 @@ - + @@ -3323,7 +3325,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -3335,7 +3337,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -3343,7 +3345,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -3360,7 +3362,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -3372,7 +3374,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -3394,7 +3396,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -3402,7 +3404,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -3417,7 +3419,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -3429,7 +3431,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -3437,7 +3439,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -3900,7 +3902,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -3908,7 +3910,7 @@ - + @@ -3916,7 +3918,7 @@ - + @@ -3924,7 +3926,7 @@ - + @@ -3932,7 +3934,7 @@ - + @@ -3943,7 +3945,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -3954,7 +3956,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -3962,7 +3964,7 @@ - + @@ -3985,13 +3987,13 @@ - + KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -4502,7 +4504,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + borderColor borderSize @@ -4516,7 +4518,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -4527,7 +4529,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + borderColor borderSize @@ -4540,7 +4542,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -4561,7 +4563,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + labelAlignment @@ -4573,7 +4575,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + borderColor borderSize labelColor @@ -4587,7 +4589,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + labelFormat strike_through @@ -4600,7 +4602,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + labelFormat underline @@ -4613,7 +4615,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + labelFormat borderColor borderSize @@ -4629,7 +4631,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + labelAlignment @@ -4641,7 +4643,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + borderColor borderSize @@ -5291,7 +5293,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -5302,7 +5304,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -5310,7 +5312,7 @@ - + @@ -5321,7 +5323,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -5332,7 +5334,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -5343,7 +5345,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -5354,7 +5356,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -5365,7 +5367,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -5373,7 +5375,7 @@ - + @@ -5384,7 +5386,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -5395,7 +5397,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -5406,7 +5408,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -5417,7 +5419,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -5428,7 +5430,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -5439,7 +5441,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -5482,7 +5484,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -5661,7 +5663,7 @@ - + @@ -5669,7 +5671,7 @@ - + @@ -5677,7 +5679,7 @@ - + @@ -5685,7 +5687,7 @@ - + @@ -6049,7 +6051,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -6068,7 +6070,7 @@ - + @@ -6076,7 +6078,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -6088,7 +6090,7 @@ - + @@ -6096,7 +6098,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -7482,7 +7484,7 @@ - + @@ -7587,7 +7589,7 @@ - + @@ -7800,7 +7802,7 @@ - + @@ -8074,7 +8076,7 @@ - + @@ -8096,7 +8098,7 @@ - + @@ -8235,7 +8237,7 @@ - + @@ -8256,7 +8258,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -8462,7 +8464,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -8517,7 +8519,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -8541,7 +8543,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -8551,7 +8553,7 @@ - + @@ -8972,50 +8974,50 @@ - + KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + - + KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + - + KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + - + KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -9123,6 +9125,7 @@ + @@ -9874,7 +9877,7 @@ - + @@ -9898,7 +9901,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -9910,7 +9913,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -9935,7 +9938,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -9947,7 +9950,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -10005,7 +10008,7 @@ - + @@ -10029,7 +10032,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -10098,7 +10101,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -10110,7 +10113,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -10119,7 +10122,7 @@ - + @@ -10190,7 +10193,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -10199,7 +10202,7 @@ - + @@ -11204,24 +11207,24 @@ - + KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + - + KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -11304,13 +11307,13 @@ - + KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -11965,23 +11968,23 @@ - + - + - + KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -12354,16 +12357,16 @@ - + - + - + @@ -12371,12 +12374,12 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + - + @@ -12384,36 +12387,36 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + - + KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + - + KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + - + @@ -12421,12 +12424,12 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + - + @@ -12434,12 +12437,12 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + - + @@ -12447,12 +12450,12 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + - + @@ -12460,12 +12463,12 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + - + @@ -12473,12 +12476,12 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + - + @@ -12486,12 +12489,12 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + - + @@ -12499,12 +12502,12 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + - + @@ -12512,12 +12515,12 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + - + @@ -12525,7 +12528,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -12564,10 +12567,10 @@ - + - + labelColor @@ -12662,62 +12665,62 @@ - + KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + - + KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + - + KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + - + KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + - + KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + @@ -12857,7 +12860,7 @@ - + @@ -12878,7 +12881,7 @@ KEEP_LOCATION KEEP_SIZE KEEP_RATIO - + diff --git a/tests/data/model/Melody Model Test.capella b/tests/data/model/Melody Model Test.capella index 7ea8f5e2..635c7d52 100644 --- a/tests/data/model/Melody Model Test.capella +++ b/tests/data/model/Melody Model Test.capella @@ -1,24 +1,24 @@ - + @@ -1248,7 +1248,7 @@ The predator is far away + id="e76aa1f5-cc12-4885-a8c2-a0022b061549" name="Example" description="<p><img alt="Other Text used as Caption" src="model/grouped_linked_work_items.png" /></p> <p>Test</p> "/> \n ' + 'Figure ' + "# Diagram [CC] Capability\n

" + ) + @staticmethod def test_delete_diagrams(diagr_base_object: BaseObjectContainer): pw = diagr_base_object.pw @@ -2171,3 +2201,40 @@ def test_read_config_links(caplog: pytest.LogCaptureFixture): link_field="output_exchanges", reverse_field="output_exchanges_reverse", ) + + @staticmethod + def test_add_context_diagram_with_caption(model: capellambse.MelodyModel): + uuid = "11906f7b-3ae9-4343-b998-95b170be2e2b" + type_config = converter_config.CapellaTypeConfig( + "test", "add_context_diagram", [] + ) + serializer = element_converter.CapellaWorkItemSerializer( + model, + polarion_repo.PolarionDataRepository(), + { + uuid: data_session.ConverterData( + "pa", + type_config, + model.by_uuid(uuid), + ) + }, + True, + generate_figure_captions=True, + ) + + work_item = serializer.serialize(uuid) + + assert work_item is not None + assert "context_diagram" in work_item.additional_attributes + assert str( + work_item.additional_attributes["context_diagram"]["value"] + ) == TEST_DIAG_DESCR.format( + title="Context Diagram", + attachment_id="__C2P__context_diagram.svg", + width=650, + cls="additional-attributes-diagram", + ) + ( + '

\n ' + 'Figure ' + "# Context Diagram of PhysicalFunction 3\n

" + ) diff --git a/tests/test_workitem_attachments.py b/tests/test_workitem_attachments.py index e568df03..4c19f99d 100644 --- a/tests/test_workitem_attachments.py +++ b/tests/test_workitem_attachments.py @@ -620,3 +620,49 @@ def test_diagram_delete_attachments( assert len(work_item.additional_attributes) == 1 assert work_item.title is None assert work_item.checksum == DIAGRAM_CHECKSUM + + +def test_attached_image_in_description_with_caption( + model: capellambse.MelodyModel, + worker: polarion_worker.CapellaPolarionWorker, +): + uuid = "e76aa1f5-cc12-4885-a8c2-a0022b061549" + converter = model_converter.ModelConverter(model, "TEST") + worker.polarion_data_repo = polarion_repo.PolarionDataRepository( + [data_model.CapellaWorkItem(WORKITEM_ID, uuid_capella=uuid)] + ) + + converter.converter_session[uuid] = data_session.ConverterData( + "", + converter_config.CapellaTypeConfig("test"), + model.by_uuid(uuid), + ) + + worker.project_client.work_items.attachments.create = mock.MagicMock() + worker.project_client.work_items.attachments.create.side_effect = ( + set_attachment_ids + ) + + converter.generate_work_items( + worker.polarion_data_repo, False, True, False, True + ) + worker.compare_and_update_work_item(converter.converter_session[uuid]) + + assert worker.project_client.work_items.update.call_count == 1 + assert worker.project_client.work_items.attachments.create.call_count == 1 + + created_attachments: list[polarion_api.WorkItemAttachment] = ( + worker.project_client.work_items.attachments.create.call_args.args[0] + ) + work_item: data_model.CapellaWorkItem = ( + worker.project_client.work_items.update.call_args.args[0] + ) + + assert len(created_attachments) == 1 + assert str(work_item.description.value) == ( + '

Other Text used as Caption

' + '

\n Figure ' + '#' + " Other Text used as Caption\n

\n\n

Test

\n" + )