From a91a52cf7514e82b00e1790cfa2f20753e219608 Mon Sep 17 00:00:00 2001 From: Aleksandr Penskoi Date: Mon, 1 Jun 2026 13:41:15 +0200 Subject: [PATCH] TS: add example test demonstrating fixed[x] merge corner case - new PatientFixedMaritalStatus profile (true fixedCodeableConcept on maritalStatus) - runtime test exercising generated apply(): - create() materializes exactly the fixed value - apply() on a resource with a conflicting coding + text merges instead of replacing, and validate() still passes (validateFixedValue uses containment) - register the profile in the example tree-shake config --- .../profile-fixed-marital-status.test.ts.snap | 44 +++++++++++++ examples/local-package-folder/generate.ts | 1 + .../profile-fixed-marital-status.test.ts | 65 +++++++++++++++++++ ...ed-marital-status.structuredefinition.json | 32 +++++++++ 4 files changed, 142 insertions(+) create mode 100644 examples/local-package-folder/__snapshots__/profile-fixed-marital-status.test.ts.snap create mode 100644 examples/local-package-folder/profile-fixed-marital-status.test.ts create mode 100644 examples/local-package-folder/structure-definitions/patient-fixed-marital-status.structuredefinition.json diff --git a/examples/local-package-folder/__snapshots__/profile-fixed-marital-status.test.ts.snap b/examples/local-package-folder/__snapshots__/profile-fixed-marital-status.test.ts.snap new file mode 100644 index 00000000..ff7d3175 --- /dev/null +++ b/examples/local-package-folder/__snapshots__/profile-fixed-marital-status.test.ts.snap @@ -0,0 +1,44 @@ +// Bun Snapshot v1, https://bun.sh/docs/test/snapshots + +exports[`demo: create() materializes the fixed maritalStatus create() produces exactly the fixed CodeableConcept 1`] = ` +{ + "maritalStatus": { + "coding": [ + { + "code": "M", + "system": "http://terminology.hl7.org/CodeSystem/v3-MaritalStatus", + }, + ], + }, + "meta": { + "profile": [ + "http://example.org/fhir/StructureDefinition/PatientFixedMaritalStatus", + ], + }, + "resourceType": "Patient", +} +`; + +exports[`corner case: apply() merges a true fixed[x] instead of replacing it conflicting caller coding and text survive the fixed-value apply() 1`] = ` +{ + "maritalStatus": { + "coding": [ + { + "code": "S", + "system": "http://terminology.hl7.org/CodeSystem/v3-MaritalStatus", + }, + { + "code": "M", + "system": "http://terminology.hl7.org/CodeSystem/v3-MaritalStatus", + }, + ], + "text": "Never married (caller-provided)", + }, + "meta": { + "profile": [ + "http://example.org/fhir/StructureDefinition/PatientFixedMaritalStatus", + ], + }, + "resourceType": "Patient", +} +`; diff --git a/examples/local-package-folder/generate.ts b/examples/local-package-folder/generate.ts index cb2b3684..74981544 100644 --- a/examples/local-package-folder/generate.ts +++ b/examples/local-package-folder/generate.ts @@ -23,6 +23,7 @@ async function generateFromLocalPackageFolder() { "http://example.org/fhir/StructureDefinition/ExampleNotebook": {}, "http://example.org/fhir/StructureDefinition/ExampleTypedBundle": {}, "http://example.org/fhir/StructureDefinition/PatientMetaRequired": {}, + "http://example.org/fhir/StructureDefinition/PatientFixedMaritalStatus": {}, }, "hl7.fhir.r4.core": { "http://hl7.org/fhir/StructureDefinition/Patient": {}, diff --git a/examples/local-package-folder/profile-fixed-marital-status.test.ts b/examples/local-package-folder/profile-fixed-marital-status.test.ts new file mode 100644 index 00000000..5b46bf8a --- /dev/null +++ b/examples/local-package-folder/profile-fixed-marital-status.test.ts @@ -0,0 +1,65 @@ +/** + * PatientFixedMaritalStatus profile — demonstrates the corner case for a *true* + * fixedCodeableConcept (FHIR `fixed[x]`, which has exact-equality semantics). + * + * The generator emits the same merging `applyFixedValue(...)` for `fixed[x]` as it does + * for `pattern[x]` / slice discriminators. For a genuine `fixed[x]`, FHIR requires the + * element to be *exactly equal* to the fixed value, so any conflicting or extra caller + * data must be dropped. The generated code instead merges and keeps it — and `validate()` + * accepts the result because `validateFixedValue` checks containment, not equality. + * + * These tests pin down that current behavior on real generated code, so a future fix that + * branches on `valueConstraint.kind` ("fixed" -> replace, "pattern" -> merge) has a clear + * failing anchor to update. + */ + +import { describe, expect, test } from "bun:test"; +import { PatientFixedMaritalStatusProfile } from "./fhir-types/example-folder-structures/profiles/Patient_PatientFixedMaritalStatus"; +import type { Patient } from "./fhir-types/hl7-fhir-r4-core/Patient"; + +const maritalSystem = "http://terminology.hl7.org/CodeSystem/v3-MaritalStatus"; + +describe("demo: create() materializes the fixed maritalStatus", () => { + test("create() produces exactly the fixed CodeableConcept", () => { + const profile = PatientFixedMaritalStatusProfile.create(); + const resource = profile.toResource(); + + // Built from scratch, so the element equals exactly the fixed value. + expect(resource.maritalStatus).toEqual({ coding: [{ system: maritalSystem, code: "M" }] }); + expect(profile.validate().errors).toEqual([]); + expect(resource).toMatchSnapshot(); + }); +}); + +describe("corner case: apply() merges a true fixed[x] instead of replacing it", () => { + test("conflicting caller coding and text survive the fixed-value apply()", () => { + // Caller already set maritalStatus to a *different* code in the same system, plus free text. + const patient: Patient = { + resourceType: "Patient", + maritalStatus: { + text: "Never married (caller-provided)", + coding: [{ system: maritalSystem, code: "S" }], + }, + }; + + const profile = PatientFixedMaritalStatusProfile.apply(patient); + const resource = profile.toResource(); + + // FHIR `fixed[x]` would require: maritalStatus === { coding: [{ system, code: "M" }] } + // i.e. the caller's text and the conflicting "S" coding dropped. Instead the merge keeps + // the caller text and *appends* the fixed "M" coding next to the conflicting "S" one. + expect(resource.maritalStatus).toEqual({ + text: "Never married (caller-provided)", + coding: [ + { system: maritalSystem, code: "S" }, + { system: maritalSystem, code: "M" }, + ], + }); + + // ...and validate() passes anyway: validateFixedValue uses containment (matchesValue), so + // the mere presence of the fixed coding satisfies it even though the resource is not + // exactly equal to the fixed value a strict `fixed[x]` would mandate. + expect(profile.validate().errors).toEqual([]); + expect(resource).toMatchSnapshot(); + }); +}); diff --git a/examples/local-package-folder/structure-definitions/patient-fixed-marital-status.structuredefinition.json b/examples/local-package-folder/structure-definitions/patient-fixed-marital-status.structuredefinition.json new file mode 100644 index 00000000..2cffb609 --- /dev/null +++ b/examples/local-package-folder/structure-definitions/patient-fixed-marital-status.structuredefinition.json @@ -0,0 +1,32 @@ +{ + "resourceType": "StructureDefinition", + "id": "patient-fixed-marital-status", + "url": "http://example.org/fhir/StructureDefinition/PatientFixedMaritalStatus", + "version": "0.0.1", + "name": "PatientFixedMaritalStatus", + "title": "Patient Profile with a fixed maritalStatus CodeableConcept", + "status": "draft", + "fhirVersion": "4.0.1", + "kind": "resource", + "abstract": false, + "type": "Patient", + "baseDefinition": "http://hl7.org/fhir/StructureDefinition/Patient", + "derivation": "constraint", + "differential": { + "element": [ + { + "id": "Patient.maritalStatus", + "path": "Patient.maritalStatus", + "min": 1, + "fixedCodeableConcept": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/v3-MaritalStatus", + "code": "M" + } + ] + } + } + ] + } +}