diff --git a/docker/env/fulfilment_job.secrets.env.example b/docker/env/fulfilment_job.secrets.env.example index e7f40b6fd0..ac2bd67751 100644 --- a/docker/env/fulfilment_job.secrets.env.example +++ b/docker/env/fulfilment_job.secrets.env.example @@ -11,5 +11,5 @@ OAUTH_CLIENT_ID= OAUTH_CLIENT_SECRET= OAUTH_SCOPE= -DYNAMICS_API_PATH= +DYNAMICS_API_HOST= DYNAMICS_API_VERSION= diff --git a/docker/env/sales_api.secrets.env.example b/docker/env/sales_api.secrets.env.example index 6ef9b3d211..1aa727eb45 100644 --- a/docker/env/sales_api.secrets.env.example +++ b/docker/env/sales_api.secrets.env.example @@ -11,7 +11,7 @@ OAUTH_CLIENT_ID= OAUTH_CLIENT_SECRET= OAUTH_SCOPE= -DYNAMICS_API_PATH= +DYNAMICS_API_HOST= DYNAMICS_API_VERSION= # GOV.UK Pay diff --git a/package-lock.json b/package-lock.json index ae23770a37..6151611c00 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,7 @@ "@types/jest": "27.4.0", "babel-jest": "27.5.1", "clone-deep": "4.0.1", - "dynamics-web-api": "1.7.3", + "dynamics-web-api": "^2.4.0", "eslint": "7.32.0", "husky": "9.1.7", "jest": "27.5.1", @@ -14031,12 +14031,12 @@ } }, "node_modules/dynamics-web-api": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/dynamics-web-api/-/dynamics-web-api-1.7.3.tgz", - "integrity": "sha512-ExscNNVrlXr/KoK5Sg/8GJyWndenHC26YKhnZVHaKOtAxWqsQzvveWnDl289BbFwPmwM18ZZWk8G5fFqPp981w==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/dynamics-web-api/-/dynamics-web-api-2.4.0.tgz", + "integrity": "sha512-kt4rstUaGzmP86qoognqu8DZg/0cMS+dTLAj8ys/jtFYh1UjXyAxdPhSapy3bOI9tjPo/fN6JbMgtZEXhbiXog==", "dependencies": { "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0" + "https-proxy-agent": "^5.0.1" } }, "node_modules/dynamics-web-api/node_modules/http-proxy-agent": { @@ -35180,7 +35180,7 @@ "cache-manager": "3.6.0", "cache-manager-ioredis": "2.1.0", "debug": "4.3.3", - "dynamics-web-api": "1.7.3", + "dynamics-web-api": "^2.4.0", "joi": "17.13.3", "moment": "2.29.1", "pluralize": "8.0.0", @@ -35232,6 +35232,7 @@ "@defra-fish/dynamics-lib": "1.70.0-rc.11", "commander": "7.2.0", "debug": "4.3.3", + "dynamics-web-api": "^2.4.0", "merge2": "1.4.1", "moment": "2.29.1", "openpgp": "5.0.0-1", @@ -35544,6 +35545,7 @@ "@hapi/vision": "6.1.0", "debug": "4.3.3", "dot-prop": "6.0.1", + "dynamics-web-api": "^2.4.0", "hapi-and-healthy": "7.0.7", "hapi-swagger": "14.2.5", "ioredis": "4.28.5", diff --git a/package.json b/package.json index e668aeb807..0392e4f716 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "@types/jest": "27.4.0", "babel-jest": "27.5.1", "clone-deep": "4.0.1", - "dynamics-web-api": "1.7.3", + "dynamics-web-api": "^2.4.0", "eslint": "7.32.0", "husky": "9.1.7", "jest": "27.5.1", diff --git a/packages/dynamics-lib/README.md b/packages/dynamics-lib/README.md index 71a3b16921..72046b8a81 100644 --- a/packages/dynamics-lib/README.md +++ b/packages/dynamics-lib/README.md @@ -16,7 +16,7 @@ shared by the different packages which comprise the Rod Licensing digital servic | OAUTH_AUTHORITY_HOST_URL | OAuth 2.0 authority host | yes | | | | | OAUTH_TENANT | OAuth 2.0 tenant | yes | | | | | OAUTH_SCOPE | OAuth 2.0 scope to request (client credentials resource) | yes | | | | -| DYNAMICS_API_PATH | Full URL to the dynamics API | yes | | | The full URL to the dynamics web api. e.g. https://dynamics-server/api/data/v9.1/ | +| DYNAMICS_API_HOST | The root domain of the dynamics server | yes | | | The root domain of the dynamics server. e.g. https://dynamics-server | | DYNAMICS_API_VERSION | The version of the Dynamics API | yes | | | The version of the dynamics web api. e.g. 9.1 | | DYNAMICS_API_TIMEOUT | The Dynamics API request timeout | no | 90000 | | The time in milliseconds after which requests will timeout if Dynamics does not return a response, e.g. 90000 | | DYNAMICS_CACHE_TTL | Default TTL for cached operations | no | 12 hours | | The default TTL for cached operations. Specified in seconds. | diff --git a/packages/dynamics-lib/package-lock.json b/packages/dynamics-lib/package-lock.json index 1686a74631..bf2dfaa332 100644 --- a/packages/dynamics-lib/package-lock.json +++ b/packages/dynamics-lib/package-lock.json @@ -12,7 +12,7 @@ "cache-manager": "3.6.0", "cache-manager-ioredis": "2.1.0", "debug": "4.3.3", - "dynamics-web-api": "1.7.3", + "dynamics-web-api": "^2.4.0", "joi": "17.13.3", "moment": "2.29.1", "pluralize": "8.0.0", @@ -155,12 +155,12 @@ } }, "node_modules/dynamics-web-api": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/dynamics-web-api/-/dynamics-web-api-1.7.3.tgz", - "integrity": "sha512-ExscNNVrlXr/KoK5Sg/8GJyWndenHC26YKhnZVHaKOtAxWqsQzvveWnDl289BbFwPmwM18ZZWk8G5fFqPp981w==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/dynamics-web-api/-/dynamics-web-api-2.4.0.tgz", + "integrity": "sha512-kt4rstUaGzmP86qoognqu8DZg/0cMS+dTLAj8ys/jtFYh1UjXyAxdPhSapy3bOI9tjPo/fN6JbMgtZEXhbiXog==", "dependencies": { "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0" + "https-proxy-agent": "^5.0.1" } }, "node_modules/http-proxy-agent": { diff --git a/packages/dynamics-lib/package.json b/packages/dynamics-lib/package.json index 7c5b8300ac..4a62de1956 100644 --- a/packages/dynamics-lib/package.json +++ b/packages/dynamics-lib/package.json @@ -36,7 +36,7 @@ "cache-manager": "3.6.0", "cache-manager-ioredis": "2.1.0", "debug": "4.3.3", - "dynamics-web-api": "1.7.3", + "dynamics-web-api": "^2.4.0", "joi": "17.13.3", "moment": "2.29.1", "pluralize": "8.0.0", diff --git a/packages/dynamics-lib/src/__mocks__/dynamics-web-api-mock-helper.js b/packages/dynamics-lib/src/__mocks__/dynamics-web-api-mock-helper.js index a5c15f4599..010da0fd75 100644 --- a/packages/dynamics-lib/src/__mocks__/dynamics-web-api-mock-helper.js +++ b/packages/dynamics-lib/src/__mocks__/dynamics-web-api-mock-helper.js @@ -3,7 +3,7 @@ const { readFileSync } = jest.requireActual('fs') const Path = jest.requireActual('path') const optionSetDataPath = Path.join(Project.root, 'src', '__mocks__', 'option-set-data.json') -export const configureDynamicsWebApiMock = (DynamicsWebApi = jest.genMockFromModule('dynamics-web-api')) => { +export const configureDynamicsWebApiMock = DynamicsWebApi => { let expectedResponse = {} let nextResponses = {} let callError = {} @@ -53,12 +53,12 @@ export const configureDynamicsWebApiMock = (DynamicsWebApi = jest.genMockFromMod } } - DynamicsWebApi.prototype.retrieveRequest = jest.fn(async () => responseCapableMethod('retrieveRequest')) - DynamicsWebApi.prototype.createRequest = jest.fn(async () => responseCapableMethod('createRequest')) - DynamicsWebApi.prototype.updateRequest = jest.fn(async () => responseCapableMethod('updateRequest')) - DynamicsWebApi.prototype.retrieveMultipleRequest = jest.fn(async () => responseCapableMethod('retrieveMultipleRequest')) + DynamicsWebApi.prototype.retrieve = jest.fn(async () => responseCapableMethod('retrieve')) + DynamicsWebApi.prototype.create = jest.fn(async () => responseCapableMethod('create')) + DynamicsWebApi.prototype.update = jest.fn(async () => responseCapableMethod('update')) + DynamicsWebApi.prototype.retrieveMultiple = jest.fn(async () => responseCapableMethod('retrieveMultiple')) DynamicsWebApi.prototype.retrieveGlobalOptionSets = jest.fn(async () => responseCapableMethod('retrieveGlobalOptionSets')) - DynamicsWebApi.prototype.executeUnboundFunction = jest.fn(async functionName => { + DynamicsWebApi.prototype.callFunction = jest.fn(async functionName => { let returnValue = null if (functionName === 'RetrieveVersion') { returnValue = { diff --git a/packages/dynamics-lib/src/__mocks__/dynamics-web-api.js b/packages/dynamics-lib/src/__mocks__/dynamics-web-api.js index 92b97aabd5..f6fce5d3c2 100644 --- a/packages/dynamics-lib/src/__mocks__/dynamics-web-api.js +++ b/packages/dynamics-lib/src/__mocks__/dynamics-web-api.js @@ -1,3 +1,5 @@ import { configureDynamicsWebApiMock } from './dynamics-web-api-mock-helper.js' -const DynamicsWebApi = jest.genMockFromModule('dynamics-web-api') -export default configureDynamicsWebApiMock(DynamicsWebApi) +const DynamicsWebApi = jest.fn() +DynamicsWebApi.prototype = {} +configureDynamicsWebApiMock(DynamicsWebApi) +export { DynamicsWebApi } diff --git a/packages/dynamics-lib/src/client/__tests__/dynamics-client.spec.js b/packages/dynamics-lib/src/client/__tests__/dynamics-client.spec.js index 169ea117d0..ad75f90a2f 100644 --- a/packages/dynamics-lib/src/client/__tests__/dynamics-client.spec.js +++ b/packages/dynamics-lib/src/client/__tests__/dynamics-client.spec.js @@ -3,7 +3,7 @@ import SimpleOAuth2 from 'simple-oauth2' describe('dynamics-client', () => { it('is configured via environment variables', async () => { - process.env.DYNAMICS_API_PATH = 'https://test-server/api/data/v9.1/' + process.env.DYNAMICS_API_HOST = 'https://test-server' process.env.DYNAMICS_API_VERSION = '9.1' process.env.DYNAMICS_API_TIMEOUT = 60000 process.env.OAUTH_AUTHORITY_HOST_URL = 'https://test-authority/' @@ -14,26 +14,24 @@ describe('dynamics-client', () => { const dynamicsApiConfig = config() expect(dynamicsApiConfig).toMatchObject({ - webApiUrl: process.env.DYNAMICS_API_PATH, - webApiVersion: process.env.DYNAMICS_API_VERSION, + serverUrl: process.env.DYNAMICS_API_HOST, + dataApi: { version: process.env.DYNAMICS_API_VERSION }, timeout: `${process.env.DYNAMICS_API_TIMEOUT}`, onTokenRefresh: expect.any(Function) }) - const testCallback = jest.fn() - await dynamicsApiConfig.onTokenRefresh(testCallback) - expect(testCallback).toHaveBeenCalledWith('MOCK TOKEN') + const token = await dynamicsApiConfig.onTokenRefresh() + expect(token).toBe('MOCK TOKEN') }) it('caches tokens until they expire', async () => { const dynamicsApiConfig = config() - const testCallback = jest.fn() - await dynamicsApiConfig.onTokenRefresh(testCallback) - expect(testCallback).toHaveBeenLastCalledWith('MOCK TOKEN') + let token = await dynamicsApiConfig.onTokenRefresh() + expect(token).toBe('MOCK TOKEN') SimpleOAuth2.__setMockTokenReturnValue('NEW MOCK TOKEN') - await dynamicsApiConfig.onTokenRefresh(testCallback) - expect(testCallback).toHaveBeenLastCalledWith('MOCK TOKEN') + token = await dynamicsApiConfig.onTokenRefresh() + expect(token).toBe('MOCK TOKEN') SimpleOAuth2.__setMockTokenExpired(true) - await dynamicsApiConfig.onTokenRefresh(testCallback) - expect(testCallback).toHaveBeenLastCalledWith('NEW MOCK TOKEN') + token = await dynamicsApiConfig.onTokenRefresh() + expect(token).toBe('NEW MOCK TOKEN') }) }) diff --git a/packages/dynamics-lib/src/client/__tests__/entity-manager.spec.js b/packages/dynamics-lib/src/client/__tests__/entity-manager.spec.js index 02858cf9ad..cc55fca311 100644 --- a/packages/dynamics-lib/src/client/__tests__/entity-manager.spec.js +++ b/packages/dynamics-lib/src/client/__tests__/entity-manager.spec.js @@ -13,7 +13,7 @@ import { } from '../../index.js' import TestEntity from '../../__mocks__/TestEntity.js' import { v4 as uuidv4 } from 'uuid' -import MockDynamicsWebApi from 'dynamics-web-api' +import { DynamicsWebApi as MockDynamicsWebApi } from 'dynamics-web-api' import { PredefinedQuery } from '../../queries/predefined-query.js' import { BaseEntity, EntityDefinition } from '../../entities/base.entity.js' @@ -33,7 +33,7 @@ describe('entity manager', () => { t.boolVal = true const result = await persist([t]) - expect(MockDynamicsWebApi.prototype.createRequest).toHaveBeenCalled() + expect(MockDynamicsWebApi.prototype.create).toHaveBeenCalled() expect(result).toHaveLength(1) expect(result[0]).toEqual(resultUuid) }) @@ -54,7 +54,7 @@ describe('entity manager', () => { ) const result = await persist([t]) - expect(MockDynamicsWebApi.prototype.updateRequest).toHaveBeenCalled() + expect(MockDynamicsWebApi.prototype.update).toHaveBeenCalled() expect(result).toHaveLength(1) expect(result[0]).toEqual(resultUuid) }) @@ -69,7 +69,7 @@ describe('entity manager', () => { t.boolVal = true const result = await persist([t], 'foo') - expect(MockDynamicsWebApi.prototype.createRequest).toHaveBeenCalled() + expect(MockDynamicsWebApi.prototype.create).toHaveBeenCalled() expect(MockDynamicsWebApi.prototype.executeBatch).toHaveBeenCalledWith( expect.objectContaining({ impersonateAAD: 'foo' @@ -94,10 +94,10 @@ describe('entity manager', () => { {} ) await expect(persist([newEntity, existingEntity])).rejects.toThrow('Test error') - // Expect the console error to contain details of the batch data (one createRequest, one updateRequest plus the exception object) + // Expect the console error to contain details of the batch data (one create, one update plus the exception object) expect(consoleErrorSpy).toHaveBeenCalledWith( expect.stringMatching('Error persisting batch. Data: %j, Exception: %o'), - expect.arrayContaining([{ createRequest: expect.any(Object) }, { updateRequest: expect.any(Object) }]), + expect.arrayContaining([{ create: expect.any(Object) }, { update: expect.any(Object) }]), expect.any(Error) ) }) @@ -332,14 +332,14 @@ describe('entity manager', () => { describe('findById', () => { it('finds by a primary key guid', async () => { - MockDynamicsWebApi.__setResponse('retrieveRequest', { + MockDynamicsWebApi.__setResponse('retrieve', { '@odata.etag': 'W/"202465000"', idval: '9f1b34a0-0c66-e611-80dc-c4346bad0190', strval: 'example' }) const result = await findById(TestEntity, '9f1b34a0-0c66-e611-80dc-c4346bad0190') - expect(MockDynamicsWebApi.prototype.retrieveRequest).toBeCalledWith({ + expect(MockDynamicsWebApi.prototype.retrieve).toBeCalledWith({ key: '9f1b34a0-0c66-e611-80dc-c4346bad0190', collection: TestEntity.definition.dynamicsCollection, select: TestEntity.definition.select @@ -350,13 +350,13 @@ describe('entity manager', () => { it('returns null if not found', async () => { const notFoundError = new Error('Not found') notFoundError.status = 404 - MockDynamicsWebApi.__throwWithErrorOn('retrieveRequest', notFoundError) + MockDynamicsWebApi.__throwWithErrorOn('retrieve', notFoundError) const result = await findById(TestEntity, '9f1b34a0-0c66-e611-80dc-c4346bad0190') expect(result).toEqual(null) }) it('throws an exception on general errors', async () => { - MockDynamicsWebApi.__throwWithErrorOn('retrieveRequest') + MockDynamicsWebApi.__throwWithErrorOn('retrieve') const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(jest.fn()) await expect(findById(TestEntity, '9f1b34a0-0c66-e611-80dc-c4346bad0190')).rejects.toThrow('Test error') expect(consoleErrorSpy).toHaveBeenCalled() @@ -365,13 +365,13 @@ describe('entity manager', () => { describe('findByAlternateKey', () => { it('finds by an alternate key', async () => { - MockDynamicsWebApi.__setResponse('retrieveRequest', { + MockDynamicsWebApi.__setResponse('retrieve', { '@odata.etag': 'W/"202465000"', idval: '9f1b34a0-0c66-e611-80dc-c4346bad0190', strval: 'example' }) const result = await findByAlternateKey(TestEntity, 'example') - expect(MockDynamicsWebApi.prototype.retrieveRequest).toBeCalledWith({ + expect(MockDynamicsWebApi.prototype.retrieve).toBeCalledWith({ key: "strval='example'", collection: TestEntity.definition.dynamicsCollection, select: TestEntity.definition.select @@ -381,13 +381,13 @@ describe('entity manager', () => { }) it('escapes special characters in the key', async () => { - MockDynamicsWebApi.__setResponse('retrieveRequest', { + MockDynamicsWebApi.__setResponse('retrieve', { '@odata.etag': 'W/"202465000"', idval: '9f1b34a0-0c66-e611-80dc-c4346bad0190', strval: 'example' }) const result = await findByAlternateKey(TestEntity, "test & example'") - expect(MockDynamicsWebApi.prototype.retrieveRequest).toBeCalledWith({ + expect(MockDynamicsWebApi.prototype.retrieve).toBeCalledWith({ key: "strval='test %26 example'''", collection: TestEntity.definition.dynamicsCollection, select: TestEntity.definition.select @@ -399,7 +399,7 @@ describe('entity manager', () => { describe('findByExample', () => { it('builds a select statement appropriate to the type definition for each field', async () => { - MockDynamicsWebApi.__setResponse('retrieveMultipleRequest', { value: [{}] }) + MockDynamicsWebApi.__setResponse('retrieveMultiple', { value: [{}] }) const lookup = new TestEntity() lookup.strVal = 'StringData' @@ -412,7 +412,7 @@ describe('entity manager', () => { const expectedLookupSelect = "strval eq 'StringData' and intval eq 123 and decval eq 123.45 and boolval eq true and dateval eq 1946-01-01 and datetimeval eq 1946-01-01T01:02:03Z and optionsetval eq 910400000" const result = await findByExample(lookup) - expect(MockDynamicsWebApi.prototype.retrieveMultipleRequest).toBeCalledWith({ + expect(MockDynamicsWebApi.prototype.retrieveMultiple).toBeCalledWith({ collection: TestEntity.definition.dynamicsCollection, select: TestEntity.definition.select, filter: expect.stringMatching(`${TestEntity.definition.defaultFilter} and ${expectedLookupSelect}`) @@ -422,7 +422,7 @@ describe('entity manager', () => { }) it('does not require the entity to define a default filter', async () => { - MockDynamicsWebApi.__setResponse('retrieveMultipleRequest', { value: [{}] }) + MockDynamicsWebApi.__setResponse('retrieveMultiple', { value: [{}] }) class SameEntity extends BaseEntity { static _definition = new EntityDefinition(() => ({ @@ -458,7 +458,7 @@ describe('entity manager', () => { lookup.testVal = 'StringData' const expectedLookupSelect = "testval eq 'StringData'" const result = await findByExample(lookup) - expect(MockDynamicsWebApi.prototype.retrieveMultipleRequest).toBeCalledWith({ + expect(MockDynamicsWebApi.prototype.retrieveMultiple).toBeCalledWith({ collection: SameEntity.definition.dynamicsCollection, select: SameEntity.definition.select, filter: expect.stringMatching(`${expectedLookupSelect}`) @@ -468,13 +468,13 @@ describe('entity manager', () => { }) it('only serializes fields into the select statement if they are set', async () => { - MockDynamicsWebApi.__setResponse('retrieveMultipleRequest', { value: [{}] }) + MockDynamicsWebApi.__setResponse('retrieveMultiple', { value: [{}] }) const lookup = new TestEntity() lookup.strVal = 'StringData' const expectedLookupSelect = "strval eq 'StringData'" const result = await findByExample(lookup) - expect(MockDynamicsWebApi.prototype.retrieveMultipleRequest).toBeCalledWith({ + expect(MockDynamicsWebApi.prototype.retrieveMultiple).toBeCalledWith({ collection: TestEntity.definition.dynamicsCollection, select: TestEntity.definition.select, filter: expect.stringMatching(`${TestEntity.definition.defaultFilter} and ${expectedLookupSelect}`) @@ -484,7 +484,7 @@ describe('entity manager', () => { }) it('throws an error object on failure', async () => { - MockDynamicsWebApi.__throwWithErrorOn('retrieveMultipleRequest') + MockDynamicsWebApi.__throwWithErrorOn('retrieveMultiple') const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(jest.fn()) await expect(findByExample(new TestEntity())).rejects.toThrow('Test error') expect(consoleErrorSpy).toHaveBeenCalled() @@ -492,8 +492,8 @@ describe('entity manager', () => { }) describe('executeQuery', () => { - it('calls retrieveMultipleRequest on the Dynamics API with the request data', async () => { - MockDynamicsWebApi.__setResponse('retrieveMultipleRequest', { + it('calls retrieveMultiple on the Dynamics API with the request data', async () => { + MockDynamicsWebApi.__setResponse('retrieveMultiple', { value: [ { '@odata.etag': 'W/"202465000"', @@ -504,7 +504,7 @@ describe('entity manager', () => { }) const result = await executeQuery(new PredefinedQuery({ root: TestEntity, filter: "strval eq 'example'" })) - expect(MockDynamicsWebApi.prototype.retrieveMultipleRequest).toBeCalledWith({ + expect(MockDynamicsWebApi.prototype.retrieveMultiple).toBeCalledWith({ collection: TestEntity.definition.dynamicsCollection, filter: "strval eq 'example'", select: TestEntity.definition.select @@ -516,7 +516,7 @@ describe('entity manager', () => { }) it('throws an error object on failure', async () => { - MockDynamicsWebApi.__throwWithErrorOn('retrieveMultipleRequest') + MockDynamicsWebApi.__throwWithErrorOn('retrieveMultiple') const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(jest.fn()) await expect(executeQuery(new PredefinedQuery({ root: TestEntity, filter: "strval eq 'example'" }))).rejects.toThrow('Test error') expect(consoleErrorSpy).toHaveBeenCalled() @@ -527,7 +527,7 @@ describe('entity manager', () => { beforeEach(async () => { MockDynamicsWebApi.__reset() MockDynamicsWebApi.__setNextResponses( - 'retrieveMultipleRequest', + 'retrieveMultiple', { value: [ { @@ -592,7 +592,7 @@ describe('entity manager', () => { }) it('throws an error object on failure', async () => { - MockDynamicsWebApi.__throwWithErrorOn('retrieveMultipleRequest') + MockDynamicsWebApi.__throwWithErrorOn('retrieveMultiple') const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(jest.fn()) await expect( executePagedQuery(new PredefinedQuery({ root: TestEntity, filter: "strval eq 'example'" }), () => {}, 1) diff --git a/packages/dynamics-lib/src/client/dynamics-client.js b/packages/dynamics-lib/src/client/dynamics-client.js index a7cae5a8ea..fa87a4b9da 100755 --- a/packages/dynamics-lib/src/client/dynamics-client.js +++ b/packages/dynamics-lib/src/client/dynamics-client.js @@ -1,4 +1,4 @@ -import DynamicsWebApi from 'dynamics-web-api' +import { DynamicsWebApi } from 'dynamics-web-api' import SimpleOAuth2 from 'simple-oauth2' const PREEMPTIVE_TOKEN_EXPIRY_SECONDS = 60 @@ -21,14 +21,16 @@ export function config () { let accessToken = null return { - webApiUrl: process.env.DYNAMICS_API_PATH, - webApiVersion: process.env.DYNAMICS_API_VERSION, + serverUrl: process.env.DYNAMICS_API_HOST, + dataApi: { + version: process.env.DYNAMICS_API_VERSION + }, timeout: process.env.DYNAMICS_API_TIMEOUT || 90000, - onTokenRefresh: async dynamicsWebApiCallback => { + onTokenRefresh: async () => { if (!accessToken || accessToken.expired(PREEMPTIVE_TOKEN_EXPIRY_SECONDS)) { accessToken = await oauthClient.getToken({ scope: process.env.OAUTH_SCOPE }) } - dynamicsWebApiCallback(accessToken.token.access_token) + return accessToken.token.access_token } } } diff --git a/packages/dynamics-lib/src/client/entity-manager.js b/packages/dynamics-lib/src/client/entity-manager.js index 8aaa47a310..6a3f1afccf 100644 --- a/packages/dynamics-lib/src/client/entity-manager.js +++ b/packages/dynamics-lib/src/client/entity-manager.js @@ -13,9 +13,9 @@ export async function persist (entities, createdBy) { dynamicsClient.startBatch() entities.forEach(entity => { if (entity.isNew()) { - dynamicsClient.createRequest(entity.toPersistRequest()) + dynamicsClient.create(entity.toPersistRequest()) } else { - dynamicsClient.updateRequest(entity.toPersistRequest()) + dynamicsClient.update(entity.toPersistRequest()) } }) return await dynamicsClient.executeBatch({ @@ -23,7 +23,7 @@ export async function persist (entities, createdBy) { }) } catch (e) { const error = e.length ? e[0] : e - const requestDetails = entities.map(entity => ({ [entity.isNew() ? 'createRequest' : 'updateRequest']: entity.toPersistRequest() })) + const requestDetails = entities.map(entity => ({ [entity.isNew() ? 'create' : 'update']: entity.toPersistRequest() })) console.error('Error persisting batch. Data: %j, Exception: %o', requestDetails, error) throw error } @@ -32,7 +32,7 @@ export async function persist (entities, createdBy) { const retrieveMultipleFetchOperation = async entityClasses => { try { dynamicsClient.startBatch() - entityClasses.forEach(cls => dynamicsClient.retrieveMultipleRequest(cls.definition.toRetrieveRequest())) + entityClasses.forEach(cls => dynamicsClient.retrieveMultiple(cls.definition.toRetrieveRequest())) return await dynamicsClient.executeBatch() } catch (e) { const error = e.length ? e[0] : e @@ -131,7 +131,7 @@ export function retrieveGlobalOptionSets () { */ export async function findById (entityType, key) { try { - const record = await dynamicsClient.retrieveRequest({ key: key, ...entityType.definition.toRetrieveRequest(null) }) + const record = await dynamicsClient.retrieve({ key: key, ...entityType.definition.toRetrieveRequest(null) }) const optionSetData = await retrieveGlobalOptionSets().cached() return entityType.fromResponse(record, optionSetData) } catch (e) { @@ -179,7 +179,7 @@ export async function findByExample (entity) { return acc }, []) ].join(' and ') - const results = await dynamicsClient.retrieveMultipleRequest(entity.constructor.definition.toRetrieveRequest(filter)) + const results = await dynamicsClient.retrieveMultiple(entity.constructor.definition.toRetrieveRequest(filter)) const optionSetData = await retrieveGlobalOptionSets().cached() return results.value.map(result => entity.constructor.fromResponse(result, optionSetData)) } catch (e) { @@ -198,7 +198,7 @@ export async function findByExample (entity) { */ export async function executeQuery (query) { try { - const response = await dynamicsClient.retrieveMultipleRequest(query.toRetrieveRequest()) + const response = await dynamicsClient.retrieveMultiple(query.toRetrieveRequest()) const optionSetData = await retrieveGlobalOptionSets().cached() return query.fromResponse(response.value, optionSetData) } catch (e) { @@ -225,7 +225,7 @@ export async function executePagedQuery (query, onPageReceived, maxPages) { const optionSetData = await retrieveGlobalOptionSets().cached() let nextLink = null do { - const response = await dynamicsClient.retrieveMultipleRequest(query.toRetrieveRequest(), nextLink) + const response = await dynamicsClient.retrieveMultiple(query.toRetrieveRequest(), nextLink) nextLink = response.oDataNextLink await onPageReceived(query.fromResponse(response.value, optionSetData)) processed += response.value.length diff --git a/packages/dynamics-lib/src/entities/base.entity.js b/packages/dynamics-lib/src/entities/base.entity.js index 56fda04e80..ff22390823 100644 --- a/packages/dynamics-lib/src/entities/base.entity.js +++ b/packages/dynamics-lib/src/entities/base.entity.js @@ -308,7 +308,7 @@ export class BaseEntity { ...(!this.isNew() && { key: this.id }), collection: this.constructor.definition.dynamicsCollection, contentId: this.uniqueContentId, - entity: this.toRequestBody() + data: this.toRequestBody() } } diff --git a/packages/dynamics-lib/src/queries/__tests__/contact.queries.spec.js b/packages/dynamics-lib/src/queries/__tests__/contact.queries.spec.js index d6aa86f6e7..e8dc055da2 100644 --- a/packages/dynamics-lib/src/queries/__tests__/contact.queries.spec.js +++ b/packages/dynamics-lib/src/queries/__tests__/contact.queries.spec.js @@ -4,11 +4,13 @@ import { Permission } from '../../entities/permission.entity.js' import { PredefinedQuery } from '../predefined-query.js' jest.mock('dynamics-web-api', () => { - return jest.fn().mockImplementation(() => { - return { - executeUnboundAction: jest.fn() - } - }) + return { + DynamicsWebApi: jest.fn().mockImplementation(() => { + return { + callAction: jest.fn() + } + }) + } }) describe('Contact Queries', () => { diff --git a/packages/fulfilment-job/package-lock.json b/packages/fulfilment-job/package-lock.json index 7ea28759f9..7f7b9c6a42 100644 --- a/packages/fulfilment-job/package-lock.json +++ b/packages/fulfilment-job/package-lock.json @@ -1173,7 +1173,7 @@ "cache-manager": "3.6.0", "cache-manager-ioredis": "2.1.0", "debug": "4.3.3", - "dynamics-web-api": "1.7.3", + "dynamics-web-api": "^2.4.0", "joi": "17.6.0", "moment": "2.29.1", "pluralize": "8.0.0", @@ -2225,13 +2225,13 @@ } }, "node_modules/dynamics-web-api": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/dynamics-web-api/-/dynamics-web-api-1.7.3.tgz", - "integrity": "sha512-ExscNNVrlXr/KoK5Sg/8GJyWndenHC26YKhnZVHaKOtAxWqsQzvveWnDl289BbFwPmwM18ZZWk8G5fFqPp981w==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/dynamics-web-api/-/dynamics-web-api-2.4.0.tgz", + "integrity": "sha512-kt4rstUaGzmP86qoognqu8DZg/0cMS+dTLAj8ys/jtFYh1UjXyAxdPhSapy3bOI9tjPo/fN6JbMgtZEXhbiXog==", "license": "MIT", "dependencies": { "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0" + "https-proxy-agent": "^5.0.1" } }, "node_modules/error-stack-parser": { diff --git a/packages/fulfilment-job/package.json b/packages/fulfilment-job/package.json index 982e92c190..d69ea6e671 100644 --- a/packages/fulfilment-job/package.json +++ b/packages/fulfilment-job/package.json @@ -39,6 +39,7 @@ "@defra-fish/dynamics-lib": "1.70.0-rc.11", "commander": "7.2.0", "debug": "4.3.3", + "dynamics-web-api": "^2.4.0", "merge2": "1.4.1", "moment": "2.29.1", "openpgp": "5.0.0-1", diff --git a/packages/fulfilment-job/src/__mocks__/dynamics-web-api.js b/packages/fulfilment-job/src/__mocks__/dynamics-web-api.js index dd4f8bd817..802a8d4c39 100644 --- a/packages/fulfilment-job/src/__mocks__/dynamics-web-api.js +++ b/packages/fulfilment-job/src/__mocks__/dynamics-web-api.js @@ -1,3 +1,5 @@ import { configureDynamicsWebApiMock } from '../../../dynamics-lib/src/__mocks__/dynamics-web-api-mock-helper.js' -const DynamicsWebApi = jest.genMockFromModule('dynamics-web-api') -export default configureDynamicsWebApiMock(DynamicsWebApi) +const DynamicsWebApi = jest.fn() +DynamicsWebApi.prototype = {} +configureDynamicsWebApiMock(DynamicsWebApi) +export { DynamicsWebApi } diff --git a/packages/sales-api-service/package-lock.json b/packages/sales-api-service/package-lock.json index 47a58d2199..1b388cdfee 100644 --- a/packages/sales-api-service/package-lock.json +++ b/packages/sales-api-service/package-lock.json @@ -1221,7 +1221,7 @@ "cache-manager": "3.6.0", "cache-manager-ioredis": "2.1.0", "debug": "4.3.3", - "dynamics-web-api": "1.7.3", + "dynamics-web-api": "^2.4.0", "joi": "17.6.0", "moment": "2.29.1", "pluralize": "8.0.0", @@ -2584,13 +2584,13 @@ } }, "node_modules/dynamics-web-api": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/dynamics-web-api/-/dynamics-web-api-1.7.3.tgz", - "integrity": "sha512-ExscNNVrlXr/KoK5Sg/8GJyWndenHC26YKhnZVHaKOtAxWqsQzvveWnDl289BbFwPmwM18ZZWk8G5fFqPp981w==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/dynamics-web-api/-/dynamics-web-api-2.4.0.tgz", + "integrity": "sha512-kt4rstUaGzmP86qoognqu8DZg/0cMS+dTLAj8ys/jtFYh1UjXyAxdPhSapy3bOI9tjPo/fN6JbMgtZEXhbiXog==", "license": "MIT", "dependencies": { "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0" + "https-proxy-agent": "^5.0.1" } }, "node_modules/error-stack-parser": { diff --git a/packages/sales-api-service/package.json b/packages/sales-api-service/package.json index 7e4d38cfe7..681c768f45 100644 --- a/packages/sales-api-service/package.json +++ b/packages/sales-api-service/package.json @@ -44,6 +44,7 @@ "@hapi/vision": "6.1.0", "debug": "4.3.3", "dot-prop": "6.0.1", + "dynamics-web-api": "^2.4.0", "hapi-and-healthy": "7.0.7", "hapi-swagger": "14.2.5", "ioredis": "4.28.5", diff --git a/packages/sales-api-service/src/__mocks__/dynamics-web-api.js b/packages/sales-api-service/src/__mocks__/dynamics-web-api.js index dd4f8bd817..802a8d4c39 100644 --- a/packages/sales-api-service/src/__mocks__/dynamics-web-api.js +++ b/packages/sales-api-service/src/__mocks__/dynamics-web-api.js @@ -1,3 +1,5 @@ import { configureDynamicsWebApiMock } from '../../../dynamics-lib/src/__mocks__/dynamics-web-api-mock-helper.js' -const DynamicsWebApi = jest.genMockFromModule('dynamics-web-api') -export default configureDynamicsWebApiMock(DynamicsWebApi) +const DynamicsWebApi = jest.fn() +DynamicsWebApi.prototype = {} +configureDynamicsWebApiMock(DynamicsWebApi) +export { DynamicsWebApi } diff --git a/packages/sales-api-service/src/server/plugins/__tests__/health.spec.js b/packages/sales-api-service/src/server/plugins/__tests__/health.spec.js index eb1b8a2178..414ce1208b 100644 --- a/packages/sales-api-service/src/server/plugins/__tests__/health.spec.js +++ b/packages/sales-api-service/src/server/plugins/__tests__/health.spec.js @@ -84,7 +84,7 @@ describe('hapi healthcheck', () => { }) it('exposes a service status page returning a 500 error when unhealthy', async () => { - jest.spyOn(dynamicsClient, 'executeUnboundFunction').mockImplementation(async () => { + jest.spyOn(dynamicsClient, 'callFunction').mockImplementation(async () => { throw new Error('Simulated') }) const result = await server.inject({ method: 'GET', url: '/service-status' }) diff --git a/packages/sales-api-service/src/server/plugins/health.js b/packages/sales-api-service/src/server/plugins/health.js index e89019993e..5a0488ef04 100644 --- a/packages/sales-api-service/src/server/plugins/health.js +++ b/packages/sales-api-service/src/server/plugins/health.js @@ -19,7 +19,7 @@ export default { test: { node: [ async () => { - return { connection: 'dynamics', status: 'ok', ...(await dynamicsClient.executeUnboundFunction('RetrieveVersion')) } + return { connection: 'dynamics', status: 'ok', ...(await dynamicsClient.callFunction('RetrieveVersion')) } }, async () => { return { connection: 'dynamodb', status: 'ok', ...(await ddb.listTables()) } diff --git a/packages/sales-api-service/src/services/__tests__/recurring-payments.service.spec.js b/packages/sales-api-service/src/services/__tests__/recurring-payments.service.spec.js index f6e6f8e797..3551a0afb6 100644 --- a/packages/sales-api-service/src/services/__tests__/recurring-payments.service.spec.js +++ b/packages/sales-api-service/src/services/__tests__/recurring-payments.service.spec.js @@ -52,7 +52,7 @@ jest.mock('@defra-fish/dynamics-lib', () => ({ findDueRecurringPayments: jest.fn(), findRecurringPaymentsByAgreementId: jest.fn(() => ({ toRetrieveRequest: () => {} })), dynamicsClient: { - retrieveMultipleRequest: jest.fn(() => ({ value: [] })) + retrieveMultiple: jest.fn(() => ({ value: [] })) }, persist: jest.fn(), findRecurringPaymentByPermissionId: jest.fn(() => ({ toRetrieveRequest: () => {} })), @@ -780,16 +780,16 @@ describe('recurring payments service', () => { expect(findRecurringPaymentsByAgreementId).toHaveBeenCalledWith(agreementId) }) - it('passes query created by findRecurringPaymentsByAgreementId to retrieveMultipleRequest', async () => { + it('passes query created by findRecurringPaymentsByAgreementId to retrieveMultiple', async () => { const retrieveRequest = Symbol('retrieve request') findRecurringPaymentsByAgreementId.mockReturnValueOnce({ toRetrieveRequest: () => retrieveRequest }) await findNewestExistingRecurringPaymentInCrm() - expect(dynamicsClient.retrieveMultipleRequest).toHaveBeenCalledWith(retrieveRequest) + expect(dynamicsClient.retrieveMultiple).toHaveBeenCalledWith(retrieveRequest) }) it('returns a Recurring Payment (not a plain object)', async () => { jest.spyOn(RecurringPayment, 'fromResponse') - dynamicsClient.retrieveMultipleRequest.mockReturnValueOnce(getMockResponse()) + dynamicsClient.retrieveMultiple.mockReturnValueOnce(getMockResponse()) const recurringPayment = await findNewestExistingRecurringPaymentInCrm() expect(RecurringPayment.fromResponse.mock.results[0].value).toBe(recurringPayment) }) @@ -824,13 +824,13 @@ describe('recurring payments service', () => { '908-oid' ] ])('returns most recent existing recurring payment from %s', async (_desc, mockResponseData, expectedId) => { - dynamicsClient.retrieveMultipleRequest.mockReturnValueOnce({ value: mockResponseData }) + dynamicsClient.retrieveMultiple.mockReturnValueOnce({ value: mockResponseData }) const recurringPayment = await findNewestExistingRecurringPaymentInCrm() expect(recurringPayment.id).toBe(expectedId) }) it('returns boolean false if no recurring payments found', async () => { - dynamicsClient.retrieveMultipleRequest.mockReturnValueOnce({ value: [] }) + dynamicsClient.retrieveMultiple.mockReturnValueOnce({ value: [] }) const recurringPayment = await findNewestExistingRecurringPaymentInCrm() expect(recurringPayment).toBeFalsy() }) @@ -987,7 +987,7 @@ describe('recurring payments service', () => { describe('findLinkedRecurringPayment', () => { const arrangeLinkedRcpSuccess = mockResponse => { jest.spyOn(RecurringPayment, 'fromResponse') - dynamicsClient.retrieveMultipleRequest.mockReturnValueOnce(mockResponse) + dynamicsClient.retrieveMultiple.mockReturnValueOnce(mockResponse) retrieveGlobalOptionSets.mockReturnValueOnce({ cached: jest.fn().mockResolvedValue({ definition: 'mock-def' }) }) @@ -999,11 +999,11 @@ describe('recurring payments service', () => { expect(findRecurringPaymentByPermissionId).toHaveBeenCalledWith(permissionId) }) - it('passes query created by findRecurringPaymentByPermissionId to retrieveMultipleRequest', async () => { + it('passes query created by findRecurringPaymentByPermissionId to retrieveMultiple', async () => { const retrieveRequest = Symbol('retrieve request') findRecurringPaymentByPermissionId.mockReturnValueOnce({ toRetrieveRequest: () => retrieveRequest }) await findLinkedRecurringPayment() - expect(dynamicsClient.retrieveMultipleRequest).toHaveBeenCalledWith(retrieveRequest) + expect(dynamicsClient.retrieveMultiple).toHaveBeenCalledWith(retrieveRequest) }) it('calls RecurringPayment.fromResponse with response and definitions', async () => { @@ -1037,7 +1037,7 @@ describe('recurring payments service', () => { 'rcp-456' ] ])('returns the most recent linked recurring payment (%s)', async (_desc, mockData, expectedId) => { - dynamicsClient.retrieveMultipleRequest.mockReturnValueOnce({ value: mockData }) + dynamicsClient.retrieveMultiple.mockReturnValueOnce({ value: mockData }) retrieveGlobalOptionSets.mockReturnValueOnce({ cached: jest.fn().mockResolvedValue({ def: 'mock' }) }) const recurringPayment = await findLinkedRecurringPayment('abc123') @@ -1045,7 +1045,7 @@ describe('recurring payments service', () => { }) it('returns false if no linked recurring payments found', async () => { - dynamicsClient.retrieveMultipleRequest.mockReturnValueOnce({ value: [] }) + dynamicsClient.retrieveMultiple.mockReturnValueOnce({ value: [] }) const recurringPayment = await findLinkedRecurringPayment('abc123') expect(recurringPayment).toBeFalsy() }) diff --git a/packages/sales-api-service/src/services/__tests__/reference-data.service.spec.js b/packages/sales-api-service/src/services/__tests__/reference-data.service.spec.js index 33252fb030..5faf0d5039 100644 --- a/packages/sales-api-service/src/services/__tests__/reference-data.service.spec.js +++ b/packages/sales-api-service/src/services/__tests__/reference-data.service.spec.js @@ -12,7 +12,7 @@ import { MOCK_1DAY_SENIOR_PERMIT_DYNAMICS_RESPONSE, MOCK_CONCESSION_DYNAMICS_RESPONSE } from '../../__mocks__/test-data.js' -import dynamicsWebApi from 'dynamics-web-api' +import { DynamicsWebApi } from 'dynamics-web-api' const getOptionSetMappingExpectation = (name, ...keys) => { const options = keys.reduce((acc, k) => { @@ -32,8 +32,8 @@ const getOptionSetMappingExpectation = (name, ...keys) => { describe('reference-data service', () => { beforeAll(async () => { - dynamicsWebApi.__reset() - dynamicsWebApi.__setResponse('executeBatch', [ + DynamicsWebApi.__reset() + DynamicsWebApi.__setResponse('executeBatch', [ { value: [MOCK_12MONTH_SENIOR_PERMIT_DYNAMICS_RESPONSE, MOCK_1DAY_SENIOR_PERMIT_DYNAMICS_RESPONSE] }, @@ -50,12 +50,12 @@ describe('reference-data service', () => { permits: expect.arrayContaining([expect.any(Permit)]), concessions: expect.arrayContaining([expect.any(Concession)]) }) - expect(dynamicsWebApi.prototype.executeBatch).toHaveBeenCalledTimes(1) + expect(DynamicsWebApi.prototype.executeBatch).toHaveBeenCalledTimes(1) }) it('uses a cache', async () => { await getReferenceData() await getReferenceData() - expect(dynamicsWebApi.prototype.executeBatch).toHaveBeenCalledTimes(1) + expect(DynamicsWebApi.prototype.executeBatch).toHaveBeenCalledTimes(1) }) }) @@ -63,7 +63,7 @@ describe('reference-data service', () => { it('retrieves an entries for the given type', async () => { const result = await getReferenceDataForEntity(Permit) expect(result).toEqual(expect.arrayContaining([expect.any(Permit)])) - expect(dynamicsWebApi.prototype.executeBatch).toHaveBeenCalledTimes(1) + expect(DynamicsWebApi.prototype.executeBatch).toHaveBeenCalledTimes(1) }) }) @@ -71,12 +71,12 @@ describe('reference-data service', () => { it('retrieves an entry for a given id', async () => { const result = await getReferenceDataForEntityAndId(Permit, MOCK_12MONTH_SENIOR_PERMIT_DYNAMICS_RESPONSE.defra_permitid) expect(result).toBeInstanceOf(Permit) - expect(dynamicsWebApi.prototype.executeBatch).toHaveBeenCalledTimes(1) + expect(DynamicsWebApi.prototype.executeBatch).toHaveBeenCalledTimes(1) }) it('returns undefined if not found', async () => { const result = await getReferenceDataForEntityAndId(Permit, 'not-found') expect(result).toBe(undefined) - expect(dynamicsWebApi.prototype.executeBatch).toHaveBeenCalledTimes(1) + expect(DynamicsWebApi.prototype.executeBatch).toHaveBeenCalledTimes(1) }) }) @@ -89,7 +89,7 @@ describe('reference-data service', () => { defra_concessionproof: getOptionSetMappingExpectation('defra_concessionproof', 910400000, 910400001, 910400002, 910400003) }) ) - expect(dynamicsWebApi.prototype.retrieveGlobalOptionSets).toHaveBeenCalledTimes(1) + expect(DynamicsWebApi.prototype.retrieveGlobalOptionSets).toHaveBeenCalledTimes(1) }) }) @@ -97,12 +97,12 @@ describe('reference-data service', () => { it('retrieves all option-sets for a single name', async () => { const result = await getGlobalOptionSet('defra_duration') expect(result).toMatchObject(getOptionSetMappingExpectation('defra_duration', 910400000, 910400001, 910400002, 910400003)) - expect(dynamicsWebApi.prototype.retrieveGlobalOptionSets).toHaveBeenCalledTimes(1) + expect(DynamicsWebApi.prototype.retrieveGlobalOptionSets).toHaveBeenCalledTimes(1) }) it('returns undefined if not found', async () => { const result = await getGlobalOptionSet('not-found') expect(result).toBe(undefined) - expect(dynamicsWebApi.prototype.retrieveGlobalOptionSets).toHaveBeenCalledTimes(1) + expect(DynamicsWebApi.prototype.retrieveGlobalOptionSets).toHaveBeenCalledTimes(1) }) }) @@ -110,17 +110,17 @@ describe('reference-data service', () => { it('retrieves a single option-set for a single name and label', async () => { const result = await getGlobalOptionSetValue('defra_duration', '1 day') expect(result).toMatchObject({ id: 910400000, label: '1 day', description: '1 day' }) - expect(dynamicsWebApi.prototype.retrieveGlobalOptionSets).toHaveBeenCalledTimes(1) + expect(DynamicsWebApi.prototype.retrieveGlobalOptionSets).toHaveBeenCalledTimes(1) }) it('returns undefined if the option-set label is not found', async () => { const result = await getGlobalOptionSetValue('defra_duration', 'not-found') expect(result).toBe(undefined) - expect(dynamicsWebApi.prototype.retrieveGlobalOptionSets).toHaveBeenCalledTimes(1) + expect(DynamicsWebApi.prototype.retrieveGlobalOptionSets).toHaveBeenCalledTimes(1) }) it('returns undefined if the option-set name is not found', async () => { const result = await getGlobalOptionSetValue('not-found', 'not-found') expect(result).toBe(undefined) - expect(dynamicsWebApi.prototype.retrieveGlobalOptionSets).toHaveBeenCalledTimes(1) + expect(DynamicsWebApi.prototype.retrieveGlobalOptionSets).toHaveBeenCalledTimes(1) }) }) }) diff --git a/packages/sales-api-service/src/services/recurring-payments.service.js b/packages/sales-api-service/src/services/recurring-payments.service.js index 83003db82a..1f3db76df1 100644 --- a/packages/sales-api-service/src/services/recurring-payments.service.js +++ b/packages/sales-api-service/src/services/recurring-payments.service.js @@ -158,7 +158,7 @@ export const processRPResult = async (transactionId, paymentId, createdDate) => export const findNewestExistingRecurringPaymentInCrm = async agreementId => { const query = findRecurringPaymentsByAgreementId(agreementId) - const response = await dynamicsClient.retrieveMultipleRequest(query.toRetrieveRequest()) + const response = await dynamicsClient.retrieveMultiple(query.toRetrieveRequest()) if (response.value.length) { const [rcpResponseData] = response.value.sort((a, b) => Date.parse(b.defra_enddate) - Date.parse(a.defra_enddate)) return RecurringPayment.fromResponse(rcpResponseData) @@ -192,7 +192,7 @@ const determineRecurringPaymentName = (transactionRecord, contact) => { export const findLinkedRecurringPayment = async permissionId => { const query = findRecurringPaymentByPermissionId(permissionId) - const response = await dynamicsClient.retrieveMultipleRequest(query.toRetrieveRequest()) + const response = await dynamicsClient.retrieveMultiple(query.toRetrieveRequest()) if (response.value.length) { const [rcpResponseData] = response.value.sort((a, b) => Date.parse(b.defra_enddate) - Date.parse(a.defra_enddate)) const definition = await retrieveGlobalOptionSets().cached()