Repository: FHIR/sushi
Pull request #1236 (2023-03-09 20:58:18)

Automatically load hl7.fhir.uv.extensions for FHIR R5 (Draft Final and Final)
This is a port of https://github.com/FHIR/sushi/pull/1234 to the v2.x branch. The cherry-pick procedure caused conflicts only in the unit tests, which I resolved manually.

Starting w/ FHIR 5.0.0-draft-final, FHIR no longer includes extensions in the core package. This PR will load the `hl7.fhir.uv.extensions` package automatically for IGs that target FHIR 5.0.0-draft-final or 5.0.0.  In the future, we'll update this to also support R4 once the R4 extensions package is ready. At that point, we'll also need to refine the loading strategy.


Patch:
diff --git a/src/utils/Processing.ts b/src/utils/Processing.ts
index 4237fe0..b7817a2 100644
--- a/src/utils/Processing.ts
+++ b/src/utils/Processing.ts
@@ -34,7 +34,13 @@ const CERTIFICATE_MESSAGE =
   '  2. Set NODE_EXTRA_CA_CERTS as described at https://bit.ly/3ghJqJZ (RECOMMENDED).\n' +
   '  3. Disable certificate validation as described at https://bit.ly/3syjzm7 (NOT RECOMMENDED).\n';
 
