Skip to content

Commit

Permalink
feat: Add support to create work items in documents and get informati…
Browse files Browse the repository at this point in the history
…on about the home document of a work item (#48)
  • Loading branch information
micha91 authored Sep 20, 2024
1 parent 24943fa commit e32a027
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 0 deletions.
25 changes: 25 additions & 0 deletions polarion_rest_api_client/clients/work_items.py
Original file line number Diff line number Diff line change
Expand Up @@ -330,12 +330,30 @@ def _build_work_item_post_request(
return api_models.WorkitemsListPostRequestDataItem(
type=api_models.WorkitemsListPostRequestDataItemType.WORKITEMS,
attributes=attrs,
# pylint: disable=line-too-long
relationships=(
api_models.WorkitemsListPostRequestDataItemRelationships(
module=api_models.WorkitemsListPostRequestDataItemRelationshipsModule(
data=api_models.WorkitemsListPostRequestDataItemRelationshipsModuleData(
id=f"{self._project_id}/{doc_ref.module_folder}/{doc_ref.module_name}",
type=api_models.WorkitemsListPostRequestDataItemRelationshipsModuleDataType.DOCUMENTS,
),
)
)
if (doc_ref := work_item.home_document) is not None
else oa_types.UNSET
),
# pylint: enable=line-too-long
)

def _build_work_item_patch_request(
self, work_item: dm.WorkItem
) -> api_models.WorkitemsSinglePatchRequest:
attrs = api_models.WorkitemsSinglePatchRequestDataAttributes()
if work_item.home_document:
logger.warning(
"Changing the work items home document is not supported."
)

if work_item.title is not None:
attrs.title = work_item.title
Expand Down Expand Up @@ -417,12 +435,18 @@ def _generate_work_item(
work_item_id = work_item.id.split("/")[-1]
links = []
attachments = []
home_document: dm.DocumentReference | None = None

# We set both truncated flags to True and will only set them to False,
# if the corresponding fields were requested and returned completely
links_truncated = True
attachments_truncated = True
if work_item.relationships:
if home_document_data := work_item.relationships.module:
if home_document_data.data and home_document_data.data.id:
_, folder, name = home_document_data.data.id.split("/")
home_document = dm.DocumentReference(folder, name)

if link_data := work_item.relationships.linked_work_items:
if (
not link_data.meta
Expand Down Expand Up @@ -476,4 +500,5 @@ def _generate_work_item(
attachments,
links_truncated,
attachments_truncated,
home_document,
)
17 changes: 17 additions & 0 deletions polarion_rest_api_client/data_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

__all__ = [
"Document",
"DocumentReference",
"Layouter",
"RenderingLayout",
"RenderingProperties",
Expand Down Expand Up @@ -85,6 +86,14 @@ def get_current_checksum(self) -> str | None:
return self._checksum


@dataclasses.dataclass
class DocumentReference:
"""A reference to a document to be used in relations."""

module_folder: str
module_name: str


class WorkItem(StatusItem):
"""A data class containing all relevant data of a Polarion WorkItem."""

Expand All @@ -96,6 +105,7 @@ class WorkItem(StatusItem):
attachments: list[WorkItemAttachment] = []
linked_work_items_truncated: bool = False
attachments_truncated: bool = False
home_document: DocumentReference | None = None

def __init__(
self,
Expand All @@ -110,6 +120,7 @@ def __init__(
attachments: list[WorkItemAttachment] | None = None,
linked_work_items_truncated: bool = False,
attachments_truncated: bool = False,
home_document: DocumentReference | None = None,
**kwargs,
):
super().__init__(id, type, status)
Expand All @@ -122,6 +133,7 @@ def __init__(
self.attachments = attachments or []
self.linked_work_items_truncated = linked_work_items_truncated
self.attachments_truncated = attachments_truncated
self.home_document = home_document

def __getattribute__(self, item: str) -> t.Any:
"""Return all non WorkItem attributes from additional_properties."""
Expand Down Expand Up @@ -175,6 +187,11 @@ def to_dict(self) -> dict[str, t.Any]:
"attachments": [
dataclasses.asdict(at) for at in sorted_attachments
],
"home_document": (
dataclasses.asdict(self.home_document)
if self.home_document
else None
),
}

def calculate_checksum(self) -> str:
Expand Down
1 change: 1 addition & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ def fixture_dummy_work_item_attachment():
TEST_REQUESTS / "patch_work_item_completely.json"
)
TEST_WI_MULTI_POST_REQUEST = TEST_REQUESTS / "post_workitems.json"
TEST_WI_MULTI_POST_REQUEST_IN_DOC = TEST_REQUESTS / "post_workitem_in_doc.json"
TEST_WI_POST_REQUEST = TEST_REQUESTS / "post_workitem.json"
TEST_WI_NO_NEXT_PAGE_RESPONSE = TEST_RESPONSES / "workitems_no_next_page.json"
TEST_WI_CREATED_RESPONSE = TEST_RESPONSES / "created_work_items.json"
Expand Down
24 changes: 24 additions & 0 deletions tests/data/expected_requests/post_workitem_in_doc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"data": [
{
"type": "workitems",
"attributes": {
"description": {
"type": "text/html",
"value": "My text value"
},
"status": "open",
"title": "Title",
"type": "task",
"capella_uuid": "asdfg"
},
"relationships": {
"module": {
"data": {
"id": "PROJ/space/document", "type": "documents"
}
}
}
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Copyright DB InfraGO AG and contributors
SPDX-License-Identifier: Apache-2.0
29 changes: 29 additions & 0 deletions tests/test_client_workitems.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
TEST_WI_DELETE_REQUEST,
TEST_WI_ERROR_NEXT_PAGE_RESPONSE,
TEST_WI_MULTI_POST_REQUEST,
TEST_WI_MULTI_POST_REQUEST_IN_DOC,
TEST_WI_NEXT_PAGE_RESPONSE,
TEST_WI_NO_NEXT_PAGE_RESPONSE,
TEST_WI_NOT_TRUNCATED_RESPONSE,
Expand Down Expand Up @@ -54,6 +55,8 @@ def test_get_one_work_item(
assert "test_custom_field" in work_item.additional_attributes
assert work_item.attachments_truncated is True
assert work_item.linked_work_items_truncated is True
assert work_item.home_document.module_folder == "MySpaceId"
assert work_item.home_document.module_name == "MyDocumentId"


def test_get_one_work_item_not_truncated(
Expand Down Expand Up @@ -159,6 +162,8 @@ def test_get_all_work_items_single_page(
)
assert "checksum" not in work_items[0].additional_attributes
assert work_items[0].get_current_checksum() == "123"
assert work_items[0].home_document.module_folder == "MySpaceId"
assert work_items[0].home_document.module_name == "MyDocumentId"


def test_get_all_work_items_faulty_item(
Expand Down Expand Up @@ -239,6 +244,30 @@ def test_create_work_items_successfully(
assert json.loads(req.content.decode()) == expected


def test_create_work_item_in_document(
client: polarion_api.OpenAPIPolarionProjectClient,
httpx_mock: pytest_httpx.HTTPXMock,
work_item: polarion_api.WorkItem,
):
with open(TEST_WI_CREATED_RESPONSE, encoding="utf8") as f:
mock_response = json.load(f)

httpx_mock.add_response(201, json=mock_response)

work_item.home_document = polarion_api.DocumentReference(
"space", "document"
)
client.create_work_items([work_item])

req = httpx_mock.get_request()

assert req is not None and req.method == "POST"
with open(TEST_WI_MULTI_POST_REQUEST_IN_DOC, encoding="utf8") as f:
expected = json.load(f)

assert json.loads(req.content.decode()) == expected


def test_create_work_items_batch_exceed_successfully(
client: polarion_api.OpenAPIPolarionProjectClient,
httpx_mock: pytest_httpx.HTTPXMock,
Expand Down

0 comments on commit e32a027

Please sign in to comment.