@@ -17,62 +17,112 @@ import type { Patient } from "./fhir-types/hl7-fhir-r4-core/Patient";
1717const smithPatient : Patient = { resourceType : "Patient" , name : [ { family : "Smith" } ] } ;
1818const activePatient : Patient = { resourceType : "Patient" , active : true } ;
1919const clinicOrg : Organization = { resourceType : "Organization" , name : "Clinic" } ;
20+ const acmeOrg : Organization = { resourceType : "Organization" , name : "Acme" } ;
2021
21- describe ( "type-discriminated bundle slices " , ( ) => {
22- test ( "create() starts with no entry — PatientEntry must be set by user " , ( ) => {
22+ describe ( "demo: single-element slice (max: 1) — PatientEntry " , ( ) => {
23+ test ( "create, set, and validate a typed patient entry " , ( ) => {
2324 const bundle = ExampleTypedBundleProfile . create ( { type : "collection" } ) ;
24- expect ( bundle . toResource ( ) . entry ) . toBeUndefined ( ) ;
25+
26+ // No entry yet — validation fails (PatientEntry min: 1)
2527 expect ( bundle . validate ( ) . errors ) . toEqual ( [
2628 "ExampleTypedBundle.entry: slice 'PatientEntry' requires at least 1 item(s), found 0" ,
2729 ] ) ;
28- } ) ;
2930
30- test ( "setPatientEntry inserts a typed patient entry" , ( ) => {
31- const bundle = ExampleTypedBundleProfile . create ( { type : "collection" } ) ;
31+ // Set a single patient entry — typed as BundleEntry<Patient>
3232 bundle . setPatientEntry ( { resource : smithPatient } ) ;
33+ expect ( bundle . validate ( ) . errors ) . toEqual ( [ ] ) ;
3334
35+ // Getter returns the entry with resource narrowed to Patient
3436 const entry = bundle . getPatientEntry ( ) ! ;
3537 expect ( entry . resource ) . toEqual ( smithPatient ) ;
36- expect ( bundle . validate ( ) . errors ) . toEqual ( [ ] ) ;
3738 } ) ;
3839
39- test ( "setPatientEntry replaces existing patient entry (no duplicates)" , ( ) => {
40+ test ( "setPatientEntry replaces existing entry (no duplicates)" , ( ) => {
4041 const bundle = ExampleTypedBundleProfile . create ( { type : "collection" } ) ;
4142 bundle . setPatientEntry ( { resource : smithPatient } ) ;
4243 bundle . setPatientEntry ( { resource : activePatient } ) ;
4344
44- const entries = bundle . toResource ( ) . entry ! ;
45- expect ( entries ) . toHaveLength ( 1 ) ;
46- expect ( entries [ 0 ] ! . resource ) . toEqual ( activePatient ) ;
45+ // Only one patient entry — the second call replaced the first
46+ expect ( bundle . toResource ( ) . entry ) . toHaveLength ( 1 ) ;
47+ expect ( bundle . getPatientEntry ( ) ! . resource ) . toEqual ( activePatient ) ;
4748 } ) ;
49+ } ) ;
4850
49- test ( "getPatientEntry('flat') returns the entry as-is (no keys stripped)" , ( ) => {
50- const bundle = ExampleTypedBundleProfile . create ( { type : "collection" } ) ;
51- bundle . setPatientEntry ( { fullUrl : "urn:uuid:patient-1" , resource : activePatient } ) ;
51+ describe ( "demo: unbounded slice (max: *) — OrganizationEntry" , ( ) => {
52+ test ( "setter accepts an array, getter returns an array" , ( ) => {
53+ const bundle = ExampleTypedBundleProfile . create ( { type : "collection" } ) . setPatientEntry ( {
54+ resource : activePatient ,
55+ } ) ;
56+
57+ // Set multiple organization entries at once
58+ bundle . setOrganizationEntry ( [ { resource : clinicOrg } , { resource : acmeOrg } ] ) ;
5259
53- const flat = bundle . getPatientEntry ( "flat" ) ! ;
54- expect ( flat . fullUrl ) . toBe ( "urn:uuid:patient-1" ) ;
55- expect ( flat . resource ) . toEqual ( activePatient ) ;
60+ // Getter returns all matching entries as an array (undefined if none)
61+ const orgs = bundle . getOrganizationEntry ( ) ! ;
62+ expect ( orgs ) . toHaveLength ( 2 ) ;
63+ expect ( orgs [ 0 ] ! . resource ) . toEqual ( clinicOrg ) ;
64+ expect ( orgs [ 1 ] ! . resource ) . toEqual ( acmeOrg ) ;
65+
66+ // Total entries: 1 patient + 2 organizations
67+ expect ( bundle . toResource ( ) . entry ) . toHaveLength ( 3 ) ;
5668 } ) ;
5769
58- test ( "fluent chaining across slice setters " , ( ) => {
70+ test ( "setOrganizationEntry replaces all previous org entries " , ( ) => {
5971 const bundle = ExampleTypedBundleProfile . create ( { type : "collection" } )
6072 . setPatientEntry ( { resource : activePatient } )
61- . setOrganizationEntry ( { resource : clinicOrg } ) ;
73+ . setOrganizationEntry ( [ { resource : clinicOrg } , { resource : acmeOrg } ] ) ;
74+
75+ // Replace with a single org — previous two are removed
76+ bundle . setOrganizationEntry ( [ { resource : { resourceType : "Organization" , name : "NewCo" } } ] ) ;
77+
78+ const orgs = bundle . getOrganizationEntry ( ) ! ;
79+ expect ( orgs ) . toHaveLength ( 1 ) ;
80+ expect ( orgs [ 0 ] ! . resource ! . name ) . toBe ( "NewCo" ) ;
6281
63- expect ( bundle . toResource ( ) . entry ) . toHaveLength ( 2 ) ;
82+ // Patient entry unaffected
6483 expect ( bundle . getPatientEntry ( ) ! . resource ) . toEqual ( activePatient ) ;
65- expect ( bundle . getOrganizationEntry ( ) ! . resource ) . toEqual ( clinicOrg ) ;
6684 } ) ;
6785
68- test ( "setOrganizationEntry replaces existing org entry (same discriminator) " , ( ) => {
86+ test ( "append to existing entries via spread " , ( ) => {
6987 const bundle = ExampleTypedBundleProfile . create ( { type : "collection" } )
7088 . setPatientEntry ( { resource : activePatient } )
71- . setOrganizationEntry ( { resource : clinicOrg } )
72- . setOrganizationEntry ( { resource : { resourceType : "Organization" , name : "Acme" } } ) ;
89+ . setOrganizationEntry ( [ { resource : clinicOrg } ] ) ;
90+
91+ // Append a new org by spreading existing entries
92+ bundle . setOrganizationEntry ( [ ...( bundle . getOrganizationEntry ( ) ?? [ ] ) , { resource : acmeOrg } ] ) ;
93+
94+ const orgs = bundle . getOrganizationEntry ( ) ! ;
95+ expect ( orgs ) . toHaveLength ( 2 ) ;
96+ expect ( orgs [ 0 ] ! . resource ) . toEqual ( clinicOrg ) ;
97+ expect ( orgs [ 1 ] ! . resource ) . toEqual ( acmeOrg ) ;
98+ } ) ;
99+
100+ test ( "empty array removes all org entries, getter returns undefined" , ( ) => {
101+ const bundle = ExampleTypedBundleProfile . create ( { type : "collection" } )
102+ . setPatientEntry ( { resource : activePatient } )
103+ . setOrganizationEntry ( [ { resource : clinicOrg } ] ) ;
104+
105+ bundle . setOrganizationEntry ( [ ] ) ;
106+
107+ // No matching entries — returns undefined, not empty array
108+ expect ( bundle . getOrganizationEntry ( ) ) . toBeUndefined ( ) ;
109+ // Patient entry still present
110+ expect ( bundle . toResource ( ) . entry ) . toHaveLength ( 1 ) ;
111+ } ) ;
112+ } ) ;
113+
114+ describe ( "fluent chaining across slice types" , ( ) => {
115+ test ( "chain single and array setters" , ( ) => {
116+ const bundle = ExampleTypedBundleProfile . create ( { type : "collection" } )
117+ . setPatientEntry ( { fullUrl : "urn:uuid:patient-1" , resource : activePatient } )
118+ . setOrganizationEntry ( [
119+ { fullUrl : "urn:uuid:org-1" , resource : clinicOrg } ,
120+ { fullUrl : "urn:uuid:org-2" , resource : acmeOrg } ,
121+ ] ) ;
73122
74- const entries = bundle . toResource ( ) . entry ! ;
75- expect ( entries ) . toHaveLength ( 2 ) ;
76- expect ( bundle . getOrganizationEntry ( ) ! . resource ! . name ) . toBe ( "Acme" ) ;
123+ expect ( bundle . toResource ( ) . entry ) . toHaveLength ( 3 ) ;
124+ expect ( bundle . getPatientEntry ( ) ! . fullUrl ) . toBe ( "urn:uuid:patient-1" ) ;
125+ expect ( bundle . getOrganizationEntry ( ) ! [ 0 ] ! . fullUrl ) . toBe ( "urn:uuid:org-1" ) ;
126+ expect ( bundle . getOrganizationEntry ( ) ! [ 1 ] ! . fullUrl ) . toBe ( "urn:uuid:org-2" ) ;
77127 } ) ;
78128} ) ;
0 commit comments