-export const AUTOMATIC_DEPENDENCIES: ImplementationGuideDependsOn[] = [
+type AutomaticDependency = {
+  packageId: string;
+  version: string;
+  fhirVersion?: RegExp;
+};
+
+export const AUTOMATIC_DEPENDENCIES: AutomaticDependency[] = [
   {
     packageId: 'hl7.fhir.uv.tools',
     version: 'current'
@@ -46,6 +52,11 @@ export const AUTOMATIC_DEPENDENCIES: ImplementationGuideDependsOn[] = [
     // See: https://chat.fhir.org/#narrow/stream/179239-tooling/topic/New.20Implicit.20Package/near/325488084
     packageId: 'hl7.terminology.r4',
     version: 'latest'
+  },
+  {
+    packageId: 'hl7.fhir.uv.extensions',
+    version: 'current',
+    fhirVersion: /^5\.0\.0(-draft-final)?$/
   }
 ];
 
@@ -214,18 +225,23 @@ export async function loadExternalDependencies(
   dependencies.push({ packageId: fhirPackageId, version: fhirVersion });
 
   // Load automatic dependencies first so they have lowest priority in resolution
-  await loadAutomaticDependencies(dependencies, defs);
+  await loadAutomaticDependencies(fhirVersion, dependencies, defs);
 
   // Then load configured dependencies, with FHIR core last so it has highest priority in resolution
   await loadConfiguredDependencies(dependencies, fhirVersion, config.filePath, defs);
 }
 
 export async function loadAutomaticDependencies(
+  fhirVersion: string,
   configuredDependencies: ImplementationGuideDependsOn[],
   defs: FHIRDefinitions
 ): Promise<void> {
   // Load dependencies serially so dependency loading order is predictable and repeatable
   for (let dep of AUTOMATIC_DEPENDENCIES) {
+    // Skip dependencies not intended for this version of FHIR
+    if (dep.fhirVersion && !dep.fhirVersion.test(fhirVersion)) {
+      continue;
+    }
     const alreadyConfigured = configuredDependencies.some(cd => {
       // hl7.some.package, hl7.some.package.r4, and hl7.some.package.r5 all represent the same content,
       // so they are essentially interchangeable and we should allow for any of them in the config.


Test patch:
diff --git a/test/testhelpers/asserts.ts b/test/testhelpers/asserts.ts
index afa7380..fddaf12 100644
--- a/test/testhelpers/asserts.ts
+++ b/test/testhelpers/asserts.ts
@@ -290,11 +290,11 @@ export function assertConceptRule(
   }
 }
 
-export function assertAutomaticDependencies(packages: string[], latestTerminology = '1.2.3-test') {
+export function assertAutomaticR4Dependencies(packages: string[]) {
   AUTOMATIC_DEPENDENCIES.forEach(dep => {
     if (dep.packageId === 'hl7.terminology.r4' && dep.version === 'latest') {
-      expect(packages).toContain(`hl7.terminology.r4#${latestTerminology}`);
-    } else {
+      expect(packages).toContain('hl7.terminology.r4#1.2.3-test');
+    } else if (dep.packageId !== 'hl7.fhir.uv.extensions') {
       expect(packages).toContain(`${dep.packageId}#${dep.version}`);
     }
   });
diff --git a/test/utils/Processing.test.ts b/test/utils/Processing.test.ts
index d2914e4..8b3fdc2 100644
--- a/test/utils/Processing.test.ts
+++ b/test/utils/Processing.test.ts
@@ -6,7 +6,7 @@ import path from 'path';
 import temp from 'temp';
 import { minimalConfig } from './minimalConfig';
 import { loggerSpy } from '../testhelpers/loggerSpy';
-import { assertAutomaticDependencies } from '../testhelpers/asserts';
+import { assertAutomaticR4Dependencies } from '../testhelpers/asserts';
 import readlineSync from 'readline-sync';
 import {
   AUTOMATIC_DEPENDENCIES,
@@ -48,6 +48,9 @@ import {
 } from '../../src/fshtypes';
 import { EOL } from 'os';
 
+const NUM_R4_AUTO_DEPENDENCIES = 2;
+const NUM_R5_AUTO_DEPENDENCIES = 3;
+
 const TERM_PKG_RESPONSE = {
   _id: 'hl7.terminology.r4',
   name: 'hl7.terminology.r4',
@@ -396,10 +399,10 @@ describe('Processing', () => {
       usCoreDependencyConfig.dependencies = [{ packageId: 'hl7.fhir.us.core', version: '3.1.0' }];
       const defs = new FHIRDefinitions();
       return loadExternalDependencies(defs, usCoreDependencyConfig).then(() => {
-        expect(defs.packages.length).toBe(2 + AUTOMATIC_DEPENDENCIES.length);
+        expect(defs.packages.length).toBe(2 + NUM_R4_AUTO_DEPENDENCIES);
         expect(defs.packages).toContain('hl7.fhir.r4.core#4.0.1');
         expect(defs.packages).toContain('hl7.fhir.us.core#3.1.0');
-        assertAutomaticDependencies(defs.packages);
+        assertAutomaticR4Dependencies(defs.packages);
         expect(loggerSpy.getAllLogs('warn')).toHaveLength(0);
       });
     });
@@ -409,7 +412,7 @@ describe('Processing', () => {
       usCoreDependencyConfig.dependencies = [{ packageId: 'hl7.fhir.us.core', version: '3.1.0' }];
       const defs = new FHIRDefinitions();
       return loadExternalDependencies(defs, usCoreDependencyConfig).then(() => {
-        expect(defs.packages.length).toBe(2 + AUTOMATIC_DEPENDENCIES.length);
+        expect(defs.packages.length).toBe(2 + NUM_R4_AUTO_DEPENDENCIES);
         expect(defs.packages).toEqual([
           'hl7.fhir.uv.tools#current',
           'hl7.terminology.r4#1.2.3-test',
@@ -429,7 +432,7 @@ describe('Processing', () => {
       ];
       const defs = new FHIRDefinitions();
       return loadExternalDependencies(defs, usCoreDependencyConfig).then(() => {
-        expect(defs.packages.length).toBe(2 + AUTOMATIC_DEPENDENCIES.length);
+        expect(defs.packages.length).toBe(2 + NUM_R4_AUTO_DEPENDENCIES);
         expect(defs.packages).toEqual([
           'hl7.fhir.us.core#3.1.0',
           'hl7.terminology.r4#8.8.8',
@@ -445,8 +448,10 @@ describe('Processing', () => {
       config.fhirVersion = ['4.1.0'];
       const defs = new FHIRDefinitions();
       return loadExternalDependencies(defs, config).then(() => {
+        expect(defs.packages.length).toBe(1 + NUM_R4_AUTO_DEPENDENCIES);
         expect(defs.packages).toContain('hl7.fhir.r4b.core#4.1.0');
         expect(defs.packages).toContain('hl7.fhir.uv.tools#current');
+        expect(defs.packages).toContain('hl7.terminology.r4#1.2.3-test');
         expect(loggerSpy.getLastMessage('warn')).toMatch(
           /support for pre-release versions of FHIR is experimental/s
         );
@@ -458,8 +463,10 @@ describe('Processing', () => {
       config.fhirVersion = ['4.3.0-snapshot1'];
       const defs = new FHIRDefinitions();
       return loadExternalDependencies(defs, config).then(() => {
+        expect(defs.packages.length).toBe(1 + NUM_R4_AUTO_DEPENDENCIES);
         expect(defs.packages).toContain('hl7.fhir.r4b.core#4.3.0-snapshot1');
         expect(defs.packages).toContain('hl7.fhir.uv.tools#current');
+        expect(defs.packages).toContain('hl7.terminology.r4#1.2.3-test');
         expect(loggerSpy.getLastMessage('warn')).toMatch(
           /support for pre-release versions of FHIR is experimental/s
         );
@@ -471,8 +478,10 @@ describe('Processing', () => {
       config.fhirVersion = ['4.3.0'];
       const defs = new FHIRDefinitions();
       return loadExternalDependencies(defs, config).then(() => {
+        expect(defs.packages.length).toBe(1 + NUM_R4_AUTO_DEPENDENCIES);
         expect(defs.packages).toContain('hl7.fhir.r4b.core#4.3.0');
         expect(defs.packages).toContain('hl7.fhir.uv.tools#current');
+        expect(defs.packages).toContain('hl7.terminology.r4#1.2.3-test');
         expect(loggerSpy.getAllLogs('warn')).toHaveLength(0);
       });
     });
@@ -482,8 +491,10 @@ describe('Processing', () => {
       config.fhirVersion = ['4.5.0'];
       const defs = new FHIRDefinitions();
       return loadExternalDependencies(defs, config).then(() => {
+        expect(defs.packages.length).toBe(1 + NUM_R4_AUTO_DEPENDENCIES);
         expect(defs.packages).toContain('hl7.fhir.r5.core#4.5.0');
         expect(defs.packages).toContain('hl7.fhir.uv.tools#current');
+        expect(defs.packages).toContain('hl7.terminology.r4#1.2.3-test');
         expect(loggerSpy.getLastMessage('warn')).toMatch(
           /support for pre-release versions of FHIR is experimental/s
         );
@@ -495,8 +506,10 @@ describe('Processing', () => {
       config.fhirVersion = ['5.0.0-snapshot1'];
       const defs = new FHIRDefinitions();
       return loadExternalDependencies(defs, config).then(() => {
+        expect(defs.packages.length).toBe(1 + NUM_R4_AUTO_DEPENDENCIES);
         expect(defs.packages).toContain('hl7.fhir.r5.core#5.0.0-snapshot1');
         expect(defs.packages).toContain('hl7.fhir.uv.tools#current');
+        expect(defs.packages).toContain('hl7.terminology.r4#1.2.3-test');
         expect(loggerSpy.getLastMessage('warn')).toMatch(
           /support for pre-release versions of FHIR is experimental/s
         );
@@ -508,8 +521,11 @@ describe('Processing', () => {
       config.fhirVersion = ['5.0.0'];
       const defs = new FHIRDefinitions();
       return loadExternalDependencies(defs, config).then(() => {
+        expect(defs.packages.length).toBe(1 + NUM_R5_AUTO_DEPENDENCIES);
         expect(defs.packages).toContain('hl7.fhir.r5.core#5.0.0');
         expect(defs.packages).toContain('hl7.fhir.uv.tools#current');
+        expect(defs.packages).toContain('hl7.terminology.r4#1.2.3-test');
+        expect(defs.packages).toContain('hl7.fhir.uv.extensions#current');
         expect(loggerSpy.getAllLogs('warn')).toHaveLength(0);
       });
     });
@@ -519,8 +535,10 @@ describe('Processing', () => {
       config.fhirVersion = ['current'];
       const defs = new FHIRDefinitions();
       return loadExternalDependencies(defs, config).then(() => {
+        expect(defs.packages.length).toBe(1 + NUM_R4_AUTO_DEPENDENCIES);
         expect(defs.packages).toContain('hl7.fhir.r5.core#current');
         expect(defs.packages).toContain('hl7.fhir.uv.tools#current');
+        expect(defs.packages).toContain('hl7.terminology.r4#1.2.3-test');
         expect(loggerSpy.getLastMessage('warn')).toMatch(
           /support for pre-release versions of FHIR is experimental/s
         );
@@ -541,9 +559,9 @@ describe('Processing', () => {
         virtualExtensionsConfig.dependencies = [{ packageId: extId, version: fhirVersion }];
         const defs = new FHIRDefinitions();
         return loadExternalDependencies(defs, virtualExtensionsConfig).then(() => {
-          expect(defs.packages.length).toBe(1 + AUTOMATIC_DEPENDENCIES.length);
+          expect(defs.packages.length).toBe(1 + NUM_R4_AUTO_DEPENDENCIES);
           expect(defs.packages).toContain(`${fhirId}#${fhirVersion}`);
-          assertAutomaticDependencies(defs.packages);
+          assertAutomaticR4Dependencies(defs.packages);
           expect(defs.supplementalFHIRPackages).toEqual([`${suppFhirId}#${suppFhirVersion}`]);
           expect(loggerSpy.getAllLogs('error')).toHaveLength(0);
         });
@@ -588,9 +606,9 @@ describe('Processing', () => {
       ];
       const defs = new FHIRDefinitions();
       return loadExternalDependencies(defs, virtualExtensionsConfig).then(() => {
-        expect(defs.packages.length).toBe(1 + AUTOMATIC_DEPENDENCIES.length);
+        expect(defs.packages.length).toBe(1 + NUM_R4_AUTO_DEPENDENCIES);
         expect(defs.packages).toContain('hl7.fhir.r4.core#4.0.1');
-        assertAutomaticDependencies(defs.packages);
+        assertAutomaticR4Dependencies(defs.packages);
         expect(defs.supplementalFHIRPackages).toEqual(['hl7.fhir.r2.core#1.0.2']);
         expect(loggerSpy.getLastMessage('warn')).toMatch(
           /Incorrect package version: hl7\.fhir\.extensions\.r2#1\.0\.2\./
@@ -604,9 +622,9 @@ describe('Processing', () => {
       badDependencyConfig.dependencies = [{ packageId: 'hl7.does.not.exist', version: 'current' }];
       const defs = new FHIRDefinitions();
       return loadExternalDependencies(defs, badDependencyConfig).then(() => {
-        expect(defs.packages.length).toBe(1 + AUTOMATIC_DEPENDENCIES.length);
+        expect(defs.packages.length).toBe(1 + NUM_R4_AUTO_DEPENDENCIES);
         expect(defs.packages).toContain('hl7.fhir.r4.core#4.0.1');
-        assertAutomaticDependencies(defs.packages);
+        assertAutomaticR4Dependencies(defs.packages);
         expect(loggerSpy.getLastMessage('error')).toMatch(
           /Failed to load hl7\.does\.not\.exist#current/s
         );
@@ -622,9 +640,9 @@ describe('Processing', () => {
       ];
       const defs = new FHIRDefinitions();
       return loadExternalDependencies(defs, selfSignedDependencyConfig).then(() => {
-        expect(defs.packages.length).toBe(1 + AUTOMATIC_DEPENDENCIES.length);
+        expect(defs.packages.length).toBe(1 + NUM_R4_AUTO_DEPENDENCIES);
         expect(defs.packages).toContain('hl7.fhir.r4.core#4.0.1');
-        assertAutomaticDependencies(defs.packages);
+        assertAutomaticR4Dependencies(defs.packages);
         expect(loggerSpy.getLastMessage('error')).toMatch(
           /Failed to load self-signed\.package#1\.0\.0/s
         );
@@ -640,9 +658,9 @@ describe('Processing', () => {
       badDependencyConfig.dependencies = [{ packageId: 'hl7.fhir.r4.core' }];
       const defs = new FHIRDefinitions();
       return loadExternalDependencies(defs, badDependencyConfig).then(() => {
-        expect(defs.packages.length).toBe(1 + AUTOMATIC_DEPENDENCIES.length);
+        expect(defs.packages.length).toBe(1 + NUM_R4_AUTO_DEPENDENCIES);
         expect(defs.packages).toContain('hl7.fhir.r4.core#4.0.1');
-        assertAutomaticDependencies(defs.packages);
+        assertAutomaticR4Dependencies(defs.packages);
         expect(loggerSpy.getLastMessage('error')).toMatch(
           /Failed to load hl7\.fhir\.r4\.core: No version specified\./s
         );
@@ -678,7 +696,7 @@ describe('Processing', () => {
       const config = cloneDeep(minimalConfig);
       config.dependencies = [{ packageId: 'hl7.fhir.us.core', version: '3.1.0' }];
       const defs = new FHIRDefinitions();
-      return loadAutomaticDependencies(config.dependencies, defs).then(() => {
+      return loadAutomaticDependencies('4.0.1', config.dependencies, defs).then(() => {
         expect(defs.packages).toHaveLength(2);
         expect(defs.packages).toContain('hl7.fhir.uv.tools#current');
         expect(defs.packages).toContain('hl7.terminology.r4#1.2.3-test');
@@ -687,6 +705,62 @@ describe('Processing', () => {
       });
     });
 
+    it('should load each automatic dependency for FHIR R4B', () => {
+      loadDependencySpy.mockImplementation(
+        async (packageName: string, version: string, FHIRDefs: FHIRDefinitions) => {
+          FHIRDefs.packages.push(`${packageName}#${version}`);
+          return Promise.resolve(FHIRDefs);
+        }
+      );
+      const config = cloneDeep(minimalConfig);
+      config.dependencies = [{ packageId: 'hl7.fhir.us.core', version: '3.1.0' }];
+      const defs = new FHIRDefinitions();
+      return loadAutomaticDependencies('4.3.0', config.dependencies, defs).then(() => {
+        expect(defs.packages).toHaveLength(2);
+        expect(defs.packages).toContain('hl7.fhir.uv.tools#current');
+        expect(defs.packages).toContain('hl7.terminology.r4#1.2.3-test');
+        expect(loggerSpy.getAllMessages('warn')).toHaveLength(0);
+      });
+    });
+
+    it('should load each automatic dependency for FHIR R5 Final Draft', () => {
+      loadDependencySpy.mockImplementation(
+        async (packageName: string, version: string, FHIRDefs: FHIRDefinitions) => {
+          FHIRDefs.packages.push(`${packageName}#${version}`);
+          return Promise.resolve(FHIRDefs);
+        }
+      );
+      const config = cloneDeep(minimalConfig);
+      config.dependencies = [{ packageId: 'hl7.fhir.us.core', version: '3.1.0' }];
+      const defs = new FHIRDefinitions();
+      return loadAutomaticDependencies('5.0.0-draft-final', config.dependencies, defs).then(() => {
+        expect(defs.packages).toHaveLength(3);
+        expect(defs.packages).toContain('hl7.fhir.uv.tools#current');
+        expect(defs.packages).toContain('hl7.terminology.r4#1.2.3-test');
+        expect(defs.packages).toContain('hl7.fhir.uv.extensions#current');
+        expect(loggerSpy.getAllMessages('warn')).toHaveLength(0);
+      });
+    });
+
+    it('should load each automatic dependency for FHIR R5', () => {
+      loadDependencySpy.mockImplementation(
+        async (packageName: string, version: string, FHIRDefs: FHIRDefinitions) => {
+          FHIRDefs.packages.push(`${packageName}#${version}`);
+          return Promise.resolve(FHIRDefs);
+        }
+      );
+      const config = cloneDeep(minimalConfig);
+      config.dependencies = [{ packageId: 'hl7.fhir.us.core', version: '3.1.0' }];
+      const defs = new FHIRDefinitions();
+      return loadAutomaticDependencies('5.0.0', config.dependencies, defs).then(() => {
+        expect(defs.packages).toHaveLength(3);
+        expect(defs.packages).toContain('hl7.fhir.uv.tools#current');
+        expect(defs.packages).toContain('hl7.terminology.r4#1.2.3-test');
+        expect(defs.packages).toContain('hl7.fhir.uv.extensions#current');
+        expect(loggerSpy.getAllMessages('warn')).toHaveLength(0);
+      });
+    });
+
     it('should should use the package server query to get the terminology version', () => {
       // Change the version to 2.4.6-test just to be sure
       nock.removeInterceptor(termNockScope);
@@ -703,12 +777,14 @@ describe('Processing', () => {
       const config = cloneDeep(minimalConfig);
       config.dependencies = [{ packageId: 'hl7.fhir.us.core', version: '3.1.0' }];
       const defs = new FHIRDefinitions();
-      return loadAutomaticDependencies(config.dependencies, defs).then(() => {
-        expect(defs.packages).toHaveLength(2);
-        expect(defs.packages).toContain('hl7.terminology.r4#2.4.6-test');
-        expect(loggerSpy.getAllMessages('warn')).toHaveLength(0);
-        expect(loadDependencySpy).toHaveBeenCalledTimes(2);
-      });
+      return loadAutomaticDependencies(config.fhirVersion[0], config.dependencies, defs).then(
+        () => {
+          expect(defs.packages).toHaveLength(2);
+          expect(defs.packages).toContain('hl7.terminology.r4#2.4.6-test');
+          expect(loggerSpy.getAllMessages('warn')).toHaveLength(0);
+          expect(loadDependencySpy).toHaveBeenCalledTimes(2);
+        }
+      );
     });
 
     it('should not load dependencies that are present in the config', () => {
@@ -721,12 +797,14 @@ describe('Processing', () => {
       const config = cloneDeep(minimalConfig);
       config.dependencies = [{ packageId: 'hl7.fhir.uv.tools', version: '2.2.0-test' }];
       const defs = new FHIRDefinitions();
-      return loadAutomaticDependencies(config.dependencies, defs).then(() => {
-        expect(defs.packages).toHaveLength(AUTOMATIC_DEPENDENCIES.length - 1);
-        expect(defs.packages).not.toContain('hl7.fhir.uv.tools#current');
-        expect(loggerSpy.getAllMessages('warn')).toHaveLength(0);
-        expect(loadDependencySpy).toHaveBeenCalledTimes(AUTOMATIC_DEPENDENCIES.length - 1);
-      });
+      return loadAutomaticDependencies(config.fhirVersion[0], config.dependencies, defs).then(
+        () => {
+          expect(defs.packages).toHaveLength(NUM_R4_AUTO_DEPENDENCIES - 1);
+          expect(defs.packages).not.toContain('hl7.fhir.uv.tools#current');
+          expect(loggerSpy.getAllMessages('warn')).toHaveLength(0);
+          expect(loadDependencySpy).toHaveBeenCalledTimes(NUM_R4_AUTO_DEPENDENCIES - 1);
+        }
+      );
     });
 
     it('should not load dependencies that are present in the config even if they have an r{x} suffix and the auto dependency does not', () => {
@@ -739,12 +817,14 @@ describe('Processing', () => {
       const config = cloneDeep(minimalConfig);
       config.dependencies = [{ packageId: 'hl7.fhir.uv.tools.r4', version: '4.0.0-test' }];
       const defs = new FHIRDefinitions();
-      return loadAutomaticDependencies(config.dependencies, defs).then(() => {
-        expect(defs.packages).toHaveLength(AUTOMATIC_DEPENDENCIES.length - 1);
-        expect(defs.packages).not.toContain('hl7.fhir.uv.tools#current');
-        expect(loggerSpy.getAllMessages('warn')).toHaveLength(0);
-        expect(loadDependencySpy).toHaveBeenCalledTimes(AUTOMATIC_DEPENDENCIES.length - 1);
-      });
+      return loadAutomaticDependencies(config.fhirVersion[0], config.dependencies, defs).then(
+        () => {
+          expect(defs.packages).toHaveLength(NUM_R4_AUTO_DEPENDENCIES - 1);
+          expect(defs.packages).not.toContain('hl7.fhir.uv.tools#current');
+          expect(loggerSpy.getAllMessages('warn')).toHaveLength(0);
+          expect(loadDependencySpy).toHaveBeenCalledTimes(NUM_R4_AUTO_DEPENDENCIES - 1);
+        }
+      );
     });
 
     it('should not load dependencies that are present in the config even if they do not have an r{x} suffix and the auto dependency does', () => {
@@ -757,13 +837,15 @@ describe('Processing', () => {
       const config = cloneDeep(minimalConfig);
       config.dependencies = [{ packageId: 'hl7.terminology', version: '4.0.0-test' }];
       const defs = new FHIRDefinitions();
-      return loadAutomaticDependencies(config.dependencies, defs).then(() => {
-        expect(defs.packages).toHaveLength(AUTOMATIC_DEPENDENCIES.length - 1);
-        expect(defs.packages).not.toContain('hl7.terminology.r4#1.2.3-test');
-        expect(defs.packages).not.toContain('hl7.terminology.r4#latest');
-        expect(loggerSpy.getAllMessages('warn')).toHaveLength(0);
-        expect(loadDependencySpy).toHaveBeenCalledTimes(AUTOMATIC_DEPENDENCIES.length - 1);
-      });
+      return loadAutomaticDependencies(config.fhirVersion[0], config.dependencies, defs).then(
+        () => {
+          expect(defs.packages).toHaveLength(NUM_R4_AUTO_DEPENDENCIES - 1);
+          expect(defs.packages).not.toContain('hl7.terminology.r4#1.2.3-test');
+          expect(defs.packages).not.toContain('hl7.terminology.r4#latest');
+          expect(loggerSpy.getAllMessages('warn')).toHaveLength(0);
+          expect(loadDependencySpy).toHaveBeenCalledTimes(NUM_R4_AUTO_DEPENDENCIES - 1);
+        }
+      );
     });
 
     it('should not load dependencies that are present in the config even if they do have an r{x} suffix that does not match the auto dependency r{x} suffix', () => {
@@ -776,13 +858,15 @@ describe('Processing', () => {
       const config = cloneDeep(minimalConfig);
       config.dependencies = [{ packageId: 'hl7.terminology.r5', version: '4.0.0-test' }];
       const defs = new FHIRDefinitions();
-      return loadAutomaticDependencies(config.dependencies, defs).then(() => {
-        expect(defs.packages).toHaveLength(AUTOMATIC_DEPENDENCIES.length - 1);
-        expect(defs.packages).not.toContain('hl7.terminology.r4#1.2.3-test');
-        expect(defs.packages).not.toContain('hl7.terminology.r4#latest');
-        expect(loggerSpy.getAllMessages('warn')).toHaveLength(0);
-        expect(loadDependencySpy).toHaveBeenCalledTimes(AUTOMATIC_DEPENDENCIES.length - 1);
-      });
+      return loadAutomaticDependencies(config.fhirVersion[0], config.dependencies, defs).then(
+        () => {
+          expect(defs.packages).toHaveLength(NUM_R4_AUTO_DEPENDENCIES - 1);
+          expect(defs.packages).not.toContain('hl7.terminology.r4#1.2.3-test');
+          expect(defs.packages).not.toContain('hl7.terminology.r4#latest');
+          expect(loggerSpy.getAllMessages('warn')).toHaveLength(0);
+          expect(loadDependencySpy).toHaveBeenCalledTimes(NUM_R4_AUTO_DEPENDENCIES - 1);
+        }
+      );
     });
 
     it('should log a warning when it fails to load an automatic dependency', () => {
@@ -799,17 +883,19 @@ describe('Processing', () => {
       const config = cloneDeep(minimalConfig);
       config.dependencies = [{ packageId: 'hl7.fhir.us.core', version: '3.1.0' }];
       const defs = new FHIRDefinitions();
-      return loadAutomaticDependencies(config.dependencies, defs).then(() => {
-        expect(defs.packages).toHaveLength(AUTOMATIC_DEPENDENCIES.length - 1);
-        expect(defs.packages).not.toContain('hl7.fhir.uv.tools#current');
-        expect(loggerSpy.getAllMessages('warn')).toHaveLength(1);
-        expect(loadDependencySpy).toHaveBeenCalledTimes(AUTOMATIC_DEPENDENCIES.length);
-        expect(loggerSpy.getLastMessage('warn')).toMatch(
-          /Failed to load automatically-provided hl7\.fhir\.uv\.tools#current/s
-        );
-        // But don't log the warning w/ details about proxies
-        expect(loggerSpy.getLastMessage('warn')).not.toMatch(/SSL/s);
-      });
+      return loadAutomaticDependencies(config.fhirVersion[0], config.dependencies, defs).then(
+        () => {
+          expect(defs.packages).toHaveLength(NUM_R4_AUTO_DEPENDENCIES - 1);
+          expect(defs.packages).not.toContain('hl7.fhir.uv.tools#current');
+          expect(loggerSpy.getAllMessages('warn')).toHaveLength(1);
+          expect(loadDependencySpy).toHaveBeenCalledTimes(NUM_R4_AUTO_DEPENDENCIES);
+          expect(loggerSpy.getLastMessage('warn')).toMatch(
+            /Failed to load automatically-provided hl7\.fhir\.uv\.tools#current/s
+          );
+          // But don't log the warning w/ details about proxies
+          expect(loggerSpy.getLastMessage('warn')).not.toMatch(/SSL/s);
+        }
+      );
     });
 
     it('should log a warning when it fails to find the latest version of an automatic dependency because of wrong JSON format', () => {
@@ -826,17 +912,19 @@ describe('Processing', () => {
       const config = cloneDeep(minimalConfig);
       config.dependencies = [{ packageId: 'hl7.fhir.us.core', version: '3.1.0' }];
       const defs = new FHIRDefinitions();
-      return loadAutomaticDependencies(config.dependencies, defs).then(() => {
-        expect(defs.packages).toHaveLength(AUTOMATIC_DEPENDENCIES.length - 1);
-        expect(defs.packages).not.toContain('hl7.terminology.r4#4.0.0');
-        expect(loggerSpy.getAllMessages('warn')).toHaveLength(1);
-        expect(loadDependencySpy).toHaveBeenCalledTimes(AUTOMATIC_DEPENDENCIES.length - 1);
-        expect(loggerSpy.getLastMessage('warn')).toMatch(
-          /Failed to load automatically-provided hl7\.terminology\.r4#latest/s
-        );
-        // But don't log the warning w/ details about proxies
-        expect(loggerSpy.getLastMessage('warn')).not.toMatch(/SSL/s);
-      });
+      return loadAutomaticDependencies(config.fhirVersion[0], config.dependencies, defs).then(
+        () => {
+          expect(defs.packages).toHaveLength(NUM_R4_AUTO_DEPENDENCIES - 1);
+          expect(defs.packages).not.toContain('hl7.terminology.r4#4.0.0');
+          expect(loggerSpy.getAllMessages('warn')).toHaveLength(1);
+          expect(loadDependencySpy).toHaveBeenCalledTimes(NUM_R4_AUTO_DEPENDENCIES - 1);
+          expect(loggerSpy.getLastMessage('warn')).toMatch(
+            /Failed to load automatically-provided hl7\.terminology\.r4#latest/s
+          );
+          // But don't log the warning w/ details about proxies
+          expect(loggerSpy.getLastMessage('warn')).not.toMatch(/SSL/s);
+        }
+      );
     });
 
     it('should log a warning when it fails to find the latest version of an automatic dependency because of HTTP error', () => {
@@ -853,17 +941,19 @@ describe('Processing', () => {
       const config = cloneDeep(minimalConfig);
       config.dependencies = [{ packageId: 'hl7.fhir.us.core', version: '3.1.0' }];
       const defs = new FHIRDefinitions();
-      return loadAutomaticDependencies(config.dependencies, defs).then(() => {
-        expect(defs.packages).toHaveLength(AUTOMATIC_DEPENDENCIES.length - 1);
-        expect(defs.packages).not.toContain('hl7.terminology.r4#4.0.0');
-        expect(loggerSpy.getAllMessages('warn')).toHaveLength(1);
-        expect(loadDependencySpy).toHaveBeenCalledTimes(AUTOMATIC_DEPENDENCIES.length - 1);
-        expect(loggerSpy.getLastMessage('warn')).toMatch(
-          /Failed to load automatically-provided hl7\.terminology\.r4#latest/s
-        );
-        // But don't log the warning w/ details about proxies
-        expect(loggerSpy.getLastMessage('warn')).not.toMatch(/SSL/s);
-      });
+      return loadAutomaticDependencies(config.fhirVersion[0], config.dependencies, defs).then(
+        () => {
+          expect(defs.packages).toHaveLength(NUM_R4_AUTO_DEPENDENCIES - 1);
+          expect(defs.packages).not.toContain('hl7.terminology.r4#4.0.0');
+          expect(loggerSpy.getAllMessages('warn')).toHaveLength(1);
+          expect(loadDependencySpy).toHaveBeenCalledTimes(NUM_R4_AUTO_DEPENDENCIES - 1);
+          expect(loggerSpy.getLastMessage('warn')).toMatch(
+            /Failed to load automatically-provided hl7\.terminology\.r4#latest/s
+          );
+          // But don't log the warning w/ details about proxies
+          expect(loggerSpy.getLastMessage('warn')).not.toMatch(/SSL/s);
+        }
+      );
     });
 
     it('should log a more detailed warning when it fails to load an automatic dependency due to certificate issue', () => {
@@ -880,19 +970,21 @@ describe('Processing', () => {
       const config = cloneDeep(minimalConfig);
       config.dependencies = [{ packageId: 'hl7.fhir.us.core', version: '3.1.0' }];
       const defs = new FHIRDefinitions();
-      return loadAutomaticDependencies(config.dependencies, defs).then(() => {
-        expect(defs.packages).toHaveLength(AUTOMATIC_DEPENDENCIES.length - 1);
-        expect(defs.packages).not.toContain('hl7.fhir.uv.tools#current');
-        expect(loggerSpy.getAllMessages('warn')).toHaveLength(1);
-        expect(loadDependencySpy).toHaveBeenCalledTimes(AUTOMATIC_DEPENDENCIES.length /*- 1 + 1*/);
-        expect(loggerSpy.getLastMessage('warn')).toMatch(
-          /Failed to load automatically-provided hl7\.fhir\.uv\.tools#current/s
-        );
-        // AND it should log the detailed message about SSL
-        expect(loggerSpy.getLastMessage('warn')).toMatch(
-          /Sometimes this error occurs in corporate or educational environments that use proxies and\/or SSL inspection/s
-        );
-      });
+      return loadAutomaticDependencies(config.fhirVersion[0], config.dependencies, defs).then(
+        () => {
+          expect(defs.packages).toHaveLength(NUM_R4_AUTO_DEPENDENCIES - 1);
+          expect(defs.packages).not.toContain('hl7.fhir.uv.tools#current');
+          expect(loggerSpy.getAllMessages('warn')).toHaveLength(1);
+          expect(loadDependencySpy).toHaveBeenCalledTimes(NUM_R4_AUTO_DEPENDENCIES /*- 1 + 1*/);
+          expect(loggerSpy.getLastMessage('warn')).toMatch(
+            /Failed to load automatically-provided hl7\.fhir\.uv\.tools#current/s
+          );
+          // AND it should log the detailed message about SSL
+          expect(loggerSpy.getLastMessage('warn')).toMatch(
+            /Sometimes this error occurs in corporate or educational environments that use proxies and\/or SSL inspection/s
+          );
+        }
+      );
     });
   });