From 34105af7345dfd95340ea64511bd5b34b4266251 Mon Sep 17 00:00:00 2001 From: KaelynJefferson <106775284+KaelynJefferson@users.noreply.github.com> Date: Thu, 27 Jun 2024 14:08:11 -0400 Subject: [PATCH] Warn when reference values do not resolve and have incorrect format (#1468) * Warn when reference values do not resolve and are not in correct format for a reference. * additional check for fhir reference format, log when reference is not of type/id format or when too/many/parts * update check for absolute url * Removing conditional for logging reference value with more/than/two/parts since acceptable reference format * update reference warn message, account for reference case of uuid or oid * combining conditional statements --- src/fhirtypes/common.ts | 8 +++ test/export/InstanceExporter.test.ts | 79 +++++++++++++++++++++++++++- 2 files changed, 86 insertions(+), 1 deletion(-) diff --git a/src/fhirtypes/common.ts b/src/fhirtypes/common.ts index fa3264849..84c6c9044 100644 --- a/src/fhirtypes/common.ts +++ b/src/fhirtypes/common.ts @@ -979,6 +979,14 @@ export function replaceReferences( clone = cloneDeep(rule); (clone.value as FshReference).reference = value.reference.slice(0, firstPipe); clone = replaceReferences(clone, tank, fisher); + } else if (type == null && id == null && value.reference) { + // if the reference to an entity is provided but is unable to be resolved + if (!(value.reference.startsWith('urn:') || value.reference.includes('/'))) { + logger.warn( + `Cannot find the entity referenced at ${value.reference}. The provided reference value will be used, but this reference does not conform to the FHIR Reference format.`, + rule.sourceInfo + ); + } } } } else if (value instanceof FshCode) { diff --git a/test/export/InstanceExporter.test.ts b/test/export/InstanceExporter.test.ts index 3002d29ae..67f2b0a61 100644 --- a/test/export/InstanceExporter.test.ts +++ b/test/export/InstanceExporter.test.ts @@ -5486,6 +5486,7 @@ describe('InstanceExporter', () => { expect(exported.managingOrganization).toEqual({ reference: 'Organization/org-id' }); + expect(loggerSpy.getAllMessages('warn')).toHaveLength(0); }); it('should assign a reference while resolving the Instance of a profile being referred to', () => { @@ -5533,6 +5534,82 @@ describe('InstanceExporter', () => { ]); }); + it('should log warning when reference values do not resolve and is not an absolute or relative URL', () => { + // * target = Reference(exampleReferenceUnableToBeResolved) + const assignedRefRule = new AssignmentRule('target'); + assignedRefRule.value = new FshReference('exampleReferenceUnableToBeResolved'); + provenanceInstance.rules.push(assignedRefRule); + const exported = exportInstance(provenanceInstance); + expect(exported.target).toEqual([ + { + reference: 'exampleReferenceUnableToBeResolved' + } + ]); + expect(loggerSpy.getAllMessages('warn')).toHaveLength(1); + expect(loggerSpy.getLastMessage('warn')).toMatch( + 'Cannot find the entity referenced at exampleReferenceUnableToBeResolved. The provided reference value will be used, but this reference does not conform to the FHIR Reference format.' + ); + }); + it('should not log warning when reference values do not resolve and is a UUID or OID', () => { + // * target = Reference(urn:uuid:exampleReference) + const assignedRefRule = new AssignmentRule('target'); + assignedRefRule.value = new FshReference('urn:uuid:exampleReference'); + provenanceInstance.rules.push(assignedRefRule); + const exported = exportInstance(provenanceInstance); + expect(exported.target).toEqual([ + { + reference: 'urn:uuid:exampleReference' + } + ]); + expect(loggerSpy.getAllMessages('warn')).toHaveLength(0); + }); + + it('should not log warning when reference values do not resolve and is a relative URL with correct number of parts', () => { + // * target = Reference(UnresolvableType/exampleReferenceUnableToBeResolved) + const assignedRefRule = new AssignmentRule('target'); + assignedRefRule.value = new FshReference( + 'UnresolvableType/exampleReferenceUnableToBeResolved' + ); + provenanceInstance.rules.push(assignedRefRule); + const exported = exportInstance(provenanceInstance); + expect(exported.target).toEqual([ + { + reference: 'UnresolvableType/exampleReferenceUnableToBeResolved' + } + ]); + expect(loggerSpy.getAllMessages('warn')).toHaveLength(0); + }); + + it('should not log warning when reference values do not resolve and is a relative URL but has more than two parts', () => { + // * target = Reference(More/Than/Two/Parts/exampleReferenceUnableToBeResolved) + const assignedRefRule = new AssignmentRule('target'); + assignedRefRule.value = new FshReference( + 'More/Than/Two/Parts/exampleReferenceUnableToBeResolved' + ); + provenanceInstance.rules.push(assignedRefRule); + const exported = exportInstance(provenanceInstance); + expect(exported.target).toEqual([ + { + reference: 'More/Than/Two/Parts/exampleReferenceUnableToBeResolved' + } + ]); + expect(loggerSpy.getAllMessages('warn')).toHaveLength(0); + }); + + it('should not log warning when reference values are an absolute URL', () => { + // * target = Reference(http://foo.org/fhir/Patient/abc) + const assignedRefRule = new AssignmentRule('target'); + assignedRefRule.value = new FshReference('http://foo.org/fhir/Patient/abc'); + provenanceInstance.rules.push(assignedRefRule); + const exported = exportInstance(provenanceInstance); + expect(exported.target).toEqual([ + { + reference: 'http://foo.org/fhir/Patient/abc' + } + ]); + expect(loggerSpy.getAllMessages('warn')).toHaveLength(0); + }); + it('should assign a reference leaving the full profile URL when it is specified', () => { const assignedRefRule = new AssignmentRule('target'); assignedRefRule.value = new FshReference( @@ -10190,7 +10267,7 @@ describe('InstanceExporter', () => { } ] }); - expect(loggerSpy.getAllLogs('warn')).toBeEmpty(); + expect(loggerSpy.getAllMessages('warn')).toHaveLength(0); expect(loggerSpy.getAllLogs('error')).toBeEmpty(); });