mbu-dev-shared-components 2.4.3__tar.gz → 2.4.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/PKG-INFO +1 -1
  2. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/solteqtand/application/document.py +4 -2
  3. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components.egg-info/PKG-INFO +1 -1
  4. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components.egg-info/SOURCES.txt +0 -3
  5. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/pyproject.toml +1 -1
  6. mbu_dev_shared_components-2.4.3/mbu_dev_shared_components/tests/go_tests/go_integration_tests.py +0 -278
  7. mbu_dev_shared_components-2.4.3/mbu_dev_shared_components/tests/go_tests/objects_tests.py +0 -124
  8. mbu_dev_shared_components-2.4.3/mbu_dev_shared_components/tests/msoffice_tests/msoffice_integration_tests.py +0 -188
  9. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/LICENSE +0 -0
  10. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/README.md +0 -0
  11. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/database/__init__.py +0 -0
  12. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/database/constants.py +0 -0
  13. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/database/logging.py +0 -0
  14. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/database/utility.py +0 -0
  15. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/getorganized/__init__.py +0 -0
  16. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/getorganized/auth.py +0 -0
  17. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/getorganized/cases.py +0 -0
  18. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/getorganized/contacts.py +0 -0
  19. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/getorganized/documents.py +0 -0
  20. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/getorganized/objects.py +0 -0
  21. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/google/__init__.py +0 -0
  22. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/google/api/__init__.py +0 -0
  23. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/google/api/auth.py +0 -0
  24. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/google/workspace/__init__.py +0 -0
  25. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/google/workspace/alerts.py +0 -0
  26. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/msoffice365/__init__.py +0 -0
  27. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/msoffice365/excel/__init__.py +0 -0
  28. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/msoffice365/excel/excel_reader.py +0 -0
  29. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/msoffice365/sharepoint_api/__init__.py +0 -0
  30. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/msoffice365/sharepoint_api/files.py +0 -0
  31. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/os2forms/__init__.py +0 -0
  32. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/os2forms/documents.py +0 -0
  33. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/os2forms/forms.py +0 -0
  34. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/romexis/__init__.py +0 -0
  35. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/romexis/db_handler.py +0 -0
  36. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/romexis/helper_functions.py +0 -0
  37. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/sap/__init__.py +0 -0
  38. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/sap/create_invoice.py +0 -0
  39. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/solteqtand/__init__.py +0 -0
  40. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/solteqtand/application/__init__.py +0 -0
  41. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/solteqtand/application/app_handler.py +0 -0
  42. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/solteqtand/application/appointment.py +0 -0
  43. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/solteqtand/application/base_ui.py +0 -0
  44. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/solteqtand/application/clinic.py +0 -0
  45. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/solteqtand/application/edi_portal.py +0 -0
  46. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/solteqtand/application/event.py +0 -0
  47. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/solteqtand/application/exceptions.py +0 -0
  48. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/solteqtand/application/handler_base.py +0 -0
  49. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/solteqtand/application/journal_note.py +0 -0
  50. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/solteqtand/application/patient.py +0 -0
  51. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/solteqtand/database/__init__.py +0 -0
  52. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/solteqtand/database/db_handler.py +0 -0
  53. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/utils/__init__.py +0 -0
  54. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/utils/db_stored_procedure_executor.py +0 -0
  55. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/utils/fernet_encryptor.py +0 -0
  56. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/utils/file_handler.py +0 -0
  57. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/utils/json_handler.py +0 -0
  58. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components.egg-info/dependency_links.txt +0 -0
  59. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components.egg-info/requires.txt +0 -0
  60. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components.egg-info/top_level.txt +0 -0
  61. {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mbu_dev_shared_components
3
- Version: 2.4.3
3
+ Version: 2.4.5
4
4
  Summary: Shared components to use in RPA projects
5
5
  Author-email: MBU <rpa@mbu.aarhus.dk>
6
6
  License-Expression: MIT
@@ -171,7 +171,8 @@ class DocumentHandler(HandlerBase):
171
171
  if new_value != metadata['templateName']:
172
172
  raise ValueError(f"Failed to set the correct status. Expected '{metadata['templateName']}', but got '{new_value}'.")
173
173
 
174
- shutil.rmtree(folder_path, ignore_errors=True)
174
+ if os.path.exists(folder_path):
175
+ shutil.rmtree(folder_path, ignore_errors=True)
175
176
 
176
177
  form_mail_merge.PaneControl(AutomationId="ButtonMerge").GetLegacyIAccessiblePattern().DoDefaultAction()
177
178
 
@@ -230,7 +231,8 @@ class DocumentHandler(HandlerBase):
230
231
  print(f"Error while creating document from template: {e}")
231
232
  raise
232
233
  finally:
233
- shutil.rmtree(folder_path, ignore_errors=True)
234
+ if os.path.exists(folder_path):
235
+ shutil.rmtree(folder_path, ignore_errors=True)
234
236
 
235
237
  def send_discharge_document_digitalpost(self, metadata: dict) -> None:
236
238
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mbu_dev_shared_components
3
- Version: 2.4.3
3
+ Version: 2.4.5
4
4
  Summary: Shared components to use in RPA projects
5
5
  Author-email: MBU <rpa@mbu.aarhus.dk>
6
6
  License-Expression: MIT
@@ -49,9 +49,6 @@ mbu_dev_shared_components/solteqtand/application/journal_note.py
49
49
  mbu_dev_shared_components/solteqtand/application/patient.py
50
50
  mbu_dev_shared_components/solteqtand/database/__init__.py
51
51
  mbu_dev_shared_components/solteqtand/database/db_handler.py
52
- mbu_dev_shared_components/tests/go_tests/go_integration_tests.py
53
- mbu_dev_shared_components/tests/go_tests/objects_tests.py
54
- mbu_dev_shared_components/tests/msoffice_tests/msoffice_integration_tests.py
55
52
  mbu_dev_shared_components/utils/__init__.py
56
53
  mbu_dev_shared_components/utils/db_stored_procedure_executor.py
57
54
  mbu_dev_shared_components/utils/fernet_encryptor.py
@@ -8,7 +8,7 @@ build-backend = "setuptools.build_meta"
8
8
 
9
9
  [project]
10
10
  name = "mbu_dev_shared_components"
11
- version = "2.4.3" # Specify the version manually here
11
+ version = "2.4.5" # Specify the version manually here
12
12
  authors = [
13
13
  { name="MBU", email="rpa@mbu.aarhus.dk" },
14
14
  ]
@@ -1,278 +0,0 @@
1
- """
2
- Integration tests for the GetOrganized API.
3
-
4
- These tests validate the following key functionalities:
5
- 1. Authentication success using CPR lookup
6
- 2. Contact lookup returns correct citizen profile
7
- 3. Retrieval of metadata for a specific case (Borgermappe)
8
- 4. Case lookup using case properties
9
- 5. Document metadata retrieval
10
- 6. Document search (legacy and modern search APIs)
11
-
12
- Expected to run daily to ensure API stability and data consistency.
13
-
14
- Required environment variables:
15
- - GO_API_ENDPOINT: Base URL for GetOrganized API
16
- - GO_API_USERNAME: API username for authentication
17
- - GO_API_PASSWORD: API password
18
- - DADJ_FULL_NAME: Full name of test citizen
19
- - DADJ_SSN: CPR number of test citizen
20
- - DADJ_GO_ID: Internal ID of test citizen in GO
21
- - DADJ_BORGERMAPPE_SAGS_ID: Case ID of the test citizen's "Borgermappe"
22
- """
23
-
24
- import os
25
- import xml.etree.ElementTree as ET
26
- import requests
27
- import pytest
28
-
29
- from mbu_dev_shared_components.getorganized import contacts
30
- from mbu_dev_shared_components.getorganized import cases
31
- from mbu_dev_shared_components.getorganized import documents
32
- from mbu_dev_shared_components.getorganized import objects
33
-
34
-
35
- # -------------------------------
36
- # Helper to load environment vars safely
37
- # -------------------------------
38
- def _get_cfg(key: str) -> str:
39
- val = os.getenv(key)
40
-
41
- if not val:
42
- pytest.skip(f"env var '{key}' not set → skipping integration test")
43
-
44
- return val
45
-
46
-
47
- @pytest.fixture(scope="module")
48
- def go_env():
49
- """
50
- Loads required environment variables for the GetOrganized API tests.
51
- Skips tests if any required variable is missing.
52
- """
53
-
54
- return {
55
- "endpoint": _get_cfg("GO_API_ENDPOINT"),
56
- "username": _get_cfg("GO_API_USERNAME"),
57
- "password": _get_cfg("GO_API_PASSWORD"),
58
- "full_name": _get_cfg("DADJ_FULL_NAME"),
59
- "ssn": _get_cfg("DADJ_SSN"),
60
- "go_id": _get_cfg("DADJ_GO_ID"),
61
- "case_id": _get_cfg("DADJ_BORGERMAPPE_SAGS_ID"),
62
- }
63
-
64
-
65
- def test_authentication_success(go_env):
66
- """
67
- Ensures valid credentials can access the API without 401/403.
68
- """
69
-
70
- resp = contacts.contact_lookup(
71
- person_ssn=go_env["ssn"],
72
- api_endpoint=f"{go_env['endpoint']}/_goapi/contacts/readitem",
73
- api_username=go_env["username"],
74
- api_password=go_env["password"],
75
- )
76
-
77
- assert resp.status_code != 401
78
- assert resp.status_code != 403
79
- assert resp.ok
80
-
81
-
82
- def test_contact_lookup_returns_expected_name(go_env):
83
- """
84
- Verifies that contact lookup returns correct full name, ID, and CPR.
85
- """
86
-
87
- resp = contacts.contact_lookup(
88
- person_ssn=go_env["ssn"],
89
- api_endpoint=f"{go_env['endpoint']}/_goapi/contacts/readitem",
90
- api_username=go_env["username"],
91
- api_password=go_env["password"],
92
- )
93
-
94
- assert resp.ok
95
-
96
- data = resp.json()
97
-
98
- assert data["FullName"] == go_env["full_name"]
99
- assert data["ID"] == go_env["go_id"]
100
- assert data["CPR"] == go_env["ssn"]
101
-
102
-
103
- def test_case_metadata_structure(go_env):
104
- """
105
- Validates the metadata structure of a known 'Borgermappe' case.
106
- """
107
-
108
- resp = cases.get_case_metadata(
109
- api_endpoint=f"{go_env['endpoint']}/_goapi/Cases/Metadata/{go_env['case_id']}",
110
- api_username=go_env["username"],
111
- api_password=go_env["password"],
112
- )
113
-
114
- assert resp.ok
115
-
116
- # Extract XML metadata and parse attributes
117
- resp_metadata_xml = resp.json().get("Metadata")
118
-
119
- assert resp_metadata_xml
120
-
121
- data = ET.fromstring(resp_metadata_xml).attrib
122
-
123
- assert data["ows_CaseID"] == go_env["case_id"]
124
-
125
- assert data["ows_CaseCategory"] == "Borgermappe"
126
-
127
- assert data["ows_CCMContactData"] == f"{go_env['full_name']};#{go_env['go_id']};#{go_env['ssn']};#;#"
128
-
129
- assert data["ows_CCMContactData_CPR"] == go_env["ssn"]
130
-
131
-
132
- def test_find_case_by_case_properties(go_env):
133
- """
134
- Searches for a case using known properties of the test citizen.
135
- """
136
-
137
- case_data_json = objects.CaseDataJson()
138
-
139
- case_data = case_data_json.search_citizen_folder_data_json(
140
- case_type_prefix="BOR",
141
- person_full_name=go_env["full_name"],
142
- person_id=go_env["go_id"],
143
- person_ssn=go_env["ssn"]
144
- )
145
-
146
- resp = cases.find_case_by_case_properties(
147
- case_data=case_data,
148
- api_endpoint=f"{go_env['endpoint']}/_goapi/Cases/FindByCaseProperties",
149
- api_username=go_env["username"],
150
- api_password=go_env["password"],
151
- )
152
-
153
- assert resp.ok
154
-
155
- data = resp.json().get("CasesInfo")
156
-
157
- assert isinstance(data, list)
158
-
159
- assert len(data) == 1
160
-
161
- assert data[0].get("CaseID") == go_env["case_id"]
162
-
163
-
164
- def test_get_document_metadata(go_env):
165
- """
166
- Fetches metadata for a known document tied to the test citizen.
167
- """
168
- document_id = 14583373 # ID must be valid for test profile
169
-
170
- resp = documents.get_document_metadata(
171
- api_endpoint=f"{go_env['endpoint']}/_goapi/Documents/Metadata/{document_id}",
172
- api_username=go_env["username"],
173
- api_password=go_env["password"],
174
- )
175
-
176
- assert resp.ok
177
-
178
- data = ET.fromstring(resp.json().get("Metadata")).attrib
179
-
180
- assert "ows_Title" in data
181
-
182
-
183
- def test_search_documents(go_env):
184
- """
185
- Performs a legacy document search using full name + CPR.
186
- """
187
-
188
- search_term = f"{go_env['full_name']} {go_env['ssn']}"
189
-
190
- resp = documents.search_documents(
191
- search_term=search_term,
192
- api_endpoint=f"{go_env['endpoint']}/_goapi/Search/Results",
193
- api_username=go_env["username"],
194
- api_password=go_env["password"],
195
- )
196
-
197
- assert resp.ok
198
-
199
- results = resp.json().get("Rows").get("Results")
200
- total_rows = resp.json().get("TotalRows")
201
-
202
- assert isinstance(results, list)
203
-
204
- if total_rows == 0:
205
- assert len(results) == 0
206
-
207
- else:
208
- assert len(results) == total_rows
209
-
210
- for doc in results:
211
- assert "title" in doc
212
- assert "created" in doc
213
- assert "caseid" in doc
214
-
215
-
216
- def _validate_modern_search_response(resp: requests.Response):
217
- """
218
- Helper: Validates structure of modern search response.
219
- """
220
-
221
- assert resp.ok
222
-
223
- json_data = resp.json()
224
-
225
- results = json_data.get("results", {}).get("Results", [])
226
-
227
- total_rows = json_data.get("totalRows")
228
-
229
- assert isinstance(results, list)
230
-
231
- if total_rows == 0:
232
- assert len(results) == 0
233
-
234
- else:
235
- assert len(results) == total_rows
236
- for doc in results:
237
-
238
- assert "title" in doc
239
- assert "created" in doc
240
- assert "caseid" in doc
241
-
242
-
243
- def test_modern_search(go_env):
244
- """
245
- Runs two modern searches: one without date filter, one with date filter.
246
- """
247
-
248
- search_term = f"{go_env['full_name']} {go_env['ssn']}"
249
-
250
- # Search 1: All-time
251
- resp_1 = documents.modern_search(
252
- page_index=0,
253
- search_term=search_term,
254
- start_date=None,
255
- end_date=None,
256
- only_items=False,
257
- case_type_prefix="BOR",
258
- api_endpoint=f"{go_env['endpoint']}/_goapi/search/ExecuteModernSearch",
259
- api_username=go_env["username"],
260
- api_password=go_env["password"],
261
- )
262
-
263
- # Search 2: Specific March 2025 range
264
- resp_2 = documents.modern_search(
265
- page_index=0,
266
- search_term=search_term,
267
- start_date="2025-03-01",
268
- end_date="2025-03-31",
269
- only_items=False,
270
- case_type_prefix="BOR",
271
- api_endpoint=f"{go_env['endpoint']}/_goapi/search/ExecuteModernSearch",
272
- api_username=go_env["username"],
273
- api_password=go_env["password"],
274
- )
275
-
276
- _validate_modern_search_response(resp_1)
277
-
278
- _validate_modern_search_response(resp_2)
@@ -1,124 +0,0 @@
1
- """
2
- Unit tests for data structure creation methods in CaseDataJson.
3
- These are pure functions that return formatted dictionaries, used in API requests.
4
-
5
- Should run on pull requests to ensure the data structure is correct.
6
- """
7
-
8
- import pytest
9
- from mbu_dev_shared_components.getorganized.objects import CaseDataJson
10
-
11
-
12
- @pytest.fixture
13
- def case_data_handler():
14
- """
15
- Fixture to provide an instance of CaseDataJson for testing.
16
- """
17
- return CaseDataJson()
18
-
19
-
20
- def test_search_citizen_folder_data_json(case_data_handler: CaseDataJson):
21
- """
22
- Ensure that the search_citizen_folder_data_json method correctly builds
23
- a search structure for a citizen's full data and filters by 'Borgermappe' case category.
24
- """
25
-
26
- result = case_data_handler.search_citizen_folder_data_json(
27
- case_type_prefix="BOR",
28
- person_full_name="Test Person",
29
- person_id="12345",
30
- person_ssn="0101011234"
31
- )
32
-
33
- assert result["LogicalOperator"] == "AND"
34
- assert result["ExcludeDeletedCases"] == "True"
35
- assert result["ReturnCasesNumber"] == "1"
36
-
37
- assert {
38
- "InternalName": "ows_CCMContactData",
39
- "Value": "Test Person;#12345;#0101011234;#;#",
40
- "DataType": "Text",
41
- "ComparisonType": "Equal",
42
- "IsMultiValue": "False"
43
- } in result["FieldProperties"]
44
-
45
- assert {
46
- "InternalName": "ows_CaseCategory",
47
- "Value": "Borgermappe",
48
- "DataType": "Text",
49
- "ComparisonType": "Equal",
50
- "IsMultiValue": "False"
51
- } in result["FieldProperties"]
52
-
53
-
54
- def test_generic_search_case_data_json_with_name_and_extra_field(case_data_handler: CaseDataJson):
55
- """
56
- Ensure that generic_search_case_data_json assembles a correct structure when using:
57
- - a custom case_type_prefix,
58
- - a non-default number of return cases,
59
- - full citizen data,
60
- - and extra field properties.
61
- """
62
-
63
- field_properties = {
64
- "ows_Title": "Lønbilag"
65
- }
66
-
67
- result = case_data_handler.generic_search_case_data_json(
68
- case_type_prefix="PER",
69
- person_full_name="Test Person",
70
- person_id="12345",
71
- person_ssn="0101011234",
72
- include_name=True,
73
- returned_cases_number="5",
74
- field_properties=field_properties
75
- )
76
-
77
- assert result["CaseTypePrefixes"] == ["PER"]
78
-
79
- assert {
80
- "InternalName": "ows_CCMContactData",
81
- "Value": "Test Person;#12345;#0101011234;#;#",
82
- "DataType": "Text",
83
- "ComparisonType": "Equal",
84
- "IsMultiValue": "False"
85
- } in result["FieldProperties"]
86
-
87
- assert result["ReturnCasesNumber"] == "5"
88
-
89
- assert {
90
- "InternalName": "ows_Title",
91
- "Value": "Lønbilag",
92
- "DataType": "Text",
93
- "ComparisonType": "Equal",
94
- "IsMultiValue": "False"
95
- } in result["FieldProperties"]
96
-
97
-
98
- def test_generic_search_case_data_json_without_name(case_data_handler: CaseDataJson):
99
- """
100
- Ensure that generic_search_case_data_json builds correct contact data when include_name=False,
101
- and only includes one field (ows_CCMContactData) by default when no additional fields are passed.
102
- """
103
-
104
- result = case_data_handler.generic_search_case_data_json(
105
- case_type_prefix="BOR",
106
- person_full_name="Daniel Tester",
107
- person_id="12345",
108
- person_ssn="0101011234",
109
- include_name=False
110
- )
111
-
112
- assert result["CaseTypePrefixes"] == ["BOR"]
113
-
114
- assert {
115
- "InternalName": "ows_CCMContactData",
116
- "Value": ";#12345;#0101011234;#;#",
117
- "DataType": "Text",
118
- "ComparisonType": "Equal",
119
- "IsMultiValue": "False"
120
- } in result["FieldProperties"]
121
-
122
- assert result["ReturnCasesNumber"] == "1"
123
-
124
- assert len(result["FieldProperties"]) == 1
@@ -1,188 +0,0 @@
1
- """
2
- Integration tests for verifying Microsoft Office Excel functionality through SharePoint.
3
-
4
- Tests included:
5
- 1. `test_list_files_from_sharepoint_folder`:
6
- - Verifies that a known test Excel file exists in the SharePoint folder.
7
-
8
- 2. `test_append_row_to_excel`:
9
- - Appends a row to a specific sheet in the Excel file.
10
- - Verifies the row was successfully added.
11
-
12
- 3. `test_format_and_sort_excel_file`:
13
- - Sorts the Excel sheet by date/time (descending).
14
- - Applies formatting (bold headers, auto column widths).
15
- - Verifies that sorting has changed the order.
16
-
17
- Important constants:
18
- - FOLDER_NAME = "MSOffice tests"
19
- - FILE_NAME = "Test_Append_Rows.xlsx"
20
- - SHEET_NAME = "Upload logs"
21
- - HEADERS = ["Upload date", "Upload time"]
22
-
23
- Requires environment variables:
24
- - MSOFFICE_USERNAME
25
- - MSOFFICE_PASSWORD
26
- """
27
-
28
- import os
29
- import datetime
30
-
31
- from io import BytesIO
32
-
33
- import pytest
34
- import openpyxl
35
-
36
- from mbu_dev_shared_components.msoffice365.sharepoint_api.files import Sharepoint
37
-
38
- FOLDER_NAME = "MSOffice tests"
39
- CURRENT_DATE = datetime.datetime.now().strftime("%d-%m-%Y")
40
- CURRENT_TIME = datetime.datetime.now().strftime("%H:%M")
41
-
42
-
43
- @pytest.fixture(scope="module")
44
- def sharepoint_api():
45
- """
46
- Authenticates with SharePoint and returns a Sharepoint API instance.
47
- Skips test if required environment variables are missing.
48
- """
49
-
50
- def _get_cfg(key: str) -> str:
51
- val = os.getenv(key)
52
-
53
- if not val:
54
- pytest.skip(f"env var '{key}' not set → skipping integration test")
55
-
56
- return val
57
-
58
- username = _get_cfg("MSOFFICE_USERNAME")
59
- password = _get_cfg("MSOFFICE_PASSWORD")
60
-
61
- site_url = "https://aarhuskommune.sharepoint.com"
62
- site_name = "MBURPA"
63
- document_library = "Delte dokumenter"
64
-
65
- sp = Sharepoint(
66
- username=username,
67
- password=password,
68
- site_url=site_url,
69
- site_name=site_name,
70
- document_library=document_library
71
- )
72
-
73
- assert sp.ctx is not None, "SharePoint authentication failed"
74
-
75
- return sp
76
-
77
-
78
- @pytest.mark.dependency(name="list_files")
79
- def test_list_files_from_sharepoint_folder(sharepoint_api: Sharepoint):
80
- """
81
- Test 1: Check that the expected Excel file exists in the SharePoint folder.
82
- """
83
-
84
- files = sharepoint_api.fetch_files_list(FOLDER_NAME)
85
-
86
- file_names = [f["Name"] for f in files]
87
-
88
- assert "Test_Append_Rows.xlsx" in file_names
89
-
90
-
91
- @pytest.mark.dependency(name="append_row", depends=["list_files"])
92
- def test_append_row_to_excel(sharepoint_api: Sharepoint):
93
- """
94
- Test 2: Append a row to the Excel file and verify it was added correctly.
95
- """
96
-
97
- file_name = "Test_Append_Rows.xlsx"
98
-
99
- sheet_name = "Upload logs"
100
-
101
- headers = ["Upload date", "Upload time"]
102
-
103
- data = {
104
- "Upload date": CURRENT_DATE,
105
- "Upload time": CURRENT_TIME
106
- }
107
-
108
- # Append the row to the SharePoint-hosted Excel file
109
- sharepoint_api.append_row_to_sharepoint_excel(
110
- required_headers=headers,
111
- folder_name=FOLDER_NAME,
112
- excel_file_name=file_name,
113
- sheet_name=sheet_name,
114
- new_row=data,
115
- )
116
-
117
- # Fetch the updated file and check that the last row matches the new data
118
- binary_file = sharepoint_api.fetch_file_using_open_binary(file_name, FOLDER_NAME)
119
-
120
- wb = openpyxl.load_workbook(BytesIO(binary_file))
121
-
122
- ws = wb[sheet_name]
123
-
124
- newest_row = list(ws.iter_rows(values_only=True))[-1]
125
-
126
- assert newest_row[0] == CURRENT_DATE
127
- assert newest_row[1] == CURRENT_TIME
128
-
129
-
130
- @pytest.mark.dependency(depends=["append_row"])
131
- def test_format_and_sort_excel_file(sharepoint_api: Sharepoint):
132
- """
133
- Test 3: Format and sort the Excel file by date and time.
134
- Ensures that sorting changes the order and formatting is applied.
135
- """
136
-
137
- file_name = "Test_Append_Rows.xlsx"
138
-
139
- sheet_name = "Upload logs"
140
-
141
- # Download the file before sorting to capture original row order
142
- test_file = sharepoint_api.fetch_file_using_open_binary(file_name, FOLDER_NAME)
143
-
144
- wb = openpyxl.load_workbook(BytesIO(test_file))
145
-
146
- ws = wb[sheet_name]
147
-
148
- all_rows = list(ws.iter_rows(values_only=True))
149
-
150
- top_before = all_rows[1] # First data row
151
-
152
- bottom_before = all_rows[-1] # Last data row
153
-
154
- # Sort by first two columns (date, time) in descending order
155
- sorting_keys = [
156
- {"key": "A", "ascending": False, "type": "str"},
157
- {"key": "B", "ascending": False, "type": "str"},
158
- ]
159
-
160
- # Apply sorting and formatting
161
- sharepoint_api.format_and_sort_excel_file(
162
- folder_name=FOLDER_NAME,
163
- excel_file_name=file_name,
164
- sheet_name=sheet_name,
165
- sorting_keys=sorting_keys,
166
- bold_rows=[1],
167
- column_widths="auto",
168
- )
169
-
170
- # Re-fetch the file after sorting and verify order has changed
171
- test_file = sharepoint_api.fetch_file_using_open_binary(file_name, FOLDER_NAME)
172
-
173
- wb = openpyxl.load_workbook(BytesIO(test_file))
174
-
175
- ws = wb[sheet_name]
176
-
177
- all_rows = list(ws.iter_rows(values_only=True))
178
-
179
- top_after = all_rows[1]
180
-
181
- bottom_after = all_rows[-1]
182
-
183
- # Check that sorting actually changed the row order
184
- assert top_before != top_after
185
- assert bottom_before != bottom_after
186
-
187
- # Check that the top row after sorting is the one just added
188
- assert top_after[0] == CURRENT_DATE