1pub mod r4;
2
3#[cfg(test)]
4mod tests {
5 use super::*;
6 use crate::r4::{
7 datetime::Date,
8 generated::resources::{ClientApplication, Practitioner, Resource},
9 };
10 use haste_reflect::MetaValue;
11 use r4::generated::{resources::Patient, types::Address};
12 use serde_json;
13
14 #[test]
15 fn test_enum_with_extension() {
16 let term_ = r4::generated::terminology::AdministrativeGender::Male(Some(
17 r4::generated::types::Element {
18 id: Some("test".to_string()),
19 ..r4::generated::types::Element::default()
20 },
21 ));
22 assert_eq!(term_.fhir_type(), "code");
23 let k = term_
24 .get_field("value")
25 .unwrap()
26 .as_any()
27 .downcast_ref::<String>()
28 .unwrap();
29 assert_eq!(k, &"male");
30 }
31
32 #[test]
48 fn enum_resource_type_variant() {
49 let resource = serde_json::from_str::<Resource>(
50 r#"{
51 "resourceType": "Patient",
52 "address": [
53 {
54 "use": "home",
55 "line": ["123 Main St"],
56 "_line": [{"id": "hello-world"}],
57 "city": "Anytown",
58 "_city": {
59 "id": "city-id"
60 },
61 "state": "CA",
62 "postalCode": "12345"
63 }]
64
65 }"#,
66 );
67
68 assert!(matches!(resource, Ok(Resource::Patient(Patient { .. }))));
69
70 let resource = serde_json::from_str::<Resource>(
71 r#"{
72 "resourceType": "Practitioner",
73 "id": "example",
74 "text": {
75 "status": "generated",
76 "div": "<div xmlns=\"http://www.w3.org/1999/xhtml\">\n <p>Dr Adam Careful is a Referring Practitioner for Acme Hospital from 1-Jan 2012 to 31-Mar\n 2012</p>\n </div>"
77 },
78 "identifier": [
79 {
80 "system": "http://www.acme.org/practitioners",
81 "value": "23"
82 }
83 ],
84 "active": true,
85 "name": [
86 {
87 "family": "Careful",
88 "given": [
89 "Adam"
90 ],
91 "prefix": [
92 "Dr"
93 ]
94 }
95 ],
96 "address": [
97 {
98 "use": "home",
99 "line": [
100 "534 Erewhon St"
101 ],
102 "city": "PleasantVille",
103 "state": "Vic",
104 "postalCode": "3999"
105 }
106 ],
107 "qualification": [
108 {
109 "identifier": [
110 {
111 "system": "http://example.org/UniversityIdentifier",
112 "value": "12345"
113 }
114 ],
115 "code": {
116 "coding": [
117 {
118 "system": "http://terminology.hl7.org/CodeSystem/v2-0360/2.7",
119 "code": "BS",
120 "display": "Bachelor of Science"
121 }
122 ],
123 "text": "Bachelor of Science"
124 },
125 "period": {
126 "start": "1995"
127 },
128 "issuer": {
129 "display": "Example University"
130 }
131 }
132 ]
133}"#,
134 );
135
136 assert!(matches!(
137 resource,
138 Ok(Resource::Practitioner(Practitioner { .. }))
139 ));
140
141 assert_eq!(
142 "{\"resourceType\":\"Practitioner\",\"id\":\"example\",\"text\":{\"status\":\"generated\",\"div\":\"<div xmlns=\\\"http://www.w3.org/1999/xhtml\\\">\\n <p>Dr Adam Careful is a Referring Practitioner for Acme Hospital from 1-Jan 2012 to 31-Mar\\n 2012</p>\\n </div>\"},\"identifier\":[{\"system\":\"http://www.acme.org/practitioners\",\"value\":\"23\"}],\"active\":true,\"name\":[{\"family\":\"Careful\",\"given\":[\"Adam\"],\"prefix\":[\"Dr\"]}],\"address\":[{\"use\":\"home\",\"line\":[\"534 Erewhon St\"],\"city\":\"PleasantVille\",\"state\":\"Vic\",\"postalCode\":\"3999\"}],\"qualification\":[{\"identifier\":[{\"system\":\"http://example.org/UniversityIdentifier\",\"value\":\"12345\"}],\"code\":{\"coding\":[{\"system\":\"http://terminology.hl7.org/CodeSystem/v2-0360/2.7\",\"code\":\"BS\",\"display\":\"Bachelor of Science\"}],\"text\":\"Bachelor of Science\"},\"period\":{\"start\":\"1995\"},\"issuer\":{\"display\":\"Example University\"}}]}",
143 serde_json::to_string(resource.as_ref().unwrap()).unwrap(),
144 );
145 }
146
147 #[test]
148 fn test_valid_address_with_extensions() {
149 let address_string = r#"
150 {
151 "use": "home",
152 "line": ["123 Main St"],
153 "_line": [{"id": "hello-world"}],
154 "city": "Anytown",
155 "_city": {
156 "id": "city-id"
157 },
158 "state": "CA",
159 "postalCode": "12345"
160 }
161 "#;
162 let address: Address = serde_json::from_str::<Address>(address_string).unwrap();
163
164 let address_use: Option<String> = address.use_.unwrap().as_ref().into();
165 assert_eq!(address_use.unwrap(), "home".to_string());
166 assert_eq!(
167 address.line.as_ref().unwrap()[0].value.as_ref().unwrap(),
168 &"123 Main St".to_string()
169 );
170 assert_eq!(
171 address.line.as_ref().unwrap()[0].id.as_ref().unwrap(),
172 &"hello-world".to_string()
173 );
174 assert_eq!(
175 address.city.as_ref().unwrap().value.as_ref().unwrap(),
176 &"Anytown".to_string()
177 );
178 assert_eq!(address.state.unwrap().value.unwrap(), "CA".to_string());
179 assert_eq!(
180 address.postalCode.unwrap().value.unwrap(),
181 "12345".to_string()
182 );
183 assert_eq!(
184 address.city.as_ref().unwrap().id.as_ref().unwrap(),
185 &"city-id".to_string()
186 );
187 }
188
189 #[test]
190 fn test_invalid_address_with_extensions() {
191 let address_string = r#"
192 {
193 "line": ["123 Main St"],
194 "_line": {"id": "hello-world"}
195 }
196 "#;
197 let address = serde_json::from_str::<Address>(address_string);
198 assert!(address.is_err());
199
200 let address_string = r#"
201 {
202 "city": "Anytown",
203 "_city": 5
204 }
205 "#;
206 let address = serde_json::from_str::<Address>(address_string);
207 assert!(address.is_err());
208 }
209
210 #[test]
211 fn test_invalid_fields() {
212 let address_string = r#"
213 {
214 "line": ["123 Main St"],
215 "_line": [{"id": "hello-world"}],
216 "bad_field": "This should not be here"
217 }
218 "#;
219
220 let address = serde_json::from_str::<Address>(address_string);
221
222 assert!(matches!(address, Err(_)));
223 }
224
225 #[test]
226 fn test_serialization_bundle() {
227 let bundle_string = r#"
228 {
229 "resourceType": "Bundle",
230 "id": "bundle-example",
231 "meta": {
232 "lastUpdated": "2014-08-18T01:43:30Z"
233 },
234 "type": "searchset",
235 "total": 3,
236 "link": [
237 {
238 "relation": "self",
239 "url": "https://example.com/base/MedicationRequest?patient=347&_include=MedicationRequest.medication&_count=2"
240 },
241 {
242 "relation": "next",
243 "url": "https://example.com/base/MedicationRequest?patient=347&searchId=ff15fd40-ff71-4b48-b366-09c706bed9d0&page=2"
244 }
245 ],
246 "entry": [
247 {
248 "fullUrl": "https://example.com/base/MedicationRequest/3123",
249 "resource": {
250 "resourceType": "MedicationRequest",
251 "id": "3123",
252 "text": {
253 "status": "generated",
254 "div": "<div xmlns=\"http://www.w3.org/1999/xhtml\"><p><b>Generated Narrative with Details</b></p><p><b>id</b>: 3123</p><p><b>status</b>: unknown</p><p><b>intent</b>: order</p><p><b>medication</b>: <a>Medication/example</a></p><p><b>subject</b>: <a>Patient/347</a></p></div>"
255 },
256 "status": "unknown",
257 "intent": "order",
258 "medicationReference": {
259 "reference": "Medication/example"
260 },
261 "subject": {
262 "reference": "Patient/347"
263 }
264 },
265 "search": {
266 "mode": "match",
267 "score": 1
268 }
269 },
270 {
271 "fullUrl": "https://example.com/base/Medication/example",
272 "resource": {
273 "resourceType": "Medication",
274 "id": "example",
275 "text": {
276 "status": "generated",
277 "div": "<div xmlns=\"http://www.w3.org/1999/xhtml\"><p><b>Generated Narrative with Details</b></p><p><b>id</b>: example</p></div>"
278 }
279 },
280 "search": {
281 "mode": "include"
282 }
283 }
284 ]
285}
286 "#;
287
288 let bundle =
289 serde_json::from_str::<r4::generated::resources::Bundle>(bundle_string).unwrap();
290
291 assert!(matches!(
292 bundle.entry.as_ref().unwrap()[0]
293 .resource
294 .as_ref()
295 .unwrap()
296 .fhir_type(),
297 "MedicationRequest"
298 ));
299 }
300
301 #[test]
302 fn test_patient_resource() {
303 let patient_string = r#"
304 {
305 "resourceType": "Patient",
306 "address": [
307 {
308 "use": "home",
309 "line": ["123 Main St"],
310 "_line": [{"id": "hello-world"}],
311 "city": "Anytown",
312 "_city": {
313 "id": "city-id"
314 },
315 "state": "CA",
316 "postalCode": "12345"
317 },
318 {
319 "use": "home",
320 "line": ["123 Main St"],
321 "_line": [{"id": "hello-world"}],
322 "city": "Anytown",
323 "_city": {
324 "id": "city-id"
325 },
326 "state": "CA",
327 "postalCode": "12345"
328 },
329 {
330 "use": "home",
331 "line": ["123 Main St"],
332 "_line": [{"id": "hello-world"}],
333 "city": "Anytown",
334 "_city": {
335 "id": "city-id"
336 },
337 "state": "CA",
338 "postalCode": "12345"
339 },
340 {
341 "use": "home",
342 "line": ["123 Main St"],
343 "_line": [{"id": "hello-world"}],
344 "city": "Anytown",
345 "_city": {
346 "id": "city-id"
347 },
348 "state": "CA",
349 "postalCode": "12345"
350 },
351 {
352 "use": "home",
353 "line": ["123 Main St"],
354 "_line": [{"id": "hello-world"}],
355 "city": "Anytown",
356 "_city": {
357 "id": "city-id"
358 },
359 "state": "CA",
360 "postalCode": "12345"
361 }
362
363 ]
364 }
365 "#
366 .trim();
367
368 let patient = serde_json::from_str::<Patient>(patient_string);
369
370 assert!(matches!(patient, Ok(Patient { .. })));
371 assert_eq!(patient.as_ref().unwrap().address.as_ref().unwrap().len(), 5);
372
373 assert_eq!(
374 patient.as_ref().unwrap().address.as_ref().unwrap()[0]
375 .city
376 .as_ref()
377 .unwrap()
378 .value
379 .as_ref()
380 .unwrap(),
381 "Anytown"
382 );
383
384 let k = "{\"resourceType\":\"Patient\",\"address\":[{\"use\":\"home\",\"_line\":[{\"id\":\"hello-world\"}],\"line\":[\"123 Main St\"],\"city\":\"Anytown\",\"_city\":{\"id\":\"city-id\"},\"state\":\"CA\",\"postalCode\":\"12345\"},{\"use\":\"home\",\"_line\":[{\"id\":\"hello-world\"}],\"line\":[\"123 Main St\"],\"city\":\"Anytown\",\"_city\":{\"id\":\"city-id\"},\"state\":\"CA\",\"postalCode\":\"12345\"},{\"use\":\"home\",\"_line\":[{\"id\":\"hello-world\"}],\"line\":[\"123 Main St\"],\"city\":\"Anytown\",\"_city\":{\"id\":\"city-id\"},\"state\":\"CA\",\"postalCode\":\"12345\"},{\"use\":\"home\",\"_line\":[{\"id\":\"hello-world\"}],\"line\":[\"123 Main St\"],\"city\":\"Anytown\",\"_city\":{\"id\":\"city-id\"},\"state\":\"CA\",\"postalCode\":\"12345\"},{\"use\":\"home\",\"_line\":[{\"id\":\"hello-world\"}],\"line\":[\"123 Main St\"],\"city\":\"Anytown\",\"_city\":{\"id\":\"city-id\"},\"state\":\"CA\",\"postalCode\":\"12345\"}]}";
385
386 assert_eq!(k, serde_json::to_string(patient.as_ref().unwrap()).unwrap());
387
388 let patient2 = serde_json::from_str::<Patient>(k).unwrap();
389 assert_eq!(serde_json::to_string(&patient2).unwrap(), k);
390 }
391
392 #[test]
393 fn null_extension_many() {
394 let patient_string = r#"
395 {
396 "resourceType": "Patient",
397 "name": [
398 {
399 "family": "Doe",
400 "given": ["John", "A."],
401 "_given": [null, {"id": "given-2"}],
402 "prefix": ["Mr."]
403 }
404 ]
405 }"#;
406
407 let patient = serde_json::from_str::<Patient>(patient_string).unwrap();
408
409 assert_eq!(
410 patient.name.as_ref().unwrap()[0].given.as_ref().unwrap()[0]
411 .value
412 .as_ref()
413 .unwrap(),
414 "John"
415 );
416
417 assert_eq!(
418 patient.name.as_ref().unwrap()[0].given.as_ref().unwrap()[0]
419 .id
420 .is_none(),
421 true,
422 );
423
424 assert_eq!(
425 patient.name.as_ref().unwrap()[0].given.as_ref().unwrap()[1]
426 .id
427 .as_ref()
428 .unwrap(),
429 "given-2",
430 );
431
432 assert_eq!(
433 serde_json::to_string(&patient).unwrap(),
434 "{\"resourceType\":\"Patient\",\"name\":[{\"family\":\"Doe\",\"_given\":[null,{\"id\":\"given-2\"}],\"given\":[\"John\",\"A.\"],\"prefix\":[\"Mr.\"]}]}"
435 );
436 }
437
438 #[test]
439 fn test_with_nulls_array_primitives() {
440 let patient_string = r#"{
441 "resourceType": "Patient",
442 "name": [
443 {
444 "family": "Doe",
445 "_given": [
446 null,
447 {
448 "id": "given-2"
449 }
450 ],
451 "given": [
452 "John",
453 null
454 ],
455 "prefix": [
456 "Mr."
457 ]
458 }
459 ]}"#;
460
461 let patient = serde_json::from_str::<Patient>(patient_string).unwrap();
462 assert_eq!(
463 serde_json::to_string(&patient).unwrap(),
464 "{\"resourceType\":\"Patient\",\"name\":[{\"family\":\"Doe\",\"_given\":[null,{\"id\":\"given-2\"}],\"given\":[\"John\",null],\"prefix\":[\"Mr.\"]}]}"
465 );
466 }
467
468 #[test]
469 fn test_serde_terminology() {
470 use crate::r4::generated::terminology::AdministrativeGender;
471
472 let admin_gender = serde_json::from_str::<AdministrativeGender>("\"male\"");
473
474 assert!(matches!(admin_gender, Ok(AdministrativeGender::Male(None))));
475 }
476
477 #[test]
478 fn test_serde_primitve() {
479 use crate::r4::generated::types::{
480 FHIRBoolean, FHIRDate, FHIRDecimal, FHIRInteger, FHIRPositiveInt, FHIRString,
481 };
482
483 let date = serde_json::from_str::<FHIRDate>("\"2020-01-01\"");
484
485 assert!(matches!(
486 date,
487 Ok(FHIRDate {
488 value: Some(Date::YearMonthDay(2020, 1, 1)),
489 id: None,
490 extension: None
491 })
492 ));
493
494 let date = serde_json::from_str::<FHIRDate>("\"bad\"");
495
496 assert!(matches!(date, Err(_)));
497
498 let fhir_string = serde_json::from_str::<FHIRString>("\"hello\"");
499
500 assert!(matches!(
501 fhir_string,
502 Ok(FHIRString {
503 value: Some(_),
504 id: None,
505 extension: None
506 })
507 ));
508
509 let fhir_boolean = serde_json::from_str::<FHIRBoolean>("true");
510
511 assert!(matches!(
512 fhir_boolean,
513 Ok(FHIRBoolean {
514 value: Some(true),
515 id: None,
516 extension: None
517 })
518 ));
519
520 let fhir_boolean = serde_json::from_str::<FHIRBoolean>("false");
521
522 assert!(matches!(
523 fhir_boolean,
524 Ok(FHIRBoolean {
525 value: Some(false),
526 id: None,
527 extension: None
528 })
529 ));
530
531 let fhir_integer = serde_json::from_str::<FHIRInteger>("42");
532 assert!(matches!(
533 fhir_integer,
534 Ok(FHIRInteger {
535 value: Some(42),
536 id: None,
537 extension: None
538 })
539 ));
540
541 let fhir_positive_int = serde_json::from_str::<FHIRPositiveInt>("42");
542
543 assert!(matches!(
544 fhir_positive_int,
545 Ok(FHIRPositiveInt {
546 value: Some(42),
547 id: None,
548 extension: None
549 })
550 ));
551
552 let invalid_fhir_positive_int = serde_json::from_str::<FHIRPositiveInt>("42.5");
553 assert!(matches!(invalid_fhir_positive_int, Err(_)));
554
555 let invalid_positive_int = serde_json::from_str::<FHIRPositiveInt>("-1");
556 assert!(matches!(invalid_positive_int, Err(_)));
557
558 let fhir_decimal = serde_json::from_str::<FHIRDecimal>("3.14");
559 assert!(matches!(
560 fhir_decimal,
561 Ok(FHIRDecimal {
562 value: Some(3.14),
563 id: None,
564 extension: None
565 })
566 ));
567 }
568
569 #[test]
570 fn test_cardinality() {
571 let client_application_string = r#"{
572 "id": "cli",
573 "resourceType": "ClientApplication",
574 "name": "CLI",
575 "grantType": ["authorization_code"],
576 "responseTypes": "token",
577 "secret": "testing",
578 "redirectUri": [
579 "http://localhost:8080/1",
580 "http://localhost:8080/2",
581 "http://localhost:8080/3",
582 "http://localhost:8080/4",
583 "http://localhost:8080/5"],
584 "scope": "openid system/*.*"
585 }"#;
586
587 let client_app = serde_json::from_str::<ClientApplication>(&client_application_string);
588
589 assert!(client_app.is_ok());
590
591 let client_application_string = r#"{
592 "id": "cli",
593 "resourceType": "ClientApplication",
594 "name": "CLI",
595 "grantType": ["authorization_code"],
596 "responseTypes": "token",
597 "secret": "testing",
598 "redirectUri": [
599 "http://localhost:8080/1",
600 "http://localhost:8080/2",
601 "http://localhost:8080/3",
602 "http://localhost:8080/4",
603 "http://localhost:8080/5",
604 "http://localhost:8080/6"],
605 "scope": "openid system/*.*"
606 }"#;
607
608 let client_app = serde_json::from_str::<ClientApplication>(&client_application_string);
609
610 assert!(client_app.is_err());
611 }
612
613 #[test]
614 fn test_empty_vec() {
615 let patient = r#"{
616 "resourceType": "Patient",
617 "name": []
618 }"#;
619
620 let patient =
621 serde_json::from_str::<Patient>(patient).expect("failed to deserialize patient");
622
623 assert_eq!(patient.name.is_none(), true);
624 }
625
626 #[test]
627 fn test_empty_fields() {
628 let patient = r#"{
629 "id": "",
630 "resourceType": "Patient",
631 "name": [{"family": "", "given": [""], "prefix": [""]}]
632 }"#;
633 let patient = serde_json::from_str::<Patient>(patient).unwrap();
634
635 assert_eq!(patient.name.is_none(), true);
636
637 let patient = r#"{
638 "id": "",
639 "resourceType": "Patient",
640 "name": [{"family": "test", "given": [""], "prefix": [""]}]
641 }"#;
642 let patient = serde_json::from_str::<Patient>(patient).unwrap();
643 let name = patient.name.unwrap()[0].clone();
644
645 assert_eq!(
646 name.family
647 .as_ref()
648 .and_then(|s| s.value.as_ref())
649 .map(|s| s.as_str()),
650 Some("test")
651 );
652 assert_eq!(name.given.is_none(), true);
653 assert_eq!(name.prefix.is_none(), true);
654
655 let patient = r#"{
656 "id": "",
657 "resourceType": "Patient",
658 "name": [{"family": "", "given": [""], "prefix": ["mr"]}]
659 }"#;
660 let patient = serde_json::from_str::<Patient>(patient).unwrap();
661 let name = patient.name.unwrap()[0].clone();
662
663 assert_eq!(
664 name.prefix.clone().unwrap()[0]
665 .value
666 .as_ref()
667 .map(|s| s.as_str()),
668 Some("mr")
669 );
670 assert_eq!(name.family.is_none(), true);
671 assert_eq!(name.given.is_none(), true);
672 }
673}