66import pytest
77from django .core .files .uploadedfile import SimpleUploadedFile
88from ninja .testing import TestClient
9+ from pydicom .uid import generate_uid
910
1011from manage_breast_screening .core .api import api
11- from manage_breast_screening .dicom .models import Study
1212from manage_breast_screening .gateway .models import GatewayActionStatus
1313from manage_breast_screening .gateway .tests .factories import GatewayActionFactory
1414from manage_breast_screening .participants .models .appointment import (
1515 AppointmentStatusNames ,
1616)
1717from manage_breast_screening .participants .tests .factories import AppointmentFactory
1818
19+ from ..authentication import Authentication
20+ from ..dicom_recorder import DicomRecorder
21+ from ..models import Study
22+
1923os .environ ["NINJA_SKIP_REGISTRY" ] = "yes"
2024
2125client = TestClient (api )
2226
2327
28+ @pytest .fixture (autouse = True )
29+ def setup (monkeypatch ):
30+ monkeypatch .setenv ("API_ENABLED" , "true" )
31+ monkeypatch .setenv ("API_AUDIENCE" , "test_audience" )
32+ monkeypatch .setenv ("TENANT_ID" , "test_tenant_id" )
33+
34+
2435@pytest .fixture
2536def dicom_file (dataset ) -> bytes :
2637 with io .BytesIO () as buffer :
@@ -38,11 +49,14 @@ def appointment_stub():
3849 )
3950
4051
41- @pytest .mark .django_db
42- def test_upload_success (dataset , dicom_file , monkeypatch ):
43- monkeypatch .setenv ("API_ENABLED" , "true" )
44- monkeypatch .setenv ("API_AUTH_TOKEN" , "testtoken" )
52+ @pytest .fixture
53+ def mock_authentication ():
54+ with patch .object (Authentication , "authenticate" , return_value = {"sub" : "testuser" }):
55+ yield
56+
4557
58+ @pytest .mark .django_db
59+ def test_upload_success (dataset , dicom_file , mock_authentication , appointment_stub ):
4660 appointment = AppointmentFactory (current_status = AppointmentStatusNames .IN_PROGRESS )
4761
4862 with patch (
@@ -52,7 +66,7 @@ def test_upload_success(dataset, dicom_file, monkeypatch):
5266 response = client .put (
5367 f"/dicom/{ appointment .pk } " ,
5468 FILES = {"file" : dicom_file },
55- headers = {"Authorization" : "Bearer " + os . getenv ( "API_AUTH_TOKEN" , "" ) },
69+ headers = {"Authorization" : "Bearer testtoken" },
5670 )
5771
5872 assert response .status_code == 201
@@ -65,23 +79,17 @@ def test_upload_success(dataset, dicom_file, monkeypatch):
6579 assert study .source_message_id == str (appointment .pk )
6680
6781
68- def test_upload_no_file (monkeypatch ):
69- monkeypatch .setenv ("API_ENABLED" , "true" )
70- monkeypatch .setenv ("API_AUTH_TOKEN" , "testtoken" )
71-
82+ def test_upload_no_file (mock_authentication ):
7283 response = client .put (
7384 "/dicom/abc123" ,
7485 FILES = {"file" : None },
75- headers = {"Authorization" : "Bearer " + os . getenv ( "API_AUTH_TOKEN" , "" ) },
86+ headers = {"Authorization" : "Bearer testtoken" },
7687 )
7788
7889 assert response .status_code == 422
7990
8091
81- def test_upload_invalid_file (monkeypatch , appointment_stub ):
82- monkeypatch .setenv ("API_ENABLED" , "true" )
83- monkeypatch .setenv ("API_AUTH_TOKEN" , "testtoken" )
84-
92+ def test_upload_invalid_file (mock_authentication , appointment_stub ):
8593 invalid_file = SimpleUploadedFile (
8694 "invalid.dcm" , b"not a dicom file" , content_type = "application/dicom"
8795 )
@@ -93,7 +101,7 @@ def test_upload_invalid_file(monkeypatch, appointment_stub):
93101 response = client .put (
94102 "/dicom/abc123" ,
95103 FILES = {"file" : invalid_file },
96- headers = {"Authorization" : "Bearer " + os . getenv ( "API_AUTH_TOKEN" , "" ) },
104+ headers = {"Authorization" : "Bearer testtoken" },
97105 )
98106
99107 assert response .status_code == 400
@@ -102,16 +110,13 @@ def test_upload_invalid_file(monkeypatch, appointment_stub):
102110 assert response .json ()["detail" ] == "The uploaded file is not a valid DICOM file."
103111
104112
105- def test_upload_file_thats_too_large (monkeypatch ):
106- monkeypatch .setenv ("API_ENABLED" , "true" )
107- monkeypatch .setenv ("API_AUTH_TOKEN" , "testtoken" )
108-
113+ def test_upload_file_thats_too_large (mock_authentication ):
109114 invalid_file = MagicMock (spec = SimpleUploadedFile , size = 101 * 1024 * 1024 )
110115
111116 response = client .put (
112117 "/dicom/abc123" ,
113118 FILES = {"file" : invalid_file },
114- headers = {"Authorization" : "Bearer " + os . getenv ( "API_AUTH_TOKEN" , "" ) },
119+ headers = {"Authorization" : "Bearer testtoken" },
115120 )
116121
117122 assert response .status_code == 400
@@ -120,10 +125,7 @@ def test_upload_file_thats_too_large(monkeypatch):
120125 assert response .json ()["detail" ] == "The file cannot be larger than 100MB"
121126
122127
123- def test_upload_missing_uids (dataset , monkeypatch , appointment_stub ):
124- monkeypatch .setenv ("API_ENABLED" , "true" )
125- monkeypatch .setenv ("API_AUTH_TOKEN" , "testtoken" )
126-
128+ def test_upload_missing_uids (dataset , mock_authentication , appointment_stub ):
127129 del dataset .StudyInstanceUID
128130 del dataset .SeriesInstanceUID
129131 del dataset .SOPInstanceUID
@@ -142,7 +144,7 @@ def test_upload_missing_uids(dataset, monkeypatch, appointment_stub):
142144 response = client .put (
143145 "/dicom/abc123" ,
144146 FILES = {"file" : dicom_file },
145- headers = {"Authorization" : "Bearer " + os . getenv ( "API_AUTH_TOKEN" , "" ) },
147+ headers = {"Authorization" : "Bearer testtoken" },
146148 )
147149
148150 assert response .status_code == 400
@@ -154,10 +156,9 @@ def test_upload_missing_uids(dataset, monkeypatch, appointment_stub):
154156 )
155157
156158
157- def test_upload_appointment_not_in_progress (dicom_file , monkeypatch , appointment_stub ):
158- monkeypatch .setenv ("API_ENABLED" , "true" )
159- monkeypatch .setenv ("API_AUTH_TOKEN" , "testtoken" )
160-
159+ def test_upload_appointment_not_in_progress (
160+ dicom_file , mock_authentication , appointment_stub
161+ ):
161162 appointment_stub .is_in_progress .return_value = False
162163
163164 with patch (
@@ -167,29 +168,26 @@ def test_upload_appointment_not_in_progress(dicom_file, monkeypatch, appointment
167168 response = client .put (
168169 "/dicom/abc123" ,
169170 FILES = {"file" : dicom_file },
170- headers = {"Authorization" : "Bearer " + os . getenv ( "API_AUTH_TOKEN" , "" ) },
171+ headers = {"Authorization" : "Bearer testtoken" },
171172 )
172173
173174 assert response .status_code == 500
174175 assert response .json ()["title" ] == "Internal Server Error"
175176
176177
177- @pytest .mark .django_db
178- def test_upload_when_api_disabled (dicom_file , monkeypatch ):
178+ def test_upload_when_api_disabled (dicom_file , mock_authentication , monkeypatch ):
179179 monkeypatch .setenv ("API_ENABLED" , "false" )
180- monkeypatch .setenv ("API_AUTH_TOKEN" , "testtoken" )
181180
182181 response = client .put (
183182 "/dicom/abc123" ,
184183 FILES = {"file" : dicom_file },
185- headers = {"Authorization" : "Bearer " + os . getenv ( "API_AUTH_TOKEN" , "" ) },
184+ headers = {"Authorization" : "Bearer testtoken" },
186185 )
187186
188187 assert response .status_code == 403
189188 assert response .json ()["status" ] == "API is not available"
190189
191190
192- @pytest .mark .django_db
193191def test_upload_no_auth (dicom_file ):
194192 response = client .put (
195193 "/dicom/abc123" ,
@@ -202,11 +200,41 @@ def test_upload_no_auth(dicom_file):
202200 }
203201
204202
205- @pytest .mark .django_db
206- def test_report_failure (monkeypatch ):
207- monkeypatch .setenv ("API_ENABLED" , "true" )
208- monkeypatch .setenv ("API_AUTH_TOKEN" , "testtoken" )
203+ def test_upload_invalid_auth (dicom_file ):
204+ response = client .put (
205+ "/dicom/abc123" ,
206+ FILES = {"file" : dicom_file },
207+ headers = {"Authorization" : "Bearer invalidtoken" },
208+ )
209209
210+ assert response .status_code == 401
211+ assert response .json () == {
212+ "detail" : "Unauthorized" ,
213+ }
214+
215+
216+ def test_upload_bypass_token_validation (dicom_file ):
217+ with patch .object (Authentication , "bypass_authentication" , return_value = True ):
218+ with patch .object (
219+ DicomRecorder ,
220+ "get_or_create_records" ,
221+ return_value = (
222+ MagicMock (study_instance_uid = generate_uid ()),
223+ MagicMock (series_instance_uid = generate_uid ()),
224+ MagicMock (sop_instance_uid = generate_uid (), id = 1 ),
225+ ),
226+ ):
227+ response = client .put (
228+ "/dicom/abc123" ,
229+ FILES = {"file" : dicom_file },
230+ headers = {"Authorization" : "Bearer anytoken" },
231+ )
232+
233+ assert response .status_code == 201
234+
235+
236+ @pytest .mark .django_db
237+ def test_report_failure (mock_authentication ):
210238 action = GatewayActionFactory ()
211239
212240 response = client .patch (
@@ -225,10 +253,7 @@ def test_report_failure(monkeypatch):
225253
226254
227255@pytest .mark .django_db
228- def test_report_failure_action_not_found (monkeypatch ):
229- monkeypatch .setenv ("API_ENABLED" , "true" )
230- monkeypatch .setenv ("API_AUTH_TOKEN" , "testtoken" )
231-
256+ def test_report_failure_action_not_found (mock_authentication ):
232257 response = client .patch (
233258 "/dicom/00000000-0000-0000-0000-000000000000/failure" ,
234259 json = {"error" : "Missing PatientID" },
0 commit comments