From 837a48254d14c6369f1f394aeb2d0646bdeb2ed9 Mon Sep 17 00:00:00 2001 From: Audrius Vaitonis Date: Mon, 15 Apr 2024 10:25:00 +0100 Subject: [PATCH] feat(DTFS2-7052): tests for ordnance survey API endpoint --- .../geospatial/geospatial.controller.test.ts | 62 +++++++++++++++++ .../geospatial/geospatial.controller.ts | 7 +- .../geospatial/geospatial.service.test.ts | 67 +++++++++++++++++++ src/modules/geospatial/geospatial.service.ts | 2 +- .../get-docs-yaml.api-test.ts.snap | 11 ++- .../get-address-by-postcode.api-test.ts | 7 +- .../get-geospatial-addresses-generator.ts | 12 ++-- 7 files changed, 150 insertions(+), 18 deletions(-) create mode 100644 src/modules/geospatial/geospatial.controller.test.ts create mode 100644 src/modules/geospatial/geospatial.service.test.ts diff --git a/src/modules/geospatial/geospatial.controller.test.ts b/src/modules/geospatial/geospatial.controller.test.ts new file mode 100644 index 00000000..d60c0a83 --- /dev/null +++ b/src/modules/geospatial/geospatial.controller.test.ts @@ -0,0 +1,62 @@ +import { GEOSPATIAL } from '@ukef/constants'; +import { GetGeospatialAddressesGenerator } from '@ukef-test/support/generator/get-geospatial-addresses-generator'; +import { RandomValueGenerator } from '@ukef-test/support/generator/random-value-generator'; +import { resetAllWhenMocks, when } from 'jest-when'; + +import { GeospatialController } from './geospatial.controller'; +import { GeospatialService } from './geospatial.service'; + +describe('GeospatialController', () => { + let geospatialServiceGetAddressesByPostcode: jest.Mock; + + let controller: GeospatialController; + + const valueGenerator = new RandomValueGenerator(); + const { getAddressByPostcodeResponse, getAddressByPostcodeMultipleResponse } = new GetGeospatialAddressesGenerator(valueGenerator).generate({ + numberToGenerate: 2, + }); + + beforeEach(() => { + resetAllWhenMocks(); + const geospatialService = new GeospatialService(null); + geospatialServiceGetAddressesByPostcode = jest.fn(); + geospatialService.getAddressesByPostcode = geospatialServiceGetAddressesByPostcode; + + controller = new GeospatialController(geospatialService); + }); + + it('should be defined', () => { + expect(GeospatialController).toBeDefined(); + }); + + describe('getAddressesByPostcode()', () => { + const postcode = GEOSPATIAL.EXAMPLES.POSTCODE; + + it('returns address for postcode', async () => { + when(geospatialServiceGetAddressesByPostcode).calledWith(postcode).mockResolvedValueOnce(getAddressByPostcodeResponse[0]); + + const response = await controller.getAddressesByPostcode({ postcode }); + + expect(geospatialServiceGetAddressesByPostcode).toHaveBeenCalled(); + expect(response).toEqual(getAddressByPostcodeResponse[0]); + }); + + it('returns multiple addressess for postcode', async () => { + when(geospatialServiceGetAddressesByPostcode).calledWith(postcode).mockResolvedValueOnce(getAddressByPostcodeMultipleResponse); + + const response = await controller.getAddressesByPostcode({ postcode }); + + expect(geospatialServiceGetAddressesByPostcode).toHaveBeenCalled(); + expect(response).toEqual(getAddressByPostcodeMultipleResponse); + }); + + it('returns empty response for postcode', async () => { + when(geospatialServiceGetAddressesByPostcode).calledWith(postcode).mockResolvedValueOnce([]); + + const response = await controller.getAddressesByPostcode({ postcode }); + + expect(geospatialServiceGetAddressesByPostcode).toHaveBeenCalled(); + expect(response).toEqual([]); + }); + }); +}); diff --git a/src/modules/geospatial/geospatial.controller.ts b/src/modules/geospatial/geospatial.controller.ts index 4d1580b7..50486d98 100644 --- a/src/modules/geospatial/geospatial.controller.ts +++ b/src/modules/geospatial/geospatial.controller.ts @@ -12,17 +12,18 @@ export class GeospatialController { @Get('addresses/postcode') @ApiOperation({ - summary: "A search based on a property's postcode. Will accept a full postcode consisting of the area, district, sector and unit e.g. SO16 0AS.", + summary: + "A search based on a property's postcode. Will accept a full valid postcode. Returns addresses from Ordanance survey Delivery Point Address (DPA) system.", }) @ApiResponse({ status: 200, - description: 'Returns addresses from Ordanance survey Delivery Point Address (DPA) system.', + description: 'Returns simplified addresses that are ready to show to users.', type: [GetAddressesResponseItem], }) @ApiNotFoundResponse({ description: 'Customer not found.', }) - getGeospatial(@Query() query: GetAddressByPostcodeQueryDto): Promise { + getAddressesByPostcode(@Query() query: GetAddressByPostcodeQueryDto): Promise { return this.geospatialService.getAddressesByPostcode(query.postcode); } } diff --git a/src/modules/geospatial/geospatial.service.test.ts b/src/modules/geospatial/geospatial.service.test.ts new file mode 100644 index 00000000..ec3165dd --- /dev/null +++ b/src/modules/geospatial/geospatial.service.test.ts @@ -0,0 +1,67 @@ +import { ConfigService } from '@nestjs/config'; +import { OrdnanceSurveyService } from '@ukef/helper-modules/ordnance-survey/ordnance-survey.service'; +import { GetGeospatialAddressesGenerator } from '@ukef-test/support/generator/get-geospatial-addresses-generator'; +import { RandomValueGenerator } from '@ukef-test/support/generator/random-value-generator'; +import { resetAllWhenMocks, when } from 'jest-when'; + +import { GeospatialService } from './geospatial.service'; + +jest.mock('@ukef/modules/informatica/informatica.service'); + +describe('CustomerService', () => { + const valueGenerator = new RandomValueGenerator(); + + let service: GeospatialService; + let configServiceGet: jest.Mock; + let informaticaServiceGetAddressesByPostcode: jest.Mock; + + beforeEach(() => { + const configService = new ConfigService(); + configServiceGet = jest.fn().mockReturnValue({ key: valueGenerator.word() }); + configService.get = configServiceGet; + + informaticaServiceGetAddressesByPostcode = jest.fn(); + const ordnanceSurveyService = new OrdnanceSurveyService(null, configService); + ordnanceSurveyService.getAddressesByPostcode = informaticaServiceGetAddressesByPostcode; + resetAllWhenMocks(); + + service = new GeospatialService(ordnanceSurveyService); + }); + + describe('getAddressesByPostcode', () => { + const { + getAddressByPostcodeResponse, + getAddressByPostcodeMultipleResponse, + getAddressOrdnanceSurveyResponse, + getAddressOrdnanceSurveyMultipleResponse, + getAddressOrdnanceSurveyEmptyResponse, + } = new GetGeospatialAddressesGenerator(valueGenerator).generate({ + numberToGenerate: 2, + }); + const postcode = getAddressByPostcodeResponse[0][0].postalCode; + + it('returns address from the backend service', async () => { + when(informaticaServiceGetAddressesByPostcode).calledWith(postcode).mockResolvedValueOnce(getAddressOrdnanceSurveyResponse[0]); + + const response = await service.getAddressesByPostcode(postcode); + + expect(response).toEqual(getAddressByPostcodeResponse[0]); + }); + + it('returns multiple addressess from the backend service', async () => { + when(informaticaServiceGetAddressesByPostcode).calledWith(postcode).mockResolvedValueOnce(getAddressOrdnanceSurveyMultipleResponse); + + const response = await service.getAddressesByPostcode(postcode); + + expect(response).toEqual(getAddressByPostcodeMultipleResponse); + }); + + it('can handle empty backend response', async () => { + when(informaticaServiceGetAddressesByPostcode).calledWith(postcode).mockResolvedValueOnce(getAddressOrdnanceSurveyEmptyResponse[0]); + + const response = await service.getAddressesByPostcode(postcode); + + expect(response).toEqual([]); + }); + }); +}); diff --git a/src/modules/geospatial/geospatial.service.ts b/src/modules/geospatial/geospatial.service.ts index e1cf93df..b3cb515d 100644 --- a/src/modules/geospatial/geospatial.service.ts +++ b/src/modules/geospatial/geospatial.service.ts @@ -27,7 +27,7 @@ export class GeospatialService { addressLine3: null, locality: item_data.POST_TOWN || null, postalCode: item_data.POSTCODE || null, - country: ENUMS.GEOSPATIAL_COUNTRIES[item_data.COUNTRY_CODE], + country: ENUMS.GEOSPATIAL_COUNTRIES[item_data.COUNTRY_CODE] || null, }); }); diff --git a/test/docs/__snapshots__/get-docs-yaml.api-test.ts.snap b/test/docs/__snapshots__/get-docs-yaml.api-test.ts.snap index 77af87e5..b71b8f1e 100644 --- a/test/docs/__snapshots__/get-docs-yaml.api-test.ts.snap +++ b/test/docs/__snapshots__/get-docs-yaml.api-test.ts.snap @@ -488,10 +488,11 @@ paths: - yield-rates /api/v1/geospatial/addresses/postcode: get: - operationId: GeospatialController_getGeospatial + operationId: GeospatialController_getAddressesByPostcode summary: >- - A search based on a property's postcode. Will accept a full postcode - consisting of the area, district, sector and unit e.g. SO16 0AS. + A search based on a property's postcode. Will accept a full valid + postcode. Returns addresses from Ordanance survey Delivery Point Address + (DPA) system. parameters: - name: postcode required: true @@ -502,9 +503,7 @@ paths: type: string responses: '200': - description: >- - Returns addresses from Ordanance survey Delivery Point Address (DPA) - system. + description: Returns simplified addresses that are ready to show to users. content: application/json: schema: diff --git a/test/geospatial/get-address-by-postcode.api-test.ts b/test/geospatial/get-address-by-postcode.api-test.ts index 770ef319..64f0283b 100644 --- a/test/geospatial/get-address-by-postcode.api-test.ts +++ b/test/geospatial/get-address-by-postcode.api-test.ts @@ -15,9 +15,10 @@ describe('GET /geospatial/addresses/postcode?postcode=', () => { ordnanceSurveyPath, mdmPath, getAddressByPostcodeResponse, + getAddressByPostcodeMultipleResponse, getAddressOrdnanceSurveyResponse, getAddressOrdnanceSurveyEmptyResponse, - getAddressessOrdnanceSurveyResponse, + getAddressOrdnanceSurveyMultipleResponse, ordnanceSurveyAuthErrorResponse, } = new GetGeospatialAddressesGenerator(valueGenerator).generate({ postcode: GEOSPATIAL.EXAMPLES.POSTCODE, @@ -58,12 +59,12 @@ describe('GET /geospatial/addresses/postcode?postcode=', () => { }); it('returns a 200 response with the addresses if they are returned by Ordnance Survey API', async () => { - requestToGetAddressesByPostcode(ordnanceSurveyPath[0]).reply(200, getAddressessOrdnanceSurveyResponse); + requestToGetAddressesByPostcode(ordnanceSurveyPath[0]).reply(200, getAddressOrdnanceSurveyMultipleResponse); const { status, body } = await api.get(mdmPath[0]); expect(status).toBe(200); - expect(body).toStrictEqual([getAddressByPostcodeResponse[0][0], getAddressByPostcodeResponse[1][0]]); + expect(body).toStrictEqual(getAddressByPostcodeMultipleResponse); }); it('returns a empty 200 response if Ordnance Survey API returns a 200 without results', async () => { diff --git a/test/support/generator/get-geospatial-addresses-generator.ts b/test/support/generator/get-geospatial-addresses-generator.ts index efabd55c..69320761 100644 --- a/test/support/generator/get-geospatial-addresses-generator.ts +++ b/test/support/generator/get-geospatial-addresses-generator.ts @@ -52,6 +52,8 @@ export class GetGeospatialAddressesGenerator extends AbstractGenerator response[0]); + const getAddressOrdnanceSurveyResponse: GetAddressOrdnanceSurveyResponse[] = values.map((v) => ({ header: { uri: 'test', @@ -107,7 +109,7 @@ export class GetGeospatialAddressesGenerator extends AbstractGenerator