|
1 | 1 | import unittest |
| 2 | +from decimal import Decimal |
2 | 3 |
|
3 | 4 | from common.validator.error_report.record_error import ErrorReport |
4 | 5 | from common.validator.expression_checker import ExpressionChecker |
@@ -163,6 +164,199 @@ def test_gender_string_rule_valid_and_invalid(self): |
163 | 164 | # Invalid values should error |
164 | 165 | self.assertIsInstance(checker.validate_expression("STRING", "GENDER", field_path, "M"), ErrorReport) |
165 | 166 |
|
| 167 | + # BOOLEAN with PRIMARY_SOURCE |
| 168 | + def test_primary_source_boolean_valid_and_invalid(self): |
| 169 | + checker = self.make_checker() |
| 170 | + field_path = "primarySource" |
| 171 | + # Valid: boolean True |
| 172 | + self.assertIsNone(checker.validate_expression("BOOLEAN", "", field_path, True)) |
| 173 | + # Invalid: non-boolean should raise TypeError per implementation |
| 174 | + self.assertIsInstance(checker.validate_expression("BOOLEAN", "", field_path, "true"), ErrorReport) |
| 175 | + |
| 176 | + # STRING with VACCINATION_PROCEDURE_CODE |
| 177 | + def test_vaccination_procedure_code_string_valid_and_invalid(self): |
| 178 | + checker = self.make_checker() |
| 179 | + field_path = "extension|0|valueCodeableConcept|coding|0|code" |
| 180 | + # Valid: non-empty string |
| 181 | + self.assertIsNone(checker.validate_expression("STRING", "", field_path, "123456")) |
| 182 | + # Invalid: empty string |
| 183 | + self.assertIsInstance(checker.validate_expression("STRING", "", field_path, ""), ErrorReport) |
| 184 | + # Invalid: non-string value |
| 185 | + self.assertIsInstance(checker.validate_expression("STRING", "", field_path, 123456), ErrorReport) |
| 186 | + |
| 187 | + # STRING with VACCINATION_PROCEDURE_TERM |
| 188 | + def test_vaccination_procedure_term_string_valid_and_invalid(self): |
| 189 | + checker = self.make_checker() |
| 190 | + field_path = "extension|0|valueCodeableConcept|coding|0|display" |
| 191 | + # Valid: non-empty string |
| 192 | + self.assertIsNone(checker.validate_expression("STRING", "", field_path, "COVID-19 vaccination")) |
| 193 | + # Invalid: empty string |
| 194 | + self.assertIsInstance(checker.validate_expression("STRING", "", field_path, ""), ErrorReport) |
| 195 | + # Invalid: non-string value |
| 196 | + self.assertIsInstance(checker.validate_expression("STRING", "", field_path, 999), ErrorReport) |
| 197 | + |
| 198 | + # POSITIVEINTEGER with DOSE_SEQUENCE |
| 199 | + def test_dose_sequence_positiveinteger_valid_and_invalid(self): |
| 200 | + checker = self.make_checker() |
| 201 | + field_path = "protocolApplied|0|doseNumberPositiveInt" |
| 202 | + # Valid: positive integer |
| 203 | + self.assertIsNone(checker.validate_expression("POSITIVEINTEGER", "", field_path, 2)) |
| 204 | + # Invalid: zero -> ValueError |
| 205 | + self.assertIsInstance(checker.validate_expression("POSITIVEINTEGER", "", field_path, 0), ErrorReport) |
| 206 | + # Invalid: negative -> ValueError |
| 207 | + self.assertIsInstance(checker.validate_expression("POSITIVEINTEGER", "", field_path, -1), ErrorReport) |
| 208 | + # Invalid: non-int -> TypeError |
| 209 | + self.assertIsInstance(checker.validate_expression("POSITIVEINTEGER", "", field_path, "2"), ErrorReport) |
| 210 | + |
| 211 | + # STRING with VACCINE_PRODUCT_CODE |
| 212 | + def test_vaccine_product_code_string_valid_and_invalid(self): |
| 213 | + checker = self.make_checker() |
| 214 | + field_path = "vaccineCode|coding|#:http://snomed.info/sct|code" |
| 215 | + # Valid: non-empty string |
| 216 | + self.assertIsNone(checker.validate_expression("STRING", "", field_path, "1119349007")) |
| 217 | + # Invalid: empty |
| 218 | + self.assertIsInstance(checker.validate_expression("STRING", "", field_path, ""), ErrorReport) |
| 219 | + # Invalid: non-string |
| 220 | + self.assertIsInstance(checker.validate_expression("STRING", "", field_path, 1119349007), ErrorReport) |
| 221 | + |
| 222 | + # STRING with VACCINE_PRODUCT_TERM |
| 223 | + def test_vaccine_product_term_string_valid_and_invalid(self): |
| 224 | + checker = self.make_checker() |
| 225 | + field_path = "vaccineCode|coding|#:http://snomed.info/sct|display" |
| 226 | + # Valid: non-empty string (spaces allowed by default) |
| 227 | + self.assertIsNone(checker.validate_expression("STRING", "", field_path, "COVID-19 mRNA vaccine")) |
| 228 | + # Invalid: empty |
| 229 | + self.assertIsInstance(checker.validate_expression("STRING", "", field_path, ""), ErrorReport) |
| 230 | + # Invalid: non-string |
| 231 | + self.assertIsInstance(checker.validate_expression("STRING", "", field_path, 12345), ErrorReport) |
| 232 | + |
| 233 | + # STRING with VACCINE_MANUFACTURER |
| 234 | + def test_vaccine_manufacturer_string_valid_and_invalid(self): |
| 235 | + checker = self.make_checker() |
| 236 | + field_path = "manufacturer|display" |
| 237 | + # Valid: non-empty string |
| 238 | + self.assertIsNone(checker.validate_expression("STRING", "", field_path, "Pfizer")) |
| 239 | + # Invalid: empty |
| 240 | + self.assertIsInstance(checker.validate_expression("STRING", "", field_path, ""), ErrorReport) |
| 241 | + # Invalid: non-string |
| 242 | + self.assertIsInstance(checker.validate_expression("STRING", "", field_path, 101), ErrorReport) |
| 243 | + |
| 244 | + # STRING with SITE_OF_VACCINATION_CODE |
| 245 | + def test_site_of_vaccination_code_string_valid_and_invalid(self): |
| 246 | + checker = self.make_checker() |
| 247 | + field_path = "site|coding|#:http://snomed.info/sct|code" |
| 248 | + self.assertIsNone( |
| 249 | + checker.validate_expression("STRING", "", field_path, "123456"), |
| 250 | + msg=f"fieldPath={field_path}", |
| 251 | + ) |
| 252 | + self.assertIsInstance( |
| 253 | + checker.validate_expression("STRING", "", field_path, ""), |
| 254 | + ErrorReport, |
| 255 | + msg=f"fieldPath={field_path}", |
| 256 | + ) |
| 257 | + self.assertIsInstance( |
| 258 | + checker.validate_expression("STRING", "", field_path, 123456), |
| 259 | + ErrorReport, |
| 260 | + msg=f"fieldPath={field_path}", |
| 261 | + ) |
| 262 | + |
| 263 | + # STRING with SITE_OF_VACCINATION_TERM |
| 264 | + def test_site_of_vaccination_term_string_valid_and_invalid(self): |
| 265 | + checker = self.make_checker() |
| 266 | + field_path = "site|coding|#:http://snomed.info/sct|display" |
| 267 | + self.assertIsNone( |
| 268 | + checker.validate_expression("STRING", "", field_path, "Left deltoid"), |
| 269 | + msg=f"fieldPath={field_path}", |
| 270 | + ) |
| 271 | + self.assertIsInstance( |
| 272 | + checker.validate_expression("STRING", "", field_path, ""), |
| 273 | + ErrorReport, |
| 274 | + msg=f"fieldPath={field_path}", |
| 275 | + ) |
| 276 | + self.assertIsInstance( |
| 277 | + checker.validate_expression("STRING", "", field_path, 999), |
| 278 | + ErrorReport, |
| 279 | + msg=f"fieldPath={field_path}", |
| 280 | + ) |
| 281 | + |
| 282 | + # STRING with ROUTE_OF_VACCINATION_CODE |
| 283 | + def test_route_of_vaccination_code_string_valid_and_invalid(self): |
| 284 | + checker = self.make_checker() |
| 285 | + field_path = "route|coding|#:http://snomed.info/sct|code" |
| 286 | + self.assertIsNone( |
| 287 | + checker.validate_expression("STRING", "", field_path, "1234"), |
| 288 | + msg=f"fieldPath={field_path}", |
| 289 | + ) |
| 290 | + self.assertIsInstance( |
| 291 | + checker.validate_expression("STRING", "", field_path, ""), |
| 292 | + ErrorReport, |
| 293 | + msg=f"fieldPath={field_path}", |
| 294 | + ) |
| 295 | + self.assertIsInstance( |
| 296 | + checker.validate_expression("STRING", "", field_path, 1234), |
| 297 | + ErrorReport, |
| 298 | + msg=f"fieldPath={field_path}", |
| 299 | + ) |
| 300 | + |
| 301 | + # STRING with ROUTE_OF_VACCINATION_TERM |
| 302 | + def test_route_of_vaccination_term_string_valid_and_invalid(self): |
| 303 | + checker = self.make_checker() |
| 304 | + field_path = "route|coding|#:http://snomed.info/sct|display" |
| 305 | + self.assertIsNone( |
| 306 | + checker.validate_expression("STRING", "", field_path, "Intramuscular"), |
| 307 | + msg=f"fieldPath={field_path}", |
| 308 | + ) |
| 309 | + self.assertIsInstance( |
| 310 | + checker.validate_expression("STRING", "", field_path, ""), |
| 311 | + ErrorReport, |
| 312 | + msg=f"fieldPath={field_path}", |
| 313 | + ) |
| 314 | + self.assertIsInstance( |
| 315 | + checker.validate_expression("STRING", "", field_path, 12), |
| 316 | + ErrorReport, |
| 317 | + msg=f"fieldPath={field_path}", |
| 318 | + ) |
| 319 | + |
| 320 | + # INTDECIMAL with DOSE_AMOUNT |
| 321 | + def test_dose_amount_intdecimal_valid_and_invalid(self): |
| 322 | + checker = self.make_checker() |
| 323 | + field_path = "doseQuantity|value" |
| 324 | + # Valid: int |
| 325 | + self.assertIsNone( |
| 326 | + checker.validate_expression("INTDECIMAL", "", field_path, 1), |
| 327 | + msg=f"fieldPath={field_path}", |
| 328 | + ) |
| 329 | + # Valid: Decimal |
| 330 | + self.assertIsNone( |
| 331 | + checker.validate_expression("INTDECIMAL", "", field_path, Decimal("0.5")), |
| 332 | + msg=f"fieldPath={field_path}", |
| 333 | + ) |
| 334 | + # Invalid: string |
| 335 | + self.assertIsInstance( |
| 336 | + checker.validate_expression("INTDECIMAL", "", field_path, "0.5"), |
| 337 | + ErrorReport, |
| 338 | + msg=f"fieldPath={field_path}", |
| 339 | + ) |
| 340 | + |
| 341 | + # STRING with DOSE_UNIT_CODE |
| 342 | + def test_dose_unit_code_string_valid_and_invalid(self): |
| 343 | + checker = self.make_checker() |
| 344 | + field_path = "doseQuantity|code" |
| 345 | + self.assertIsNone( |
| 346 | + checker.validate_expression("STRING", "", field_path, "ml"), |
| 347 | + msg=f"fieldPath={field_path}", |
| 348 | + ) |
| 349 | + self.assertIsInstance( |
| 350 | + checker.validate_expression("STRING", "", field_path, ""), |
| 351 | + ErrorReport, |
| 352 | + msg=f"fieldPath={field_path}", |
| 353 | + ) |
| 354 | + self.assertIsInstance( |
| 355 | + checker.validate_expression("STRING", "", field_path, 1), |
| 356 | + ErrorReport, |
| 357 | + msg=f"fieldPath={field_path}", |
| 358 | + ) |
| 359 | + |
166 | 360 | # LIST with PERFORMING_PROFESSIONAL_FORENAME (empty rule -> non-empty list) |
167 | 361 | def test_practitioner_forename_list_valid_and_invalid(self): |
168 | 362 | checker = self.make_checker() |
@@ -211,31 +405,7 @@ def test_postcode_string_rule_valid_and_invalid(self): |
211 | 405 | ErrorReport, |
212 | 406 | ) |
213 | 407 | # Empty should also fail |
214 | | - self.assertIsInstance( |
215 | | - checker.validate_expression("STRING", "", field_path, ""), |
216 | | - ErrorReport, |
217 | | - ) |
218 | | - |
219 | | - |
220 | | -# def test_boolean_valid_and_invalid(self): |
221 | | -# checker = self.make_checker() |
222 | | -# self.assertIsNone(checker.validate_expression("BOOLEAN", "", "bool_field", True, 1)) |
223 | | -# self.assertIsInstance(checker.validate_expression("BOOLEAN", "", "bool_field", "true", 1), ErrorReport) |
224 | | - |
225 | | -# # POSITIVEINTEGER |
226 | | -# def test_positive_integer_valid_and_invalid(self): |
227 | | -# checker = self.make_checker() |
228 | | -# self.assertIsNone(checker.validate_expression("POSITIVEINTEGER", "", "pos_field", "2", 1)) |
229 | | -# self.assertIsInstance(checker.validate_expression("POSITIVEINTEGER", "", "pos_field", "0", 1), ErrorReport) |
230 | | -# self.assertIsInstance(checker.validate_expression("POSITIVEINTEGER", "", "pos_field", "-5", 1), ErrorReport) |
231 | | -# self.assertIsInstance(checker.validate_expression("POSITIVEINTEGER", "", "pos_field", "abc", 1), ErrorReport) |
232 | | - |
233 | | -# # INTDECIMAL |
234 | | -# def test_intdecimal_valid_and_invalid(self): |
235 | | -# checker = self.make_checker() |
236 | | -# self.assertIsNone(checker.validate_expression("INTDECIMAL", "", "num_field", "1.23", 1)) |
237 | | -# self.assertIsNone(checker.validate_expression("INTDECIMAL", "", "num_field", 3, 1)) |
238 | | -# self.assertIsInstance(checker.validate_expression("INTDECIMAL", "", "num_field", "abc", 1), ErrorReport) |
| 408 | + self.assertIsInstance(checker.validate_expression("STRING", "", field_path, ""), ErrorReport) |
239 | 409 |
|
240 | 410 |
|
241 | 411 | # class DummyParserEx: |
|
0 commit comments