11from ftrs_common .fhir .operation_outcome import (
2+ FHIR_OPERATION_OUTCOME_CODES ,
3+ OPERATION_OUTCOME_SYSTEM ,
24 OperationOutcomeException ,
35 OperationOutcomeHandler ,
46)
@@ -25,6 +27,18 @@ def test_operation_outcome_handler_build_basic() -> None:
2527 assert outcome ["issue" ][0 ]["diagnostics" ] == diagnostics
2628 assert outcome ["issue" ][0 ]["code" ] == "invalid"
2729 assert outcome ["issue" ][0 ]["severity" ] == "error"
30+ assert "details" in outcome ["issue" ][0 ]
31+ assert "coding" in outcome ["issue" ][0 ]["details" ]
32+ assert (
33+ outcome ["issue" ][0 ]["details" ]["coding" ][0 ]["system" ]
34+ == OPERATION_OUTCOME_SYSTEM
35+ )
36+ assert outcome ["issue" ][0 ]["details" ]["coding" ][0 ]["code" ] == "MSG_PARAM_INVALID"
37+ assert (
38+ outcome ["issue" ][0 ]["details" ]["coding" ][0 ]["display" ]
39+ == "Parameter content is invalid"
40+ )
41+ assert outcome ["issue" ][0 ]["details" ]["text" ] == diagnostics
2842
2943
3044def test_operation_outcome_handler_build_with_details_and_issues () -> None :
@@ -36,16 +50,96 @@ def test_operation_outcome_handler_build_with_details_and_issues() -> None:
3650 assert outcome ["issue" ][0 ]["diagnostics" ] == "Warn"
3751
3852
53+ def test_operation_outcome_handler_build_with_custom_code () -> None :
54+ diagnostics : str = "Resource not found"
55+ outcome = OperationOutcomeHandler .build (
56+ diagnostics , code = "not-found" , severity = "error"
57+ )
58+ assert outcome ["issue" ][0 ]["code" ] == "not-found"
59+ assert outcome ["issue" ][0 ]["details" ]["coding" ][0 ]["code" ] == "MSG_NO_EXIST"
60+ assert (
61+ outcome ["issue" ][0 ]["details" ]["coding" ][0 ]["display" ]
62+ == "Resource does not exist"
63+ )
64+
65+
66+ def test_operation_outcome_handler_build_with_unknown_code () -> None :
67+ diagnostics : str = "Unknown error"
68+ outcome = OperationOutcomeHandler .build (diagnostics , code = "unknown-code" )
69+ assert outcome ["issue" ][0 ]["details" ]["coding" ][0 ]["code" ] == "MSG_ERROR_PARSING"
70+ assert (
71+ outcome ["issue" ][0 ]["details" ]["coding" ][0 ]["display" ]
72+ == "Error processing request"
73+ )
74+
75+
76+ def test_operation_outcome_handler_build_with_details_text () -> None :
77+ diagnostics : str = "Detailed diagnostics"
78+ details_text : str = "Human readable text"
79+ outcome = OperationOutcomeHandler .build (diagnostics , details_text = details_text )
80+ assert outcome ["issue" ][0 ]["diagnostics" ] == diagnostics
81+ assert outcome ["issue" ][0 ]["details" ]["text" ] == details_text
82+
83+
84+ def test_operation_outcome_handler_build_with_expression () -> None :
85+ diagnostics : str = "Invalid field"
86+ expression : list [str ] = ["Organization.identifier[0].value" ]
87+ outcome = OperationOutcomeHandler .build (diagnostics , expression = expression )
88+ assert outcome ["issue" ][0 ]["expression" ] == expression
89+
90+
91+ def test_operation_outcome_handler_build_with_custom_details () -> None :
92+ diagnostics : str = "Test diagnostics"
93+ custom_details : dict = {
94+ "coding" : [
95+ {
96+ "system" : "https://custom.system" ,
97+ "code" : "CUSTOM_CODE" ,
98+ "display" : "Custom Display" ,
99+ }
100+ ],
101+ "text" : "Custom text" ,
102+ }
103+ outcome = OperationOutcomeHandler .build (diagnostics , details = custom_details )
104+ assert outcome ["issue" ][0 ]["details" ] == custom_details
105+
106+
107+ def test_operation_outcome_handler_build_with_issues () -> None :
108+ diagnostics : str = "Test diagnostics"
109+ details : dict = {"text" : "More info" }
110+ issues : list = [
111+ {
112+ "severity" : "warning" ,
113+ "code" : "processing" ,
114+ "diagnostics" : "Warn" ,
115+ "details" : {"text" : "Warning details" },
116+ }
117+ ]
118+ outcome = OperationOutcomeHandler .build (diagnostics , details = details , issues = issues )
119+ assert outcome ["issue" ][0 ]["severity" ] == "warning"
120+ assert outcome ["issue" ][0 ]["diagnostics" ] == "Warn"
121+
122+
39123def test_operation_outcome_handler_from_exception () -> None :
40124 exc = Exception ("Boom!" )
41125 outcome = OperationOutcomeHandler .from_exception (exc )
42126 assert outcome ["issue" ][0 ]["diagnostics" ] == "Boom!"
43127 assert outcome ["issue" ][0 ]["code" ] == "exception"
44128 assert outcome ["issue" ][0 ]["severity" ] == "fatal"
129+ assert (
130+ outcome ["issue" ][0 ]["details" ]["coding" ][0 ]["system" ]
131+ == OPERATION_OUTCOME_SYSTEM
132+ )
133+ assert outcome ["issue" ][0 ]["details" ]["coding" ][0 ]["code" ] == "MSG_ERROR_PARSING"
134+ assert (
135+ outcome ["issue" ][0 ]["details" ]["coding" ][0 ]["display" ]
136+ == "Error processing request"
137+ )
138+ assert "An unexpected error occurred" in outcome ["issue" ][0 ]["details" ]["text" ]
45139
46140
47- def test_operation_outcome_handler_from_validation_error_default_diagnostics () -> None :
48- dummy_model_path = "tests.fhir.test_operation_outcome.DummyModel"
141+ def test_operation_outcome_handler_from_validation_error () -> None :
142+ dummy_model_path : str = "tests.fhir.test_operation_outcome.DummyModel"
49143
50144 error = ValidationError .from_exception_data (
51145 dummy_model_path ,
@@ -63,26 +157,39 @@ def test_operation_outcome_handler_from_validation_error_default_diagnostics() -
63157 assert outcome ["issue" ][0 ]["diagnostics" ] == "Validation failed for resource."
64158 assert outcome ["issue" ][0 ]["code" ] == "invalid"
65159 assert outcome ["issue" ][0 ]["severity" ] == "error"
66- assert "Invalid Resource" in outcome ["issue" ][0 ]["details" ]["coding" ][0 ]["display" ]
67-
68-
69- def test_operation_outcome_handler_from_validation_error_with_diagnostics () -> None :
70- dummy_model_path = "tests.fhir.test_operation_outcome.DummyModel"
71-
72- error = ValidationError .from_exception_data (
73- dummy_model_path ,
74- [
75- {
76- "type" : "value_error" ,
77- "loc" : ("foo" ,),
78- "msg" : "Fake error" ,
79- "input" : "bad_value" ,
80- "ctx" : {"error" : ValueError ("Fake error" )},
81- }
82- ],
160+ assert (
161+ outcome ["issue" ][0 ]["details" ]["coding" ][0 ]["system" ]
162+ == OPERATION_OUTCOME_SYSTEM
163+ )
164+ assert outcome ["issue" ][0 ]["details" ]["coding" ][0 ]["code" ] == "MSG_PARAM_INVALID"
165+ assert (
166+ outcome ["issue" ][0 ]["details" ]["coding" ][0 ]["display" ]
167+ == "Parameter content is invalid"
83168 )
84169
85- outcome = OperationOutcomeHandler .from_validation_error (error )
86- assert outcome ["issue" ][0 ]["diagnostics" ] == "Validation failed for resource."
87- assert outcome ["issue" ][0 ]["code" ] == "invalid"
88- assert outcome ["issue" ][0 ]["severity" ] == "error"
170+
171+ def test_fhir_operation_outcome_codes_mapping () -> None :
172+ """Test that all expected codes are mapped correctly."""
173+ expected_mappings : dict [str , tuple [str , str ]] = {
174+ "invalid" : ("MSG_PARAM_INVALID" , "Parameter content is invalid" ),
175+ "not-found" : ("MSG_NO_EXIST" , "Resource does not exist" ),
176+ "exception" : ("MSG_ERROR_PARSING" , "Error processing request" ),
177+ "structure" : ("MSG_BAD_SYNTAX" , "Bad Syntax" ),
178+ "required" : ("MSG_RESOURCE_REQUIRED" , "A resource is required" ),
179+ "value" : ("MSG_PARAM_INVALID" , "Parameter content is invalid" ),
180+ "processing" : ("MSG_ERROR_PARSING" , "Error processing request" ),
181+ "duplicate" : ("MSG_DUPLICATE_ID" , "Duplicate Id for resource" ),
182+ "informational" : ("MSG_UPDATED" , "Existing resource updated" ),
183+ "success" : ("MSG_UPDATED" , "Existing resource updated" ),
184+ }
185+ for code , expected in expected_mappings .items ():
186+ assert FHIR_OPERATION_OUTCOME_CODES [code ] == expected
187+
188+
189+ def test_build_details_helper () -> None :
190+ """Test the _build_details helper method."""
191+ details = OperationOutcomeHandler ._build_details ("invalid" , "Test text" )
192+ assert details ["coding" ][0 ]["system" ] == OPERATION_OUTCOME_SYSTEM
193+ assert details ["coding" ][0 ]["code" ] == "MSG_PARAM_INVALID"
194+ assert details ["coding" ][0 ]["display" ] == "Parameter content is invalid"
195+ assert details ["text" ] == "Test text"
0 commit comments