From cd912c3f364cdd292374c52ddb991c72da7fb9f3 Mon Sep 17 00:00:00 2001 From: Robert A Dingwell Date: Fri, 31 Mar 2023 09:39:00 -0400 Subject: [PATCH 01/19] Upgrading to mongoose 7 and making slight adjustments based on that update to deal with failing tests --- env.json | 4 +-- package.json | 5 ++-- src/config.ts | 2 +- src/fhir/utilities.ts | 24 +++++++--------- src/lib/MongoDatabase.ts | 2 +- src/lib/__tests__/vsac_cache.test.ts | 43 ++++++++++++---------------- 6 files changed, 35 insertions(+), 45 deletions(-) diff --git a/env.json b/env.json index a9a3fd6e..b36b4dd9 100644 --- a/env.json +++ b/env.json @@ -1,7 +1,7 @@ { - "MONGO_HOSTNAME": { + "MONGO_URL": { "type": "string", - "default": "mongodb://rems-user:pass@127.0.0.1:27017", + "default": "mongodb://127.0.0.1:27017", "required": true }, "MONGO_DB_NAME": { diff --git a/package.json b/package.json index f1896fd5..ce527370 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "scripts": { "develop": "node dist/scripts/develop.js", "start": "ts-node-dev --inspect=8091 src/scripts/serve.ts", - "test": "jest --maxWorkers=4 --coverage --detectOpenHandles", + "test": "jest --runInBand --coverage --detectOpenHandles", "lint": "eslint \"**/*.{js,ts}\"", "lint:fix": "eslint \"**/*.{js,ts}\" --quiet --fix", "prettier": "prettier --check \"**/*.{js,ts}\"", @@ -54,7 +54,6 @@ "dependencies": { "@projecttacoma/node-fhir-server-core": "^2.2.8", "@types/fhir": "^0.0.35", - "@types/mongoose": "^5.11.97", "axios": "^1.2.1", "body-parser": "^1.19.0", "conventional-changelog-cli": "^2.0.34", @@ -65,7 +64,7 @@ "moment": "^2.24.0", "moment-timezone": "^0.5.40", "mongodb": "^4.12.1", - "mongoose": "^6.9.2", + "mongoose": "^7.0.3", "morgan": "^1.9.1", "tingodb": "^0.6.1", "uid": "^2.0.1", diff --git a/src/config.ts b/src/config.ts index 8fbdf8f0..270025d8 100644 --- a/src/config.ts +++ b/src/config.ts @@ -32,7 +32,7 @@ export default { options: '' }, mongoConfig: { - location: env.MONGO_HOSTNAME, + location: env.MONGO_URL, db_name: env.MONGO_DB_NAME, options: { //auto_reconnect: true, diff --git a/src/fhir/utilities.ts b/src/fhir/utilities.ts index 606e0201..62c1f333 100644 --- a/src/fhir/utilities.ts +++ b/src/fhir/utilities.ts @@ -64,20 +64,24 @@ export class FhirUtilities { id = resource.id; } console.log(' FhirUtilities::store: ' + resource.resourceType + ' -- ' + id); - - const fhirResource = new model(resource); + const fhirResource = new model(resource); // Create the resource's metadata const Meta = FhirUtilities.getMeta(baseVersion); fhirResource.meta = new Meta({ versionId: '1', lastUpdated: moment.utc().format('YYYY-MM-DDTHH:mm:ssZ') }); + + + model.exists({ id: fhirResource.id }).then(doesExist => { if (!doesExist) { try { resolve(fhirResource.save()); + ("resolve") } catch { reject(); + } } else { reject(); @@ -269,7 +273,7 @@ export class FhirUtilities { static async populateDB() { // prepopulateDB - medicationCollection.insertMany( + await medicationCollection.insertMany( [ { name: 'Turalio', @@ -376,14 +380,10 @@ export class FhirUtilities { } ] } - ], - (err: any, result: any) => { - if (err) console.log(err); - console.log('Inserted Drug Information'); - } + ] ); - metRequirementsCollection.insertMany( + await metRequirementsCollection.insertMany( [ { stakeholderId: 'Organization/pharm0111', @@ -417,11 +417,7 @@ export class FhirUtilities { completedQuestionnaire: null, case_numbers: [] } - ], - (err: any, result: any) => { - if (err) console.log(err); - console.log('Inserted Pharmacist Met Requirements'); - } + ] ); } } diff --git a/src/lib/MongoDatabase.ts b/src/lib/MongoDatabase.ts index 448f58c1..27661738 100644 --- a/src/lib/MongoDatabase.ts +++ b/src/lib/MongoDatabase.ts @@ -16,7 +16,7 @@ export class MongoDatabase extends Database { new Promise(resolve => { // Connect to mongo console.log('MongoDatabase connect: ' + this.location); - const dbString = `${this.location}/${this.db_name}`; + const dbString = `${this.location}${this.db_name}`; this.client = new mongoose.mongo.MongoClient(dbString); this.database = this.client.db(this.db_name); return resolve(mongoose.connect(dbString)); diff --git a/src/lib/__tests__/vsac_cache.test.ts b/src/lib/__tests__/vsac_cache.test.ts index 2d011ccc..be03b5cc 100644 --- a/src/lib/__tests__/vsac_cache.test.ts +++ b/src/lib/__tests__/vsac_cache.test.ts @@ -18,11 +18,11 @@ describe('VsacCache', () => { afterAll(async () => { await mongoose.connection.close(); }); + beforeEach(async () => { // client.clearCache(); const baseVersion = '4_0_0'; - const collectionString = `${constants.COLLECTION.VALUESET}_${baseVersion}`; - + await ValueSetModel.deleteMany({}); client.onlyVsac = false; jest.resetModules(); @@ -48,7 +48,7 @@ describe('VsacCache', () => { ); }); - test.skip('should be able to cache valuesets in Library Resources', async () => { + test('should be able to cache valuesets in Library Resources', async function() { const mockRequest = nock('http://cts.nlm.nih.gov/fhir'); mockRequest @@ -59,7 +59,7 @@ describe('VsacCache', () => { .reply(200, JSON.stringify(valueSet)); const valueSets = client.collectLibraryValuesets(library); - valueSets.forEach(async vs => { + valueSets.forEach(async function(vs) { expect(await client.isCached(vs)).toBeFalsy(); }); @@ -73,7 +73,7 @@ describe('VsacCache', () => { } }); - test.skip('should be able to cache valuesets in Questionnaire Resources', async () => { + test('should be able to cache valuesets in Questionnaire Resources', async () => { const mockRequest = nock('http://terminology.hl7.org/'); mockRequest.get('/ValueSet/yes-no-unknown-not-asked').reply(200, JSON.stringify(valueSet)); @@ -92,22 +92,20 @@ describe('VsacCache', () => { }); test.skip('should be not load valuesets already cached unless forced', async () => { - const mockRequest = nock('http://terminology.hl7.org/'); + const mockRequest = nock('http://terminology.hl7.org'); + const vs = 'http://terminology.hl7.org/ValueSet/yes-no-unknown-not-asked' + mockRequest.get('/ValueSet/yes-no-unknown-not-asked').reply(200, JSON.stringify(valueSet)); try { const valueSets = client.collectQuestionnaireValuesets(questionnaire); - valueSets.forEach(async vs => { - expect(await client.isCached(vs)).toBeFalsy(); - }); - - const cached = await client.cacheQuestionnaireItems(questionnaire); + expect(await client.isCached(vs)).toBeFalsy(); - valueSets.forEach(async vs => { - expect(await client.isCached(vs)).toBeTruthy(); - }); + const cached = await client.downloadAndCacheValueset(vs); + expect(await client.isCached(vs)).toBeTruthy(); - const vs = valueSets.values().next().value; + mockRequest.get('/ValueSet/yes-no-unknown-not-asked').reply(200, JSON.stringify(valueSet)); let update = await client.downloadAndCacheValueset(vs); + expect(update.get('cached')).toBeFalsy(); mockRequest.get('/ValueSet/yes-no-unknown-not-asked').reply(200, JSON.stringify(valueSet)); @@ -119,19 +117,16 @@ describe('VsacCache', () => { } }); - test.skip('should be able to handle errors downloading valuesests', async () => { + test('should be able to handle errors downloading valuesests', async () => { const mockRequest = nock('http://terminology.hl7.org/'); + const vs = 'http://terminology.hl7.org/ValueSet/yes-no-unknown-not-asked' mockRequest.get('/ValueSet/yes-no-unknown-not-asked').reply(404, ''); - - const valueSets = client.collectQuestionnaireValuesets(questionnaire); - valueSets.forEach(async vs => { - expect(await client.isCached(vs)).toBeFalsy(); - }); + expect(await client.isCached(vs)).toBeFalsy(); try { - const err = await client.downloadAndCacheValueset( - 'http://terminology.hl7.org/ValueSet/yes-no-unknown-not-asked' - ); + const err = await client.downloadAndCacheValueset(vs); + console.log(err); + expect(err.get('error')).toBeDefined(); } finally { mockRequest.done(); From 0bc9a86d6d01a74f6c2b3d9e7b9a2394e4c74e0b Mon Sep 17 00:00:00 2001 From: Robert A Dingwell Date: Fri, 31 Mar 2023 09:40:39 -0400 Subject: [PATCH 02/19] fixing issue with droping collection --- src/lib/vsac_cache.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/vsac_cache.ts b/src/lib/vsac_cache.ts index 3cbf3ce9..3f4defe9 100644 --- a/src/lib/vsac_cache.ts +++ b/src/lib/vsac_cache.ts @@ -237,7 +237,7 @@ class VsacCache { clearCache() { // drop the collection try { - ValueSetModel.collection.drop(console.log); + ValueSetModel.collection.drop(); } catch (e) { console.error(e); } From 293f7faecb267d49f884a168b0755c2bacbe2a97 Mon Sep 17 00:00:00 2001 From: Robert A Dingwell Date: Fri, 31 Mar 2023 09:44:29 -0400 Subject: [PATCH 03/19] linting and prettier fixes --- src/fhir/utilities.ts | 293 +++++++++++++-------------- src/lib/__tests__/vsac_cache.test.ts | 14 +- src/lib/vsac_cache.ts | 8 +- 3 files changed, 152 insertions(+), 163 deletions(-) diff --git a/src/fhir/utilities.ts b/src/fhir/utilities.ts index 62c1f333..16fea019 100644 --- a/src/fhir/utilities.ts +++ b/src/fhir/utilities.ts @@ -64,7 +64,7 @@ export class FhirUtilities { id = resource.id; } console.log(' FhirUtilities::store: ' + resource.resourceType + ' -- ' + id); - const fhirResource = new model(resource); + const fhirResource = new model(resource); // Create the resource's metadata const Meta = FhirUtilities.getMeta(baseVersion); fhirResource.meta = new Meta({ @@ -72,16 +72,13 @@ export class FhirUtilities { lastUpdated: moment.utc().format('YYYY-MM-DDTHH:mm:ssZ') }); - - model.exists({ id: fhirResource.id }).then(doesExist => { if (!doesExist) { try { resolve(fhirResource.save()); - ("resolve") + ('resolve'); } catch { reject(); - } } else { reject(); @@ -273,151 +270,147 @@ export class FhirUtilities { static async populateDB() { // prepopulateDB - await medicationCollection.insertMany( - [ - { - name: 'Turalio', - codeSystem: 'http://www.nlm.nih.gov/research/umls/rxnorm', - code: '2183126', - requirements: [ - { - name: 'Patient Enrollment', - description: 'Submit Patient Enrollment form to the REMS Administrator', - stakeholderType: 'patient', - createNewCase: true, - resourceId: 'TuralioRemsPatientEnrollment' - }, - { - name: 'Prescriber Enrollment', - description: 'Submit Prescriber Enrollment form to the REMS Administrator', - stakeholderType: 'prescriber', - createNewCase: false, - resourceId: 'TuralioPrescriberEnrollmentForm' - }, - { - name: 'Prescriber Knowledge Assessment', - description: 'Submit Prescriber Knowledge Assessment form to the REMS Administrator', - stakeholderType: 'prescriber', - createNewCase: false, - resourceId: 'TuralioPrescriberKnowledgeAssessment' - }, - { - name: 'Pharmacist Enrollment', - description: 'Submit Pharmacist Enrollment form to the REMS Administrator', - stakeholderType: 'pharmacist', - createNewCase: false, - resourceId: 'TuralioPharmacistEnrollment' - } - ] - }, - { - name: 'TIRF', - codeSystem: 'http://www.nlm.nih.gov/research/umls/rxnorm', - code: '1237051', - requirements: [ - { - name: 'Patient Enrollment', - description: 'Submit Patient Enrollment form to the REMS Administrator', - stakeholderType: 'patient', - createNewCase: true, - resourceId: 'TIRFRemsPatientEnrollment' - }, - { - name: 'Prescriber Enrollment', - description: 'Submit Prescriber Enrollment form to the REMS Administrator', - stakeholderType: 'prescriber', - createNewCase: false, - resourceId: 'TIRFPrescriberEnrollmentForm' - }, - { - name: 'Prescriber Knowledge Assessment', - description: 'Submit Prescriber Knowledge Assessment form to the REMS Administrator', - stakeholderType: 'prescriber', - createNewCase: false, - resourceId: 'TIRFPrescriberKnowledgeAssessment' - }, - { - name: 'Pharmacist Enrollment', - description: 'Submit Pharmacist Enrollment form to the REMS Administrator', - stakeholderType: 'pharmacist', - createNewCase: false, - resourceId: 'TIRFPharmacistEnrollmentForm' - }, - { - name: 'Pharmacist Knowledge Assessment', - description: 'Submit Pharmacist Knowledge Assessment form to the REMS Administrator', - stakeholderType: 'pharmacist', - createNewCase: false, - resourceId: 'TIRFPharmacistKnowledgeAssessment' - } - ] - }, - { - name: 'Isotretinoin', - codeSystem: 'http://www.nlm.nih.gov/research/umls/rxnorm', - code: '6064', - requirements: [ - { - name: 'Patient Enrollment', - description: 'Submit Patient Enrollment form to the REMS Administrator', - stakeholderType: 'patient', - createNewCase: true, - resourceId: 'IPledgeRemsPatientEnrollment' - }, - { - name: 'Prescriber Enrollment', - description: 'Submit Prescriber Enrollment form to the REMS Administrator', - stakeholderType: 'prescriber', - createNewCase: false, - resourceId: 'IPledgeRemsPrescriberEnrollmentForm' - }, - { - name: 'Pharmacist Enrollment', - description: 'Submit Pharmacist Enrollment form to the REMS Administrator', - stakeholderType: 'pharmacist', - createNewCase: false, - resourceId: 'IPledgeRemsPharmacistEnrollmentForm' - } - ] - } - ] - ); + await medicationCollection.insertMany([ + { + name: 'Turalio', + codeSystem: 'http://www.nlm.nih.gov/research/umls/rxnorm', + code: '2183126', + requirements: [ + { + name: 'Patient Enrollment', + description: 'Submit Patient Enrollment form to the REMS Administrator', + stakeholderType: 'patient', + createNewCase: true, + resourceId: 'TuralioRemsPatientEnrollment' + }, + { + name: 'Prescriber Enrollment', + description: 'Submit Prescriber Enrollment form to the REMS Administrator', + stakeholderType: 'prescriber', + createNewCase: false, + resourceId: 'TuralioPrescriberEnrollmentForm' + }, + { + name: 'Prescriber Knowledge Assessment', + description: 'Submit Prescriber Knowledge Assessment form to the REMS Administrator', + stakeholderType: 'prescriber', + createNewCase: false, + resourceId: 'TuralioPrescriberKnowledgeAssessment' + }, + { + name: 'Pharmacist Enrollment', + description: 'Submit Pharmacist Enrollment form to the REMS Administrator', + stakeholderType: 'pharmacist', + createNewCase: false, + resourceId: 'TuralioPharmacistEnrollment' + } + ] + }, + { + name: 'TIRF', + codeSystem: 'http://www.nlm.nih.gov/research/umls/rxnorm', + code: '1237051', + requirements: [ + { + name: 'Patient Enrollment', + description: 'Submit Patient Enrollment form to the REMS Administrator', + stakeholderType: 'patient', + createNewCase: true, + resourceId: 'TIRFRemsPatientEnrollment' + }, + { + name: 'Prescriber Enrollment', + description: 'Submit Prescriber Enrollment form to the REMS Administrator', + stakeholderType: 'prescriber', + createNewCase: false, + resourceId: 'TIRFPrescriberEnrollmentForm' + }, + { + name: 'Prescriber Knowledge Assessment', + description: 'Submit Prescriber Knowledge Assessment form to the REMS Administrator', + stakeholderType: 'prescriber', + createNewCase: false, + resourceId: 'TIRFPrescriberKnowledgeAssessment' + }, + { + name: 'Pharmacist Enrollment', + description: 'Submit Pharmacist Enrollment form to the REMS Administrator', + stakeholderType: 'pharmacist', + createNewCase: false, + resourceId: 'TIRFPharmacistEnrollmentForm' + }, + { + name: 'Pharmacist Knowledge Assessment', + description: 'Submit Pharmacist Knowledge Assessment form to the REMS Administrator', + stakeholderType: 'pharmacist', + createNewCase: false, + resourceId: 'TIRFPharmacistKnowledgeAssessment' + } + ] + }, + { + name: 'Isotretinoin', + codeSystem: 'http://www.nlm.nih.gov/research/umls/rxnorm', + code: '6064', + requirements: [ + { + name: 'Patient Enrollment', + description: 'Submit Patient Enrollment form to the REMS Administrator', + stakeholderType: 'patient', + createNewCase: true, + resourceId: 'IPledgeRemsPatientEnrollment' + }, + { + name: 'Prescriber Enrollment', + description: 'Submit Prescriber Enrollment form to the REMS Administrator', + stakeholderType: 'prescriber', + createNewCase: false, + resourceId: 'IPledgeRemsPrescriberEnrollmentForm' + }, + { + name: 'Pharmacist Enrollment', + description: 'Submit Pharmacist Enrollment form to the REMS Administrator', + stakeholderType: 'pharmacist', + createNewCase: false, + resourceId: 'IPledgeRemsPharmacistEnrollmentForm' + } + ] + } + ]); - await metRequirementsCollection.insertMany( - [ - { - stakeholderId: 'Organization/pharm0111', - completed: true, - requirementName: 'Pharmacist Enrollment', - drugName: 'Turalio', - completedQuestionnaire: null, - case_numbers: [] - }, - { - stakeholderId: 'Organization/pharm0111', - completed: true, - requirementName: 'Pharmacist Enrollment', - drugName: 'TIRF', - completedQuestionnaire: null, - case_numbers: [] - }, - { - stakeholderId: 'Organization/pharm0111', - completed: true, - requirementName: 'Pharmacist Knowledge Assessment', - drugName: 'TIRF', - completedQuestionnaire: null, - case_numbers: [] - }, - { - stakeholderId: 'Organization/pharm0111', - completed: true, - requirementName: 'Pharmacist Enrollment', - drugName: 'Isotretinoin', - completedQuestionnaire: null, - case_numbers: [] - } - ] - ); + await metRequirementsCollection.insertMany([ + { + stakeholderId: 'Organization/pharm0111', + completed: true, + requirementName: 'Pharmacist Enrollment', + drugName: 'Turalio', + completedQuestionnaire: null, + case_numbers: [] + }, + { + stakeholderId: 'Organization/pharm0111', + completed: true, + requirementName: 'Pharmacist Enrollment', + drugName: 'TIRF', + completedQuestionnaire: null, + case_numbers: [] + }, + { + stakeholderId: 'Organization/pharm0111', + completed: true, + requirementName: 'Pharmacist Knowledge Assessment', + drugName: 'TIRF', + completedQuestionnaire: null, + case_numbers: [] + }, + { + stakeholderId: 'Organization/pharm0111', + completed: true, + requirementName: 'Pharmacist Enrollment', + drugName: 'Isotretinoin', + completedQuestionnaire: null, + case_numbers: [] + } + ]); } } diff --git a/src/lib/__tests__/vsac_cache.test.ts b/src/lib/__tests__/vsac_cache.test.ts index be03b5cc..7a139c91 100644 --- a/src/lib/__tests__/vsac_cache.test.ts +++ b/src/lib/__tests__/vsac_cache.test.ts @@ -22,7 +22,7 @@ describe('VsacCache', () => { beforeEach(async () => { // client.clearCache(); const baseVersion = '4_0_0'; - + await ValueSetModel.deleteMany({}); client.onlyVsac = false; jest.resetModules(); @@ -48,7 +48,7 @@ describe('VsacCache', () => { ); }); - test('should be able to cache valuesets in Library Resources', async function() { + test('should be able to cache valuesets in Library Resources', async function () { const mockRequest = nock('http://cts.nlm.nih.gov/fhir'); mockRequest @@ -59,7 +59,7 @@ describe('VsacCache', () => { .reply(200, JSON.stringify(valueSet)); const valueSets = client.collectLibraryValuesets(library); - valueSets.forEach(async function(vs) { + valueSets.forEach(async function (vs) { expect(await client.isCached(vs)).toBeFalsy(); }); @@ -93,7 +93,7 @@ describe('VsacCache', () => { test.skip('should be not load valuesets already cached unless forced', async () => { const mockRequest = nock('http://terminology.hl7.org'); - const vs = 'http://terminology.hl7.org/ValueSet/yes-no-unknown-not-asked' + const vs = 'http://terminology.hl7.org/ValueSet/yes-no-unknown-not-asked'; mockRequest.get('/ValueSet/yes-no-unknown-not-asked').reply(200, JSON.stringify(valueSet)); try { @@ -105,7 +105,7 @@ describe('VsacCache', () => { mockRequest.get('/ValueSet/yes-no-unknown-not-asked').reply(200, JSON.stringify(valueSet)); let update = await client.downloadAndCacheValueset(vs); - + expect(update.get('cached')).toBeFalsy(); mockRequest.get('/ValueSet/yes-no-unknown-not-asked').reply(200, JSON.stringify(valueSet)); @@ -119,14 +119,14 @@ describe('VsacCache', () => { test('should be able to handle errors downloading valuesests', async () => { const mockRequest = nock('http://terminology.hl7.org/'); - const vs = 'http://terminology.hl7.org/ValueSet/yes-no-unknown-not-asked' + const vs = 'http://terminology.hl7.org/ValueSet/yes-no-unknown-not-asked'; mockRequest.get('/ValueSet/yes-no-unknown-not-asked').reply(404, ''); expect(await client.isCached(vs)).toBeFalsy(); try { const err = await client.downloadAndCacheValueset(vs); console.log(err); - + expect(err.get('error')).toBeDefined(); } finally { mockRequest.done(); diff --git a/src/lib/vsac_cache.ts b/src/lib/vsac_cache.ts index 3f4defe9..98139014 100644 --- a/src/lib/vsac_cache.ts +++ b/src/lib/vsac_cache.ts @@ -1,10 +1,6 @@ import axios from 'axios'; import fhirpath from 'fhirpath'; -import fs from 'fs'; -import { stringify } from 'querystring'; import { FhirUtilities } from '../fhir/utilities'; -import { Globals } from '../globals'; -import constants from '../constants'; import ValueSetModel from './schemas/resources/ValueSet'; import { ValueSet } from 'fhir/r4'; class VsacCache { @@ -36,7 +32,7 @@ class VsacCache { */ async cacheLibrary(library: any, forceReload = false) { const valueSets = this.collectLibraryValuesets(library); - return await this.cacheValuesets(valueSets); + return await this.cacheValuesets(valueSets,forceReload); } /** @@ -48,7 +44,7 @@ class VsacCache { async cacheQuestionnaireItems(obj: any, forceReload = false) { const valueSets = this.collectQuestionnaireValuesets(obj); - return await this.cacheValuesets(valueSets); + return await this.cacheValuesets(valueSets,forceReload); } /** From f1ce72071ed6567d7351ec900c32658cf4f9d915 Mon Sep 17 00:00:00 2001 From: Robert A Dingwell Date: Fri, 31 Mar 2023 10:07:45 -0400 Subject: [PATCH 04/19] fixing prettier errors after linting --- src/lib/vsac_cache.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/vsac_cache.ts b/src/lib/vsac_cache.ts index 98139014..8b0b88e2 100644 --- a/src/lib/vsac_cache.ts +++ b/src/lib/vsac_cache.ts @@ -32,7 +32,7 @@ class VsacCache { */ async cacheLibrary(library: any, forceReload = false) { const valueSets = this.collectLibraryValuesets(library); - return await this.cacheValuesets(valueSets,forceReload); + return await this.cacheValuesets(valueSets, forceReload); } /** @@ -44,7 +44,7 @@ class VsacCache { async cacheQuestionnaireItems(obj: any, forceReload = false) { const valueSets = this.collectQuestionnaireValuesets(obj); - return await this.cacheValuesets(valueSets,forceReload); + return await this.cacheValuesets(valueSets, forceReload); } /** From 00a5d82786ea42d67659f405de1562c4cd949ded Mon Sep 17 00:00:00 2001 From: Robert A Dingwell Date: Fri, 31 Mar 2023 10:09:30 -0400 Subject: [PATCH 05/19] removing node 16 tests --- .github/workflows/ci-workflow.yml | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/.github/workflows/ci-workflow.yml b/.github/workflows/ci-workflow.yml index 27900387..6429e351 100644 --- a/.github/workflows/ci-workflow.yml +++ b/.github/workflows/ci-workflow.yml @@ -33,22 +33,4 @@ jobs: - run: npm install - run: npm test env: - CI: true - test_mac_os: - name: Test on node ${{ matrix.node-version }} and ${{ matrix.os }} - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [macos-latest] - node-version: [16] - - steps: - - uses: actions/checkout@v1 - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 - with: - node-version: ${{ matrix.node-version }} - - run: npm install - - run: npm test - env: - CI: true + CI: true \ No newline at end of file From 7e9dedfbf2c4309e05755e949b9e9c04a1a23361 Mon Sep 17 00:00:00 2001 From: Robert A Dingwell Date: Fri, 31 Mar 2023 10:29:17 -0400 Subject: [PATCH 06/19] removing log statements --- src/lib/__tests__/vsac_cache.test.ts | 7 +++++-- src/lib/vsac_cache.ts | 4 +--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/lib/__tests__/vsac_cache.test.ts b/src/lib/__tests__/vsac_cache.test.ts index 7a139c91..1bcfc1cc 100644 --- a/src/lib/__tests__/vsac_cache.test.ts +++ b/src/lib/__tests__/vsac_cache.test.ts @@ -122,12 +122,15 @@ describe('VsacCache', () => { const vs = 'http://terminology.hl7.org/ValueSet/yes-no-unknown-not-asked'; mockRequest.get('/ValueSet/yes-no-unknown-not-asked').reply(404, ''); expect(await client.isCached(vs)).toBeFalsy(); - + let err; try { - const err = await client.downloadAndCacheValueset(vs); + err = await client.downloadAndCacheValueset(vs); console.log(err); expect(err.get('error')).toBeDefined(); + } catch (e) { + console.log('Expected Error to be defined', err); + throw e; } finally { mockRequest.done(); } diff --git a/src/lib/vsac_cache.ts b/src/lib/vsac_cache.ts index 8b0b88e2..e54b4ee3 100644 --- a/src/lib/vsac_cache.ts +++ b/src/lib/vsac_cache.ts @@ -103,8 +103,7 @@ class VsacCache { if (forceReload || !(await this.isCached(idOrUrl))) { const vs = await this.downloadValueset(idOrUrl); if (vs.get('error')) { - console.log('Error Downloading ', idOrUrl); - console.log(vs.get('error').message); + console.log('Error Downloading ', idOrUrl, vs.get('error')); } else if (vs.get('valueSet')) { await this.storeValueSet(this.getValuesetId(idOrUrl), vs.get('valueSet')); vs.set('cached', true); @@ -145,7 +144,6 @@ class VsacCache { }); if ((this.onlyVsac && isVsac) || !this.onlyVsac) { try { - console.log('Downloading vs ' + url); const vs = await axios.get(url, { headers: headers }); From c2113db13461f52e75e49ab5aaf3994e3a273dc3 Mon Sep 17 00:00:00 2001 From: Robert A Dingwell Date: Fri, 31 Mar 2023 10:39:57 -0400 Subject: [PATCH 07/19] Attempting to update ci test to node 18 to see if that has effect on outcomes --- .github/workflows/ci-workflow.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-workflow.yml b/.github/workflows/ci-workflow.yml index 6429e351..cb680df3 100644 --- a/.github/workflows/ci-workflow.yml +++ b/.github/workflows/ci-workflow.yml @@ -22,7 +22,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] - node-version: [14] + node-version: [18] steps: - uses: actions/checkout@v1 From c977e23734610ee08042a39ce3aefb644d33ca06 Mon Sep 17 00:00:00 2001 From: Robert A Dingwell Date: Fri, 31 Mar 2023 11:06:56 -0400 Subject: [PATCH 08/19] aligning jest package versions --- package.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index ce527370..915d4801 100644 --- a/package.json +++ b/package.json @@ -76,8 +76,9 @@ "devDependencies": { "@shelf/jest-mongodb": "^4.1.6", "@types/cors": "^2.8.12", + "@types/mongoose": "^5.11.97", "@types/express": "^4.17.14", - "@types/jest": "^27.5.2", + "@types/jest": "^27.5.1", "@types/lodash": "^4.14.188", "@types/morgan": "^1.9.3", "@types/node": "^18.11.9", @@ -88,7 +89,9 @@ "axios-mock-adapter": "^1.21.2", "eslint": "^8.28.0", "eslint-config-prettier": "^6.10.1", - "jest": "^27.4.5", + "jest": "^27.5.1", + "jest-environment-node":"^27.5.1", + "jest-config": "^27.5.1", "jest-extended": "^1.2.0", "json-diff": "^0.9.0", "nock": "^13.2.9", From eca269267a381332fe0311e7778880128b968124 Mon Sep 17 00:00:00 2001 From: Robert A Dingwell Date: Fri, 31 Mar 2023 11:16:41 -0400 Subject: [PATCH 09/19] removing logging statements --- src/lib/__tests__/vsac_cache.test.ts | 2 +- src/lib/vsac_cache.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/__tests__/vsac_cache.test.ts b/src/lib/__tests__/vsac_cache.test.ts index 1bcfc1cc..ebb73610 100644 --- a/src/lib/__tests__/vsac_cache.test.ts +++ b/src/lib/__tests__/vsac_cache.test.ts @@ -125,7 +125,7 @@ describe('VsacCache', () => { let err; try { err = await client.downloadAndCacheValueset(vs); - console.log(err); + // console.log(err); expect(err.get('error')).toBeDefined(); } catch (e) { diff --git a/src/lib/vsac_cache.ts b/src/lib/vsac_cache.ts index e54b4ee3..12eeaead 100644 --- a/src/lib/vsac_cache.ts +++ b/src/lib/vsac_cache.ts @@ -103,7 +103,7 @@ class VsacCache { if (forceReload || !(await this.isCached(idOrUrl))) { const vs = await this.downloadValueset(idOrUrl); if (vs.get('error')) { - console.log('Error Downloading ', idOrUrl, vs.get('error')); + console.log('Error Downloading ', idOrUrl, typeof vs.get('error')); } else if (vs.get('valueSet')) { await this.storeValueSet(this.getValuesetId(idOrUrl), vs.get('valueSet')); vs.set('cached', true); From 98a421a2daf690254c6b19a7adb93fea3d29602b Mon Sep 17 00:00:00 2001 From: Robert A Dingwell Date: Fri, 31 Mar 2023 11:18:32 -0400 Subject: [PATCH 10/19] Prettier fixes --- src/lib/__tests__/vsac_cache.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/__tests__/vsac_cache.test.ts b/src/lib/__tests__/vsac_cache.test.ts index ebb73610..241884c0 100644 --- a/src/lib/__tests__/vsac_cache.test.ts +++ b/src/lib/__tests__/vsac_cache.test.ts @@ -125,7 +125,7 @@ describe('VsacCache', () => { let err; try { err = await client.downloadAndCacheValueset(vs); - // console.log(err); + // console.log(err); expect(err.get('error')).toBeDefined(); } catch (e) { From f346b0901712565956ad069cdfbd45c258cbc3ff Mon Sep 17 00:00:00 2001 From: Robert A Dingwell Date: Mon, 3 Apr 2023 13:50:52 -0400 Subject: [PATCH 11/19] Migrating tests to mocha and sinon to deal with github CI runner issues --- package.json | 44 ++-------- src/hooks/rems.hook.test.ts | 11 +-- src/lib/__tests__/vsac_cache.test.ts | 64 ++++++++------ src/lib/vsac_cache.ts | 4 +- src/lib/winston.test.ts | 33 +++---- src/server.test.ts | 126 +++++++++++++++------------ 6 files changed, 140 insertions(+), 142 deletions(-) diff --git a/package.json b/package.json index 915d4801..47ca37cf 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "scripts": { "develop": "node dist/scripts/develop.js", "start": "ts-node-dev --inspect=8091 src/scripts/serve.ts", - "test": "jest --runInBand --coverage --detectOpenHandles", + "test": "mocha -r ts-node/register src/*.test.ts src/**/*.test.ts src/**/**/*.test.ts", "lint": "eslint \"**/*.{js,ts}\"", "lint:fix": "eslint \"**/*.{js,ts}\" --quiet --fix", "prettier": "prettier --check \"**/*.{js,ts}\"", @@ -24,33 +24,6 @@ "type": "git", "url": "git+ssh://git@bitbucket.org/asymmetrik/carejourney-cds.git" }, - "jest": { - "moduleNameMapper": { - "axios": "axios/dist/node/axios.cjs" - }, - "preset": "@shelf/jest-mongodb", - "testEnvironment": "node", - "transform": { - "^.+\\.ts?$": "ts-jest" - }, - "transformIgnorePatterns": [ - "/node_modules/" - ], - "testPathIgnorePatterns": [ - "/src/config/env/test.js" - ], - "verbose": true, - "collectCoverage": true, - "coverageReporters": [ - "text", - "lcov", - "json" - ], - "coveragePathIgnorePatterns": [ - "/node_modules", - "/src/profiles" - ] - }, "dependencies": { "@projecttacoma/node-fhir-server-core": "^2.2.8", "@types/fhir": "^0.0.35", @@ -74,29 +47,30 @@ "winston-daily-rotate-file": "^4.2.1" }, "devDependencies": { - "@shelf/jest-mongodb": "^4.1.6", + "@types/chai": "^4.3.4", "@types/cors": "^2.8.12", - "@types/mongoose": "^5.11.97", "@types/express": "^4.17.14", - "@types/jest": "^27.5.1", "@types/lodash": "^4.14.188", + "@types/mocha": "^10.0.1", + "@types/mongoose": "^5.11.97", "@types/morgan": "^1.9.3", "@types/node": "^18.11.9", "@types/nodemon": "^1.19.2", + "@types/sinon" : "10.0.13", "@types/uuid": "^9.0.0", "@typescript-eslint/eslint-plugin": "^5.45.0", "@typescript-eslint/parser": "^5.45.0", "axios-mock-adapter": "^1.21.2", + "chai": "^4.3.7", "eslint": "^8.28.0", "eslint-config-prettier": "^6.10.1", - "jest": "^27.5.1", - "jest-environment-node":"^27.5.1", - "jest-config": "^27.5.1", - "jest-extended": "^1.2.0", "json-diff": "^0.9.0", + "mocha": "^10.2.0", + "mongodb-memory-server": "^8.12.1", "nock": "^13.2.9", "nodemon": "^2.0.20", "prettier": "^2.0.5", + "sinon": "^15.0.3", "ts-jest": "^27.1.2", "ts-node": "^10.9.1", "ts-node-dev": "^2.0.0", diff --git a/src/hooks/rems.hook.test.ts b/src/hooks/rems.hook.test.ts index 488f41be..4e96e339 100644 --- a/src/hooks/rems.hook.test.ts +++ b/src/hooks/rems.hook.test.ts @@ -1,8 +1,9 @@ import OrderSign from './OrderSign'; import getREMSHook from './rems.hook'; +import {expect} from 'chai'; describe('hook: test rems', () => { - test('should have definition and handler', () => { + it('should have definition and handler', () => { const prefetch = { patient: 'Patient/{{context.patientId}}', practitioner: 'Practitioner/{{context.userId}}' @@ -15,10 +16,10 @@ describe('hook: test rems', () => { prefetch ); - expect(getREMSHook).toHaveProperty('definition'); - expect(getREMSHook).toHaveProperty('handler'); + expect(getREMSHook).to.haveOwnProperty('definition'); + expect(getREMSHook).to.haveOwnProperty('handler'); - expect(getREMSHook.definition).toStrictEqual(expectedDefinition); - expect(getREMSHook.handler).toBeInstanceOf(Function); + expect(getREMSHook.definition).to.deep.equal(expectedDefinition); + expect(getREMSHook.handler).to.instanceOf(Function); }); }); diff --git a/src/lib/__tests__/vsac_cache.test.ts b/src/lib/__tests__/vsac_cache.test.ts index 241884c0..9d116f81 100644 --- a/src/lib/__tests__/vsac_cache.test.ts +++ b/src/lib/__tests__/vsac_cache.test.ts @@ -5,18 +5,29 @@ import valueSet from './fixtures/valueSet.json'; import nock from 'nock'; import constants from '../../constants'; import ValueSetModel from '../schemas/resources/ValueSet'; -import mongoose from 'mongoose'; +import mongoose, { ConnectOptions } from 'mongoose'; +const { MongoMemoryServer } = require("mongodb-memory-server"); +import { assert, expect } from "chai" describe('VsacCache', () => { const client = new VsacCache('./tmp', '2c1d55c3-3484-4902-b645-25f3a4974ce6'); - - beforeAll(async () => { - if (process.env.MONGO_URL) { - await mongoose.connect(process.env.MONGO_URL); + let mongo: typeof MongoMemoryServer; + before(async () => { + + mongo = await MongoMemoryServer.create(); + const uri = mongo.getUri(); + let options :ConnectOptions = { + } + await mongoose.connect(uri, options); }); - afterAll(async () => { + after(async () => { + console.log("Closing connection?"); + + await mongoose.connection.dropDatabase(); await mongoose.connection.close(); + await mongo.stop(); + }); beforeEach(async () => { @@ -25,15 +36,14 @@ describe('VsacCache', () => { await ValueSetModel.deleteMany({}); client.onlyVsac = false; - jest.resetModules(); }); // need to mock the server endpoints to we do not require hitting // the server for CI testing with someones api credentials - test('should be able to collect valueset references from Library Resources', async () => { + it('should be able to collect valueset references from Library Resources', async () => { const valueSets = client.collectLibraryValuesets(library); - expect(valueSets).toEqual( + expect(valueSets).to.deep.equal( new Set([ 'http://cts.nlm.nih.gov/fhir/ValueSet/2.16.840.1.113762.1.4.1219.85', 'http://cts.nlm.nih.gov/fhir/ValueSet/2.16.840.1.113762.1.4.1219.35' @@ -41,14 +51,14 @@ describe('VsacCache', () => { ); }); - test('should be able to collect valueset references from Questionnaire Resources', async () => { + it('should be able to collect valueset references from Questionnaire Resources', async () => { const valueSets = client.collectQuestionnaireValuesets(questionnaire); - expect(valueSets).toEqual( + expect(valueSets).to.deep.equal( new Set(['http://terminology.hl7.org/ValueSet/yes-no-unknown-not-asked']) ); }); - test('should be able to cache valuesets in Library Resources', async function () { + it('should be able to cache valuesets in Library Resources', async function () { const mockRequest = nock('http://cts.nlm.nih.gov/fhir'); mockRequest @@ -60,74 +70,74 @@ describe('VsacCache', () => { const valueSets = client.collectLibraryValuesets(library); valueSets.forEach(async function (vs) { - expect(await client.isCached(vs)).toBeFalsy(); + expect(await client.isCached(vs)).to.be.false; }); try { await client.cacheLibrary(library); valueSets.forEach(async vs => { - expect(await client.isCached(vs)).toBeTruthy(); + expect(await client.isCached(vs)).to.be.true; }); } finally { mockRequest.done(); } }); - test('should be able to cache valuesets in Questionnaire Resources', async () => { + it('should be able to cache valuesets in Questionnaire Resources', async () => { const mockRequest = nock('http://terminology.hl7.org/'); mockRequest.get('/ValueSet/yes-no-unknown-not-asked').reply(200, JSON.stringify(valueSet)); const valueSets = client.collectQuestionnaireValuesets(questionnaire); valueSets.forEach(async vs => { - expect(await client.isCached(vs)).toBeFalsy(); + expect(await client.isCached(vs)).to.be.false; }); try { await client.cacheQuestionnaireItems(questionnaire); valueSets.forEach(async vs => { - expect(await client.isCached(vs)).toBeTruthy(); + expect(await client.isCached(vs)).to.be.true; }); } finally { mockRequest.done(); } }); - test.skip('should be not load valuesets already cached unless forced', async () => { + it.skip('should be not load valuesets already cached unless forced', async () => { const mockRequest = nock('http://terminology.hl7.org'); const vs = 'http://terminology.hl7.org/ValueSet/yes-no-unknown-not-asked'; mockRequest.get('/ValueSet/yes-no-unknown-not-asked').reply(200, JSON.stringify(valueSet)); try { const valueSets = client.collectQuestionnaireValuesets(questionnaire); - expect(await client.isCached(vs)).toBeFalsy(); + expect(await client.isCached(vs)).to.be.false; const cached = await client.downloadAndCacheValueset(vs); - expect(await client.isCached(vs)).toBeTruthy(); + expect(await client.isCached(vs)).to.be.true; mockRequest.get('/ValueSet/yes-no-unknown-not-asked').reply(200, JSON.stringify(valueSet)); let update = await client.downloadAndCacheValueset(vs); - expect(update.get('cached')).toBeFalsy(); + expect(update.get('cached')).to.be.false; mockRequest.get('/ValueSet/yes-no-unknown-not-asked').reply(200, JSON.stringify(valueSet)); update = await client.downloadAndCacheValueset(vs, true); - expect(update.get('cached')).toBeTruthy(); + expect(update.get('cached')).to.be.true; } finally { mockRequest.done(); } }); - test('should be able to handle errors downloading valuesests', async () => { + it('should be able to handle errors downloading valuesests', async () => { const mockRequest = nock('http://terminology.hl7.org/'); const vs = 'http://terminology.hl7.org/ValueSet/yes-no-unknown-not-asked'; mockRequest.get('/ValueSet/yes-no-unknown-not-asked').reply(404, ''); - expect(await client.isCached(vs)).toBeFalsy(); + expect(await client.isCached(vs)).to.be.false; let err; try { err = await client.downloadAndCacheValueset(vs); // console.log(err); - expect(err.get('error')).toBeDefined(); + expect(err.get('error')).to.not.be.undefined; } catch (e) { console.log('Expected Error to be defined', err); throw e; @@ -136,10 +146,10 @@ describe('VsacCache', () => { } }); - test('Should not attempt tp download non-vsac valuesets if configured to do so', async () => { + it('Should not attempt tp download non-vsac valuesets if configured to do so', async () => { client.onlyVsac = true; const err = await client.downloadAndCacheValueset('http://localhost:9999/vs/1234'); - expect(err.get('error')).toEqual( + expect(err.get('error')).to.equal( 'Cannot download non vsac valuesets: http://localhost:9999/vs/1234' ); }); diff --git a/src/lib/vsac_cache.ts b/src/lib/vsac_cache.ts index 12eeaead..a19a6ed0 100644 --- a/src/lib/vsac_cache.ts +++ b/src/lib/vsac_cache.ts @@ -174,10 +174,10 @@ class VsacCache { if (valueSet) { resolve(valueSet); } - resolve(null); + resolve(false); }); } else { - resolve(null); + resolve(false); } }); } diff --git a/src/lib/winston.test.ts b/src/lib/winston.test.ts index 508847bd..4141a32a 100644 --- a/src/lib/winston.test.ts +++ b/src/lib/winston.test.ts @@ -6,37 +6,38 @@ */ import container from './winston'; import config from '../config'; +import {assert, expect} from "chai"; describe('Logger Class', () => { beforeEach(() => { - jest.resetModules(); + }); - test('setup without daily log file', () => { + it('setup without daily log file', () => { const logger = container.get('application'); - expect(logger).toBeDefined(); - expect(logger.transports).toHaveLength(1); - expect(logger.transports[0].level).toBe(config.logging.level); + expect(logger).to.not.equal(undefined); + expect(logger.transports.length).to.equal(1); + expect(logger.transports[0].level).to.equal(config.logging.level); }); - test('setup with daily log file generation', () => { + it('setup with daily log file generation', () => { // Mock the config to test other branch of if statement - jest.mock('../config', () => ({ - logging: { - level: 'debug', - directory: 'logs' - } - })); + // jest.mock('../config', () => ({ + // logging: { + // level: 'debug', + // directory: 'logs' + // } + // })); const containerPromise = import('./winston'); const configPromise = import('../config'); containerPromise.then(container => { configPromise.then(config => { const logger = container.default.get('application'); - expect(logger).toBeDefined(); - expect(logger.transports).toHaveLength(2); - expect(logger.transports[0].level).toBe(config.default.logging.level); - expect(logger.transports[1].level).toBe(config.default.logging.level); + expect(logger).to.not.equal(undefined); + expect(logger.transports.length).to.equal(2); + expect(logger.transports[0].level).to.equal(config.default.logging.level); + expect(logger.transports[1].level).to.equal(config.default.logging.level); }); }); }); diff --git a/src/server.test.ts b/src/server.test.ts index bdf4fa88..5e1a5b58 100644 --- a/src/server.test.ts +++ b/src/server.test.ts @@ -2,83 +2,95 @@ import { initialize, REMSServer } from './server'; import config from './config'; import { Globals } from './globals'; import { Db, MongoClient } from 'mongodb'; +import sinon from "sinon"; +import {assert, expect} from "chai"; +const { MongoMemoryServer } = require("mongodb-memory-server"); +import mongoose, { ConnectOptions } from 'mongoose'; + describe('REMSServer class', () => { let server: REMSServer; let connection: MongoClient; let db: Db; - - beforeAll(async () => { - if (process.env.MONGO_URL) { - connection = await MongoClient.connect(process.env.MONGO_URL, {}); - db = await connection.db(process.env.MONGO_DB_NAME); - Globals.database = db; + let mongo: typeof MongoMemoryServer; + before(async () => { + + mongo = await MongoMemoryServer.create(); + const uri = mongo.getUri(); + let options :ConnectOptions = { + } + await mongoose.connect(uri, options); }); - afterAll(async () => { - await connection.close(); + after(async () => { + console.log("Closing connection?"); + + await mongoose.connection.dropDatabase(); + await mongoose.connection.close(); + await mongo.stop(); + }); beforeEach(() => { - jest.mock('morgan', () => jest.fn()); - - // Mock express and body parser - jest.mock('body-parser', () => ({ - urlencoded: jest.fn(), - json: jest.fn() - })); - - jest.mock('express', () => { - const mock = jest.fn(() => ({ - use: jest.fn(), - set: jest.fn(), - get: jest.fn(), - listen: jest.fn(), - options: jest.fn(), - post: jest.fn(), - static: jest.fn() - })); - return mock; - }); + // jest.mock('morgan', () => jest.fn()); + + // // Mock express and body parser + // jest.mock('body-parser', () => ({ + // urlencoded: jest.fn(), + // json: jest.fn() + // })); + + // jest.mock('express', () => { + // const mock = jest.fn(() => ({ + // use: jest.fn(), + // set: jest.fn(), + // get: jest.fn(), + // listen: jest.fn(), + // options: jest.fn(), + // post: jest.fn(), + // static: jest.fn() + // })); + // return mock; + // }); server = new REMSServer(config.fhirServerConfig); }); afterEach(() => { - jest.clearAllMocks(); + // jest.clearAllMocks(); }); - test('method: constructor', () => { - expect(server).toBeInstanceOf(REMSServer); - expect(server).toHaveProperty('app'); - expect(server).toHaveProperty('listen'); + it('method: constructor', () => { + expect(server).to.be.instanceOf(REMSServer); + expect(server).to.have.property('app'); + expect(server).to.have.property('listen'); }); - test('method: configureMiddleware', () => { - const set = jest.spyOn(server.app, 'set'); - const use = jest.spyOn(server.app, 'use'); + it('method: configureMiddleware', () => { + const set = sinon.spy(server.app, 'set'); + const use = sinon.spy(server.app, 'use'); server.configureMiddleware(); - expect(set).toHaveBeenCalledTimes(6); - expect(set.mock.calls[0][0]).toBe('showStackError'); - expect(set.mock.calls[0][1]).toBe(true); - expect(set.mock.calls[5][0]).toBe('jsonp callback'); - expect(set.mock.calls[5][1]).toBe(true); + expect(set.callCount).to.equal(6); + // expect(set.mock.calls[0][0]).toBe('showStackError'); + // expect(set.mock.calls[0][1]).toBe(true); + // expect(set.mock.calls[5][0]).toBe('jsonp callback'); + // expect(set.mock.calls[5][1]).toBe(true); - expect(use).toHaveBeenCalledTimes(8); + expect(use.callCount).to.equal(8); }); - test('method: configureLogstream', () => { - const use = jest.spyOn(server.app, 'use'); + it('method: configureLogstream', () => { + const use = sinon.spy(server.app, 'use'); server.configureLogstream(); - expect(use).toHaveBeenCalledTimes(1); + expect(use.calledOnce).to.have.true; }); - test('method: registerService', () => { + it('method: registerService', () => { const mockService = { definition: { hook: 'patient-view', @@ -93,7 +105,7 @@ describe('REMSServer class', () => { server.registerService(mockService); - expect(server.services).toStrictEqual([ + expect(server.services).to.deep.equal([ { hook: 'patient-view', name: 'foo', @@ -103,21 +115,21 @@ describe('REMSServer class', () => { ]); }); - test('Method: listen', () => { - const listen = jest.spyOn(server.app, 'listen'); - const callback = jest.fn(); + it('Method: listen', () => { + const listen = sinon.spy(server.app, 'listen'); + const callback = sinon.fake(); // Start listening on a port and pass the callback through const serverListen = server.listen({ port: 3000 }, callback); - expect(listen).toHaveBeenCalledTimes(1); - expect(listen.mock.calls[0][0]).toBe(3000); - expect(listen.mock.calls[0][1]).toBe(callback); + expect(listen.calledOnce).to.be.true; + // expect(listen.mock.calls[0][0]).toBe(3000); + // expect(listen.mock.calls[0][1]).toBe(callback); serverListen.close(); }); - test('should be able to initilize a server', () => { + it('should be able to initilize a server', () => { const newServer = initialize(config); - expect(newServer).toBeInstanceOf(REMSServer); - expect(newServer).toHaveProperty('app'); - expect(newServer).toHaveProperty('listen'); + expect(newServer).to.be.instanceOf(REMSServer); + expect(newServer).to.have.property('app'); + expect(newServer).to.have.property('listen'); }); }); From 41244928262403669f2c2f6575eedab6527015e4 Mon Sep 17 00:00:00 2001 From: Robert A Dingwell Date: Mon, 3 Apr 2023 14:17:09 -0400 Subject: [PATCH 12/19] Fixing liniting/prettier issues --- package.json | 1 + src/hooks/rems.hook.test.ts | 2 +- src/lib/__tests__/vsac_cache.test.ts | 16 ++++++---------- src/lib/winston.test.ts | 5 +---- src/server.test.ts | 19 +++++++------------ 5 files changed, 16 insertions(+), 27 deletions(-) diff --git a/package.json b/package.json index 47ca37cf..d7b3585b 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,7 @@ "@types/lodash": "^4.14.188", "@types/mocha": "^10.0.1", "@types/mongoose": "^5.11.97", + "@types/mongodb-memory-server": "2.3.0", "@types/morgan": "^1.9.3", "@types/node": "^18.11.9", "@types/nodemon": "^1.19.2", diff --git a/src/hooks/rems.hook.test.ts b/src/hooks/rems.hook.test.ts index 4e96e339..60dd15dd 100644 --- a/src/hooks/rems.hook.test.ts +++ b/src/hooks/rems.hook.test.ts @@ -1,6 +1,6 @@ import OrderSign from './OrderSign'; import getREMSHook from './rems.hook'; -import {expect} from 'chai'; +import { expect } from 'chai'; describe('hook: test rems', () => { it('should have definition and handler', () => { diff --git a/src/lib/__tests__/vsac_cache.test.ts b/src/lib/__tests__/vsac_cache.test.ts index 9d116f81..b74bd3eb 100644 --- a/src/lib/__tests__/vsac_cache.test.ts +++ b/src/lib/__tests__/vsac_cache.test.ts @@ -6,28 +6,24 @@ import nock from 'nock'; import constants from '../../constants'; import ValueSetModel from '../schemas/resources/ValueSet'; import mongoose, { ConnectOptions } from 'mongoose'; -const { MongoMemoryServer } = require("mongodb-memory-server"); -import { assert, expect } from "chai" +import { MongoMemoryServer } from 'mongodb-memory-server'; +import { assert, expect } from 'chai'; describe('VsacCache', () => { const client = new VsacCache('./tmp', '2c1d55c3-3484-4902-b645-25f3a4974ce6'); - let mongo: typeof MongoMemoryServer; + let mongo: any; before(async () => { - mongo = await MongoMemoryServer.create(); const uri = mongo.getUri(); - let options :ConnectOptions = { - - } + const options: ConnectOptions = {}; await mongoose.connect(uri, options); }); after(async () => { - console.log("Closing connection?"); - + console.log('Closing connection?'); + await mongoose.connection.dropDatabase(); await mongoose.connection.close(); await mongo.stop(); - }); beforeEach(async () => { diff --git a/src/lib/winston.test.ts b/src/lib/winston.test.ts index 4141a32a..0d589fbe 100644 --- a/src/lib/winston.test.ts +++ b/src/lib/winston.test.ts @@ -6,12 +6,9 @@ */ import container from './winston'; import config from '../config'; -import {assert, expect} from "chai"; +import { expect } from 'chai'; describe('Logger Class', () => { - beforeEach(() => { - - }); it('setup without daily log file', () => { const logger = container.get('application'); diff --git a/src/server.test.ts b/src/server.test.ts index 5e1a5b58..644f1044 100644 --- a/src/server.test.ts +++ b/src/server.test.ts @@ -1,10 +1,9 @@ import { initialize, REMSServer } from './server'; import config from './config'; -import { Globals } from './globals'; import { Db, MongoClient } from 'mongodb'; -import sinon from "sinon"; -import {assert, expect} from "chai"; -const { MongoMemoryServer } = require("mongodb-memory-server"); +import sinon from 'sinon'; +import {expect} from 'chai'; +import { MongoMemoryServer } from 'mongodb-memory-server'; import mongoose, { ConnectOptions } from 'mongoose'; describe('REMSServer class', () => { @@ -12,19 +11,18 @@ describe('REMSServer class', () => { let connection: MongoClient; let db: Db; - let mongo: typeof MongoMemoryServer; + let mongo: any; before(async () => { - mongo = await MongoMemoryServer.create(); const uri = mongo.getUri(); - let options :ConnectOptions = { + const options :ConnectOptions = { - } + }; await mongoose.connect(uri, options); }); after(async () => { - console.log("Closing connection?"); + console.log('Closing connection?'); await mongoose.connection.dropDatabase(); await mongoose.connection.close(); @@ -57,9 +55,6 @@ describe('REMSServer class', () => { server = new REMSServer(config.fhirServerConfig); }); - afterEach(() => { - // jest.clearAllMocks(); - }); it('method: constructor', () => { expect(server).to.be.instanceOf(REMSServer); From cff60ccfee855e4bed719f2ebcb9400946a2a786 Mon Sep 17 00:00:00 2001 From: Robert A Dingwell Date: Mon, 3 Apr 2023 14:43:02 -0400 Subject: [PATCH 13/19] more prettier issues --- src/lib/winston.test.ts | 1 - src/server.test.ts | 12 ++++-------- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/lib/winston.test.ts b/src/lib/winston.test.ts index 0d589fbe..87600480 100644 --- a/src/lib/winston.test.ts +++ b/src/lib/winston.test.ts @@ -9,7 +9,6 @@ import config from '../config'; import { expect } from 'chai'; describe('Logger Class', () => { - it('setup without daily log file', () => { const logger = container.get('application'); diff --git a/src/server.test.ts b/src/server.test.ts index 644f1044..1b58074e 100644 --- a/src/server.test.ts +++ b/src/server.test.ts @@ -2,8 +2,8 @@ import { initialize, REMSServer } from './server'; import config from './config'; import { Db, MongoClient } from 'mongodb'; import sinon from 'sinon'; -import {expect} from 'chai'; -import { MongoMemoryServer } from 'mongodb-memory-server'; +import { expect } from 'chai'; +import { MongoMemoryServer } from 'mongodb-memory-server'; import mongoose, { ConnectOptions } from 'mongoose'; describe('REMSServer class', () => { @@ -15,19 +15,16 @@ describe('REMSServer class', () => { before(async () => { mongo = await MongoMemoryServer.create(); const uri = mongo.getUri(); - const options :ConnectOptions = { - - }; + const options: ConnectOptions = {}; await mongoose.connect(uri, options); }); after(async () => { console.log('Closing connection?'); - + await mongoose.connection.dropDatabase(); await mongoose.connection.close(); await mongo.stop(); - }); beforeEach(() => { @@ -55,7 +52,6 @@ describe('REMSServer class', () => { server = new REMSServer(config.fhirServerConfig); }); - it('method: constructor', () => { expect(server).to.be.instanceOf(REMSServer); expect(server).to.have.property('app'); From 2f7b3074bbac2a037c0da9cc1770320117dfc4b3 Mon Sep 17 00:00:00 2001 From: Robert A Dingwell Date: Mon, 3 Apr 2023 14:47:52 -0400 Subject: [PATCH 14/19] Increasing timeout from 2 seconds to 10 seconds --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d7b3585b..3461cb83 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "scripts": { "develop": "node dist/scripts/develop.js", "start": "ts-node-dev --inspect=8091 src/scripts/serve.ts", - "test": "mocha -r ts-node/register src/*.test.ts src/**/*.test.ts src/**/**/*.test.ts", + "test": "mocha --timeout 10000 -r ts-node/register src/*.test.ts src/**/*.test.ts src/**/**/*.test.ts", "lint": "eslint \"**/*.{js,ts}\"", "lint:fix": "eslint \"**/*.{js,ts}\" --quiet --fix", "prettier": "prettier --check \"**/*.{js,ts}\"", From 9a745dbc6bba02f4fff1f8f99286796ada81a971 Mon Sep 17 00:00:00 2001 From: Robert A Dingwell Date: Tue, 4 Apr 2023 10:37:56 -0400 Subject: [PATCH 15/19] Moving test to thier own directory --- package.json | 2 +- {src/lib/__tests__ => test}/fixtures/library.json | 0 {src/lib/__tests__ => test}/fixtures/questionnaire.json | 0 {src/lib/__tests__ => test}/fixtures/valueSet.json | 0 {src/hooks => test}/rems.hook.test.ts | 4 ++-- {src => test}/server.test.ts | 4 ++-- {src/lib/__tests__ => test}/vsac_cache.test.ts | 5 ++--- {src/lib => test}/winston.test.ts | 8 ++++---- 8 files changed, 11 insertions(+), 12 deletions(-) rename {src/lib/__tests__ => test}/fixtures/library.json (100%) rename {src/lib/__tests__ => test}/fixtures/questionnaire.json (100%) rename {src/lib/__tests__ => test}/fixtures/valueSet.json (100%) rename {src/hooks => test}/rems.hook.test.ts (87%) rename {src => test}/server.test.ts (97%) rename {src/lib/__tests__ => test}/vsac_cache.test.ts (97%) rename {src/lib => test}/winston.test.ts (86%) diff --git a/package.json b/package.json index 3461cb83..0aaeaa2a 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "scripts": { "develop": "node dist/scripts/develop.js", "start": "ts-node-dev --inspect=8091 src/scripts/serve.ts", - "test": "mocha --timeout 10000 -r ts-node/register src/*.test.ts src/**/*.test.ts src/**/**/*.test.ts", + "test": "mocha --timeout 10000 -r ts-node/register test/*.test.ts", "lint": "eslint \"**/*.{js,ts}\"", "lint:fix": "eslint \"**/*.{js,ts}\" --quiet --fix", "prettier": "prettier --check \"**/*.{js,ts}\"", diff --git a/src/lib/__tests__/fixtures/library.json b/test/fixtures/library.json similarity index 100% rename from src/lib/__tests__/fixtures/library.json rename to test/fixtures/library.json diff --git a/src/lib/__tests__/fixtures/questionnaire.json b/test/fixtures/questionnaire.json similarity index 100% rename from src/lib/__tests__/fixtures/questionnaire.json rename to test/fixtures/questionnaire.json diff --git a/src/lib/__tests__/fixtures/valueSet.json b/test/fixtures/valueSet.json similarity index 100% rename from src/lib/__tests__/fixtures/valueSet.json rename to test/fixtures/valueSet.json diff --git a/src/hooks/rems.hook.test.ts b/test/rems.hook.test.ts similarity index 87% rename from src/hooks/rems.hook.test.ts rename to test/rems.hook.test.ts index 60dd15dd..55d3fe07 100644 --- a/src/hooks/rems.hook.test.ts +++ b/test/rems.hook.test.ts @@ -1,5 +1,5 @@ -import OrderSign from './OrderSign'; -import getREMSHook from './rems.hook'; +import OrderSign from '../src/hooks/OrderSign'; +import getREMSHook from '../src/hooks/rems.hook'; import { expect } from 'chai'; describe('hook: test rems', () => { diff --git a/src/server.test.ts b/test/server.test.ts similarity index 97% rename from src/server.test.ts rename to test/server.test.ts index 1b58074e..e31e7e30 100644 --- a/src/server.test.ts +++ b/test/server.test.ts @@ -1,5 +1,5 @@ -import { initialize, REMSServer } from './server'; -import config from './config'; +import { initialize, REMSServer } from '../src/server'; +import config from '../src/config'; import { Db, MongoClient } from 'mongodb'; import sinon from 'sinon'; import { expect } from 'chai'; diff --git a/src/lib/__tests__/vsac_cache.test.ts b/test/vsac_cache.test.ts similarity index 97% rename from src/lib/__tests__/vsac_cache.test.ts rename to test/vsac_cache.test.ts index b74bd3eb..99418d6a 100644 --- a/src/lib/__tests__/vsac_cache.test.ts +++ b/test/vsac_cache.test.ts @@ -1,10 +1,9 @@ -import VsacCache from '../vsac_cache'; +import VsacCache from '../src/lib/vsac_cache'; import library from './fixtures/library.json'; import questionnaire from './fixtures/questionnaire.json'; import valueSet from './fixtures/valueSet.json'; import nock from 'nock'; -import constants from '../../constants'; -import ValueSetModel from '../schemas/resources/ValueSet'; +import ValueSetModel from '../src/lib/schemas/resources/ValueSet'; import mongoose, { ConnectOptions } from 'mongoose'; import { MongoMemoryServer } from 'mongodb-memory-server'; import { assert, expect } from 'chai'; diff --git a/src/lib/winston.test.ts b/test/winston.test.ts similarity index 86% rename from src/lib/winston.test.ts rename to test/winston.test.ts index 87600480..c770d4c1 100644 --- a/src/lib/winston.test.ts +++ b/test/winston.test.ts @@ -4,8 +4,8 @@ * environment based configuration that changes between runs. We need this * for full coverage */ -import container from './winston'; -import config from '../config'; +import container from '../src/lib/winston'; +import config from '../src/config'; import { expect } from 'chai'; describe('Logger Class', () => { @@ -25,8 +25,8 @@ describe('Logger Class', () => { // directory: 'logs' // } // })); - const containerPromise = import('./winston'); - const configPromise = import('../config'); + const containerPromise = import('../src/lib/winston'); + const configPromise = import('../src/config'); containerPromise.then(container => { configPromise.then(config => { const logger = container.default.get('application'); From 93820b6c99ba7906b64194adff5c859e4997de35 Mon Sep 17 00:00:00 2001 From: Robert A Dingwell Date: Tue, 4 Apr 2023 11:12:22 -0400 Subject: [PATCH 16/19] adding inspection of spied calls --- .eslintrc | 4 +++- package.json | 7 ++++--- test/server.test.ts | 34 ++++++---------------------------- 3 files changed, 13 insertions(+), 32 deletions(-) diff --git a/.eslintrc b/.eslintrc index bbb67807..dccaa743 100644 --- a/.eslintrc +++ b/.eslintrc @@ -5,7 +5,8 @@ "plugin:@typescript-eslint/recommended" ], "plugins": [ - "@typescript-eslint" + "@typescript-eslint", + "prettier" ], "parser": "@typescript-eslint/parser", "parserOptions": { @@ -13,6 +14,7 @@ "sourceType": "module" }, "rules": { + "prettier/prettier": ["error"], "semi": ["off"], "@typescript-eslint/semi": ["error", "always"], "quotes": ["error", "single", { "avoidEscape": true }], diff --git a/package.json b/package.json index 0aaeaa2a..036d2f5d 100644 --- a/package.json +++ b/package.json @@ -52,19 +52,20 @@ "@types/express": "^4.17.14", "@types/lodash": "^4.14.188", "@types/mocha": "^10.0.1", - "@types/mongoose": "^5.11.97", "@types/mongodb-memory-server": "2.3.0", + "@types/mongoose": "^5.11.97", "@types/morgan": "^1.9.3", "@types/node": "^18.11.9", "@types/nodemon": "^1.19.2", - "@types/sinon" : "10.0.13", + "@types/sinon": "10.0.13", "@types/uuid": "^9.0.0", "@typescript-eslint/eslint-plugin": "^5.45.0", "@typescript-eslint/parser": "^5.45.0", "axios-mock-adapter": "^1.21.2", "chai": "^4.3.7", "eslint": "^8.28.0", - "eslint-config-prettier": "^6.10.1", + "eslint-config-prettier": "^6.15.0", + "eslint-plugin-prettier": "^4.2.1", "json-diff": "^0.9.0", "mocha": "^10.2.0", "mongodb-memory-server": "^8.12.1", diff --git a/test/server.test.ts b/test/server.test.ts index e31e7e30..ef2df2c8 100644 --- a/test/server.test.ts +++ b/test/server.test.ts @@ -28,27 +28,6 @@ describe('REMSServer class', () => { }); beforeEach(() => { - // jest.mock('morgan', () => jest.fn()); - - // // Mock express and body parser - // jest.mock('body-parser', () => ({ - // urlencoded: jest.fn(), - // json: jest.fn() - // })); - - // jest.mock('express', () => { - // const mock = jest.fn(() => ({ - // use: jest.fn(), - // set: jest.fn(), - // get: jest.fn(), - // listen: jest.fn(), - // options: jest.fn(), - // post: jest.fn(), - // static: jest.fn() - // })); - // return mock; - // }); - server = new REMSServer(config.fhirServerConfig); }); @@ -63,12 +42,11 @@ describe('REMSServer class', () => { const use = sinon.spy(server.app, 'use'); server.configureMiddleware(); - expect(set.callCount).to.equal(6); - // expect(set.mock.calls[0][0]).toBe('showStackError'); - // expect(set.mock.calls[0][1]).toBe(true); - // expect(set.mock.calls[5][0]).toBe('jsonp callback'); - // expect(set.mock.calls[5][1]).toBe(true); + expect(set.getCall(4).args[0]).to.equal('showStackError'); + expect(set.getCall(4).args[1]).to.be.true; + expect(set.getCall(5).args[0]).to.equal('jsonp callback'); + expect(set.getCall(5).args[1]).to.be.true; expect(use.callCount).to.equal(8); }); @@ -112,8 +90,8 @@ describe('REMSServer class', () => { // Start listening on a port and pass the callback through const serverListen = server.listen({ port: 3000 }, callback); expect(listen.calledOnce).to.be.true; - // expect(listen.mock.calls[0][0]).toBe(3000); - // expect(listen.mock.calls[0][1]).toBe(callback); + expect(listen.getCall(0).args[0]).to.equal(3000); + expect(listen.getCall(0).args[1]).to.equal(callback); serverListen.close(); }); From 9ce0a7e1c0dae48818a3365e608de62e9d518a67 Mon Sep 17 00:00:00 2001 From: rdingwell Date: Tue, 4 Apr 2023 15:46:51 -0400 Subject: [PATCH 17/19] Update ci-workflow.yml Reverting to node 14 --- .github/workflows/ci-workflow.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-workflow.yml b/.github/workflows/ci-workflow.yml index cb680df3..1e864950 100644 --- a/.github/workflows/ci-workflow.yml +++ b/.github/workflows/ci-workflow.yml @@ -22,7 +22,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] - node-version: [18] + node-version: [14] steps: - uses: actions/checkout@v1 @@ -33,4 +33,4 @@ jobs: - run: npm install - run: npm test env: - CI: true \ No newline at end of file + CI: true From adf38971e2851b2ae481d48e536e3833f662f937 Mon Sep 17 00:00:00 2001 From: rdingwell Date: Tue, 4 Apr 2023 17:32:56 -0400 Subject: [PATCH 18/19] Update package.json Upping test timeout for github runners --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d511d25f..6d46c2a9 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "scripts": { "develop": "node dist/scripts/develop.js", "start": "ts-node-dev --inspect=8091 src/scripts/serve.ts", - "test": "mocha --timeout 10000 -r ts-node/register test/*.test.ts", + "test": "mocha --timeout 20000 -r ts-node/register test/*.test.ts", "lint": "eslint \"**/*.{js,ts}\"", "lint:fix": "eslint \"**/*.{js,ts}\" --quiet --fix", "prettier": "prettier --check \"**/*.{js,ts}\"", From 31bc96350a8817ad30d0c77dc0c6183e61133b43 Mon Sep 17 00:00:00 2001 From: Robert A Dingwell Date: Fri, 14 Apr 2023 13:12:56 -0400 Subject: [PATCH 19/19] changing environment varible name to match changes in code --- docker-compose-dev.yml | 4 ++-- docker-compose-m1.yml | 2 +- docker-compose.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml index abaa1eef..0497296c 100644 --- a/docker-compose-dev.yml +++ b/docker-compose-dev.yml @@ -102,7 +102,7 @@ services: - "8091:8091" environment: VSAC_API_KEY: ${VSAC_API_KEY} - MONGO_HOSTNAME: mongodb://rems-user:pass@pims_remsadmin_mongo:27017 + MONGO_URL: mongodb://rems-user:pass@pims_remsadmin_mongo:27017 volumes: - rems_dev_rems-sync:/REMS:nocopy # nocopy is important - rems_dev_rems-nodeModules:/REMS/node_modules @@ -118,7 +118,7 @@ services: - "5051:5051" environment: REMS_ADMIN_BASE: http://rems-administrator:8090 - MONGO_HOSTNAME: mongodb://pims_remsadmin_mongo:27017/pims + MONGO_URL: mongodb://pims_remsadmin_mongo:27017/pims volumes: - rems_dev_pims-sync:/home/node/app/pims:nocopy - rems_dev_pims-nodeModules:/home/node/app/pims/node_modules diff --git a/docker-compose-m1.yml b/docker-compose-m1.yml index 9702174d..d4b34777 100644 --- a/docker-compose-m1.yml +++ b/docker-compose-m1.yml @@ -56,7 +56,7 @@ services: - "9015:9015" # Bind port 3000 of host to 3000 of container environment: VSAC_API_KEY: ${VSAC_API_KEY} - MONGO_HOSTNAME: mongodb://rems-admin-pims-root:rems-admin-pims-password@pims_remsadmin_mongo:27017 + MONGO_URL: mongodb://rems-admin-pims-root:rems-admin-pims-password@pims_remsadmin_mongo:27017 pims_remsadmin_mongo: image: mongo diff --git a/docker-compose.yml b/docker-compose.yml index 485af4f3..d8045140 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -57,7 +57,7 @@ services: - "9015:9015" # Bind port 3000 of host to 3000 of container environment: VSAC_API_KEY: ${VSAC_API_KEY} - MONGO_HOSTNAME: mongodb://rems-admin-pims-root:rems-admin-pims-password@pims_remsadmin_mongo:27017 + MONGO_URL: mongodb://rems-admin-pims-root:rems-admin-pims-password@pims_remsadmin_mongo:27017 pims_remsadmin_mongo: image: mongo