haste_fhir_model/
lib.rs

1pub mod r4;
2
3#[cfg(test)]
4mod tests {
5    use super::*;
6    use crate::r4::generated::resources::{Practitioner, Resource};
7    use haste_fhir_serialization_json::{FHIRJSONDeserializer, errors::DeserializeError};
8    use haste_reflect::MetaValue;
9    use r4::generated::{resources::Patient, types::Address};
10    use serde_json;
11
12    #[test]
13    fn test_enum_with_extension() {
14        let term_ = r4::generated::terminology::AdministrativeGender::Male(Some(
15            r4::generated::types::Element {
16                id: Some("test".to_string()),
17                ..r4::generated::types::Element::default()
18            },
19        ));
20        assert_eq!(term_.typename(), "FHIRCode");
21        let k = term_
22            .get_field("value")
23            .unwrap()
24            .as_any()
25            .downcast_ref::<String>()
26            .unwrap();
27        assert_eq!(k, &"male");
28    }
29
30    #[test]
31    fn test_serializing_string_html() {
32        let k = r#""<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>""#;
33        let parsed_str_serde =
34            serde_json::to_string(&serde_json::from_str::<serde_json::Value>(k).unwrap()).unwrap();
35
36        assert_eq!(
37            parsed_str_serde,
38            haste_fhir_serialization_json::to_string(
39                &haste_fhir_serialization_json::from_str::<String>(k).unwrap()
40            )
41            .unwrap()
42        );
43    }
44
45    #[test]
46    fn enum_resource_type_variant() {
47        let resource = haste_fhir_serialization_json::from_str::<Resource>(
48            r#"{
49            "resourceType": "Patient",
50            "address": [
51                {
52                    "use": "home",
53                    "line": ["123 Main St"],
54                    "_line": [{"id": "hello-world"}],
55                    "city": "Anytown",
56                    "_city": {
57                        "id": "city-id"
58                    },
59                    "state": "CA",
60                    "postalCode": "12345"
61                }]
62            
63            }"#,
64        );
65
66        assert!(matches!(resource, Ok(Resource::Patient(Patient { .. }))));
67
68        let resource = haste_fhir_serialization_json::from_str::<Resource>(
69            r#"{
70  "resourceType": "Practitioner",
71  "id": "example",
72  "text": {
73    "status": "generated",
74    "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>"
75  },
76  "identifier": [
77    {
78      "system": "http://www.acme.org/practitioners",
79      "value": "23"
80    }
81  ],
82  "active": true,
83  "name": [
84    {
85      "family": "Careful",
86      "given": [
87        "Adam"
88      ],
89      "prefix": [
90        "Dr"
91      ]
92    }
93  ],
94  "address": [
95    {
96      "use": "home",
97      "line": [
98        "534 Erewhon St"
99      ],
100      "city": "PleasantVille",
101      "state": "Vic",
102      "postalCode": "3999"
103    }
104  ],
105  "qualification": [
106    {
107      "identifier": [
108        {
109          "system": "http://example.org/UniversityIdentifier",
110          "value": "12345"
111        }
112      ],
113      "code": {
114        "coding": [
115          {
116            "system": "http://terminology.hl7.org/CodeSystem/v2-0360/2.7",
117            "code": "BS",
118            "display": "Bachelor of Science"
119          }
120        ],
121        "text": "Bachelor of Science"
122      },
123      "period": {
124        "start": "1995"
125      },
126      "issuer": {
127        "display": "Example University"
128      }
129    }
130  ]
131}"#,
132        );
133
134        assert!(matches!(
135            resource,
136            Ok(Resource::Practitioner(Practitioner { .. }))
137        ));
138
139        assert_eq!(
140            "{\"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\"}}]}",
141            haste_fhir_serialization_json::to_string(resource.as_ref().unwrap()).unwrap()
142        );
143    }
144
145    #[test]
146    fn test_valid_address_with_extensions() {
147        let address_string = r#"
148        {
149            "use": "home",
150            "line": ["123 Main St"],
151            "_line": [{"id": "hello-world"}],
152            "city": "Anytown",
153            "_city": {
154                "id": "city-id"
155            },
156            "state": "CA",
157            "postalCode": "12345"
158        }
159        "#;
160        let address: Address = Address::from_json_str(address_string).unwrap();
161        let address_use: Option<String> = address.use_.unwrap().as_ref().into();
162        assert_eq!(address_use.unwrap(), "home".to_string());
163        assert_eq!(
164            address.line.as_ref().unwrap()[0].value.as_ref().unwrap(),
165            &"123 Main St".to_string()
166        );
167        assert_eq!(
168            address.line.as_ref().unwrap()[0].id.as_ref().unwrap(),
169            &"hello-world".to_string()
170        );
171        assert_eq!(
172            address.city.as_ref().unwrap().value.as_ref().unwrap(),
173            &"Anytown".to_string()
174        );
175        assert_eq!(address.state.unwrap().value.unwrap(), "CA".to_string());
176        assert_eq!(
177            address.postalCode.unwrap().value.unwrap(),
178            "12345".to_string()
179        );
180        assert_eq!(
181            address.city.as_ref().unwrap().id.as_ref().unwrap(),
182            &"city-id".to_string()
183        );
184    }
185
186    #[test]
187    fn test_invalid_address_with_extensions() {
188        let address_string = r#"
189        {
190            "line": ["123 Main St"],
191            "_line": {"id": "hello-world"}
192        }
193        "#;
194        let address = Address::from_json_str(address_string);
195        assert!(matches!(address, Err(DeserializeError::InvalidType(_))));
196
197        let address_string = r#"
198        {
199            "city": "Anytown",
200            "_city": 5
201        }
202        "#;
203        let address = Address::from_json_str(address_string);
204        assert!(matches!(address, Err(DeserializeError::InvalidType(_))));
205    }
206
207    #[test]
208    fn test_invalid_fields() {
209        let address_string = r#"
210        {
211            "line": ["123 Main St"],
212            "_line": [{"id": "hello-world"}],
213            "bad_field": "This should not be here"
214        }
215        "#;
216
217        let address = Address::from_json_str(address_string);
218
219        assert_eq!(
220            address.unwrap_err().to_string(),
221            "Unknown field encountered: Address: 'bad_field'"
222        );
223    }
224
225    #[test]
226    fn test_serialization_bundle() {
227        let bundle = 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: r4::generated::resources::Bundle =
289            r4::generated::resources::Bundle::from_json_str(bundle).unwrap();
290        assert_eq!(bundle.entry.as_ref().unwrap().len(), 2);
291        let k = bundle.entry.as_ref().unwrap()[0]
292            .resource
293            .as_ref()
294            .unwrap()
295            .typename();
296
297        assert!(matches!(k, "MedicationRequest"));
298    }
299
300    #[test]
301    fn test_patient_resource() {
302        let patient_string = r#"
303        {
304            "resourceType": "Patient",
305            "address": [
306                {
307                    "use": "home",
308                    "line": ["123 Main St"],
309                    "_line": [{"id": "hello-world"}],
310                    "city": "Anytown",
311                    "_city": {
312                        "id": "city-id"
313                    },
314                    "state": "CA",
315                    "postalCode": "12345"
316                },
317                {
318                    "use": "home",
319                    "line": ["123 Main St"],
320                    "_line": [{"id": "hello-world"}],
321                    "city": "Anytown",
322                    "_city": {
323                        "id": "city-id"
324                    },
325                    "state": "CA",
326                    "postalCode": "12345"
327                },
328                {
329                    "use": "home",
330                    "line": ["123 Main St"],
331                    "_line": [{"id": "hello-world"}],
332                    "city": "Anytown",
333                    "_city": {
334                        "id": "city-id"
335                    },
336                    "state": "CA",
337                    "postalCode": "12345"
338                },
339                {
340                    "use": "home",
341                    "line": ["123 Main St"],
342                    "_line": [{"id": "hello-world"}],
343                    "city": "Anytown",
344                    "_city": {
345                        "id": "city-id"
346                    },
347                    "state": "CA",
348                    "postalCode": "12345"
349                },
350                {
351                    "use": "home",
352                    "line": ["123 Main St"],
353                    "_line": [{"id": "hello-world"}],
354                    "city": "Anytown",
355                    "_city": {
356                        "id": "city-id"
357                    },
358                    "state": "CA",
359                    "postalCode": "12345"
360                }
361
362            ]
363        }
364        "#
365        .trim();
366
367        let patient = Patient::from_json_str(patient_string);
368
369        assert!(matches!(patient, Ok(Patient { .. })));
370        assert_eq!(patient.as_ref().unwrap().address.as_ref().unwrap().len(), 5);
371
372        assert_eq!(
373            patient.as_ref().unwrap().address.as_ref().unwrap()[0]
374                .city
375                .as_ref()
376                .unwrap()
377                .value
378                .as_ref()
379                .unwrap(),
380            "Anytown"
381        );
382
383        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\"}]}";
384
385        assert_eq!(
386            k,
387            haste_fhir_serialization_json::to_string(patient.as_ref().unwrap()).unwrap(),
388        );
389
390        let patient2 = Patient::from_json_str(k).unwrap();
391        assert_eq!(
392            haste_fhir_serialization_json::to_string(&patient2).unwrap(),
393            k
394        );
395    }
396}