Skip to content

Commit 91d43cf

Browse files
committed
update existing integration tests
1 parent 88e4ab4 commit 91d43cf

1 file changed

Lines changed: 49 additions & 19 deletions

File tree

refiner/tests/integration/test_export.py

Lines changed: 49 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import csv
22
import re
3-
from io import StringIO
3+
import zipfile
4+
from io import BytesIO, StringIO
45

56
import pytest
67
from fastapi import status
@@ -10,6 +11,15 @@
1011
from app.db.configurations.model import DbConfigurationCustomCode
1112

1213

14+
def get_csv_from_zip(content: bytes, filename_pattern: str) -> str:
15+
"""Extract a CSV file from a zip response by filename pattern."""
16+
with zipfile.ZipFile(BytesIO(content)) as zf:
17+
for name in zf.namelist():
18+
if re.search(filename_pattern, name):
19+
return zf.read(name).decode("utf-8")
20+
raise FileNotFoundError(f"No file matching {filename_pattern!r} found in zip")
21+
22+
1323
@pytest.mark.integration
1424
@pytest.mark.asyncio
1525
class TestConfigurationExport:
@@ -21,11 +31,11 @@ async def test_export_returns_404_for_unknown_id(self, setup, authed_client):
2131
response = await authed_client.get(f"/api/v1/configurations/{dummy_id}/export")
2232
assert response.status_code == status.HTTP_404_NOT_FOUND
2333

24-
async def test_export_returns_csv_with_correct_headers(
34+
async def test_export_returns_zip_with_correct_headers(
2535
self, setup, authed_client, get_condition_id, create_config
2636
):
2737
"""
28-
CSV should be returned in correct form when given a valid config.
38+
Zip should be returned in correct form when given a valid config.
2939
"""
3040
condition_id = await get_condition_id("Colorado tick fever")
3141
config = await create_config(condition_id)
@@ -34,14 +44,33 @@ async def test_export_returns_csv_with_correct_headers(
3444
)
3545

3646
assert response.status_code == status.HTTP_200_OK
37-
assert response.headers["content-type"].startswith("text/csv")
47+
assert response.headers["content-type"].startswith("application/zip")
3848

3949
cd_header = response.headers.get("content-disposition", "")
4050
assert re.search(
41-
r'filename=".+_Code_Export_\d{6}_\d{2}_\d{2}_\d{2}\.csv"',
51+
r'filename=".+_Configuration_Export_\d{6}_\d{2}_\d{2}_\d{2}\.zip"',
4252
cd_header,
4353
), f"Unexpected Content-Disposition: {cd_header!r}"
4454

55+
async def test_export_zip_contains_expected_files(
56+
self, setup, authed_client, get_condition_id, create_config
57+
):
58+
"""
59+
Zip should contain a codes CSV and a sections CSV.
60+
"""
61+
condition_id = await get_condition_id("Colorado tick fever")
62+
config = await create_config(condition_id)
63+
response = await authed_client.get(
64+
f"/api/v1/configurations/{config['id']}/export"
65+
)
66+
67+
assert response.status_code == status.HTTP_200_OK
68+
69+
with zipfile.ZipFile(BytesIO(response.content)) as zf:
70+
names = zf.namelist()
71+
assert any(re.search(r"Code_Export.+\.csv", n) for n in names)
72+
assert any(re.search(r"Section_Export.+\.csv", n) for n in names)
73+
4574
async def test_export_includes_all_codes_from_multiple_codesets(
4675
self,
4776
setup,
@@ -72,7 +101,7 @@ async def test_export_includes_all_codes_from_multiple_codesets(
72101
response = await authed_client.get(f"/api/v1/configurations/{config_id}/export")
73102
assert response.status_code == status.HTTP_200_OK
74103

75-
content = response.text
104+
content = get_csv_from_zip(response.content, r"Code_Export")
76105
lines = [line for line in content.splitlines() if line.strip()]
77106
assert len(lines) == expected_code_rows + 1 # header + codes
78107

@@ -87,7 +116,6 @@ async def test_export_csv_conditions_column_correct(
87116
"""
88117
CSV "Condition" column should only contain the associated condition names.
89118
"""
90-
91119
amebiasis_id = await get_condition_id("Amebiasis")
92120
config = await create_config(amebiasis_id)
93121
config_id = config["id"]
@@ -98,9 +126,9 @@ async def test_export_csv_conditions_column_correct(
98126
response = await authed_client.get(f"/api/v1/configurations/{config_id}/export")
99127
assert response.status_code == status.HTTP_200_OK
100128

101-
reader = csv.DictReader(StringIO(response.text))
102-
column_name = "Condition"
103-
conditions_in_csv = {row[column_name] for row in reader if row[column_name]}
129+
content = get_csv_from_zip(response.content, r"Code_Export")
130+
reader = csv.DictReader(StringIO(content))
131+
conditions_in_csv = {row["Condition"] for row in reader if row["Condition"]}
104132

105133
assert conditions_in_csv == {"Amebiasis", "Byssinosis"}
106134

@@ -132,17 +160,18 @@ async def test_export_csv_code_systems_valid(
132160
response = await authed_client.get(f"/api/v1/configurations/{config_id}/export")
133161
assert response.status_code == status.HTTP_200_OK
134162

135-
reader = csv.DictReader(StringIO(response.text))
136-
column_name = "Code System"
137-
code_systems_in_csv = {row[column_name] for row in reader if row[column_name]}
163+
content = get_csv_from_zip(response.content, r"Code_Export")
164+
reader = csv.DictReader(StringIO(content))
165+
code_systems_in_csv = {
166+
row["Code System"] for row in reader if row["Code System"]
167+
}
138168

139169
code_systems = await get_all_code_systems_db(db=db_pool)
140170
expected_systems = {cs.display_name for cs in code_systems.values()}
141171

142-
# csv systems must be a subset of the expected systems set
143172
assert code_systems_in_csv <= expected_systems
144173

145-
async def test_export_custom_codes_have_blank_code_system(
174+
async def test_export_custom_codes_have_blank_condition(
146175
self,
147176
setup,
148177
authed_client,
@@ -169,18 +198,19 @@ async def test_export_custom_codes_have_blank_code_system(
169198
response = await authed_client.get(f"/api/v1/configurations/{config_id}/export")
170199
assert response.status_code == status.HTTP_200_OK
171200

172-
reader = csv.DictReader(StringIO(response.text))
201+
content = get_csv_from_zip(response.content, r"Code_Export")
202+
reader = csv.DictReader(StringIO(content))
173203
for row in reader:
174204
if row["Code Type"] == "Custom code":
175205
assert row["Condition"] == "", (
176-
f"Expected blank Code System for custom code, got {row['Code System']!r}"
206+
f"Expected blank Condition for custom code, got {row['Condition']!r}"
177207
)
178208

179209
async def test_export_csv_body_is_non_empty(
180210
self, setup, authed_client, get_condition_id, create_config
181211
):
182212
"""
183-
CSV should contain at least a header row.
213+
Codes CSV should contain at least a header row.
184214
"""
185215
condition_id = await get_condition_id("Cholera")
186216
config = await create_config(condition_id)
@@ -189,6 +219,6 @@ async def test_export_csv_body_is_non_empty(
189219
)
190220

191221
assert response.status_code == status.HTTP_200_OK
192-
content = response.text
222+
content = get_csv_from_zip(response.content, r"Code_Export")
193223
lines = [line for line in content.splitlines() if line.strip()]
194224
assert len(lines) >= 1, "Expected at least a CSV header row in the response"

0 commit comments

Comments
 (0)