From 3bd2dc37494a6d4e06b2023000fdd601e48c6229 Mon Sep 17 00:00:00 2001 From: harvey-dvla <162578903+harvey-dvla@users.noreply.github.com> Date: Tue, 26 Mar 2024 15:20:10 +0000 Subject: [PATCH] code changes to align behaviour of this module with postman-paf-java (java implementation) --- src/__test__/addressConversion.test.js | 81 +++++++++++++++++-- src/addressConversion.js | 3 +- src/conversion-rules/__test__/fixtures.js | 27 +++++++ .../__test__/ruleConversions.test.js | 40 +++++++++ .../__test__/ruleConversionsHelper.test.js | 56 ------------- src/conversion-rules/ruleConversions.js | 26 ++++++ src/conversion-rules/ruleConversionsHelper.js | 32 ++++++-- 7 files changed, 194 insertions(+), 71 deletions(-) diff --git a/src/__test__/addressConversion.test.js b/src/__test__/addressConversion.test.js index 61a4379..a80acbf 100644 --- a/src/__test__/addressConversion.test.js +++ b/src/__test__/addressConversion.test.js @@ -149,21 +149,86 @@ describe('convertStructuredToUnstructured', () => { }); }); - it('throws error when unable to apply rules', () => { + it('converts structuredAddress when no rules apply thoroughfareName', () => { // Given const structuredAddress = { + thoroughfareName: structuredAddressTemplate.thoroughfareName, + ...postTownAndPostcode, + }; + + // When + const convertedUnstructuredAddress = convertStructuredToUnstructured(structuredAddress); + + // Then + expect(convertedUnstructuredAddress).toEqual({ + line1: structuredAddress.thoroughfareName, + ...line5AndPostcode, + }); + }); + + it('converts structuredAddress when no rules apply dependant thoroughfareName', () => { + // Given + const structuredAddress = { + dependentThoroughfareName: structuredAddressTemplate.dependentThoroughfareName, + ...postTownAndPostcode, + }; + + // When + const convertedUnstructuredAddress = convertStructuredToUnstructured(structuredAddress); + + // Then + expect(convertedUnstructuredAddress).toEqual({ + line1: structuredAddress.dependentThoroughfareName, + ...line5AndPostcode, + }); + }); + + it('converts structuredAddress when no rules apply dependant doubleDependentLocality', () => { + // Given + const structuredAddress = { + doubleDependentLocality: structuredAddressTemplate.doubleDependentLocality, + ...postTownAndPostcode, + }; + + // When + const convertedUnstructuredAddress = convertStructuredToUnstructured(structuredAddress); + + // Then + expect(convertedUnstructuredAddress).toEqual({ + line1: structuredAddress.doubleDependentLocality, + ...line5AndPostcode, + }); + }); + + it('converts structuredAddress when no rules apply dependant dependentLocality', () => { + // Given + const structuredAddress = { + dependentLocality: structuredAddressTemplate.dependentLocality, ...postTownAndPostcode, }; // When - let error; - try { - convertStructuredToUnstructured(structuredAddress); - } catch (err) { - error = err; - } + const convertedUnstructuredAddress = convertStructuredToUnstructured(structuredAddress); // Then - expect(error.message).toEqual('Structured address did not match any of the conversion rules'); + expect(convertedUnstructuredAddress).toEqual({ + line1: structuredAddress.dependentLocality, + ...line5AndPostcode, + }); + }); + + it('returns posttown and postcode correctly when only postcode and postTown supplied', () => { + // Given + const structuredAddress = { + ...postTownAndPostcode, + }; + + // When + const convertedUnstructuredAddress = convertStructuredToUnstructured(structuredAddress); + + // Then + expect(convertedUnstructuredAddress).toEqual({ + ...line5AndPostcode, + }); }); }); diff --git a/src/addressConversion.js b/src/addressConversion.js index 7955879..ee1c1cc 100644 --- a/src/addressConversion.js +++ b/src/addressConversion.js @@ -7,6 +7,7 @@ const { convertRule5StructuredToUnstructured, convertRule6StructuredToUnstructured, convertRule7StructuredToUnstructured, + convertNoRuleApplicableStructuredToUnstructured, } = require('./conversion-rules/ruleConversions'); /** @@ -41,7 +42,7 @@ const convertStructuredToUnstructured = (structuredAddress) => { return convertRule7StructuredToUnstructured(structuredAddress); } - throw new Error('Structured address did not match any of the conversion rules'); + return convertNoRuleApplicableStructuredToUnstructured(structuredAddress); }; module.exports = { diff --git a/src/conversion-rules/__test__/fixtures.js b/src/conversion-rules/__test__/fixtures.js index 8fa8da6..a9d2448 100644 --- a/src/conversion-rules/__test__/fixtures.js +++ b/src/conversion-rules/__test__/fixtures.js @@ -13,6 +13,31 @@ const structuredAddressTemplate = { postcode: 'AC1 2DC', }; +const structuredAddressNoPostcodeOrPosttownTemplate = { + organisationName: 'BUSY BUSINESS', + departmentName: 'DEPARTMENT OF DEFENCE AGAINST FAILED TESTS', + poBoxNumber: '12345', + buildingName: 'BOB', + buildingNumber: '1', + subBuildingName: 'FLAT 1', + thoroughfareName: 'DRIVE-THROUGH THOROUGHFARE', + dependentThoroughfareName: '"IT DEPENDS..." ROAD', + dependentLocality: 'NOWHERE', + doubleDependentLocality: 'TWICE NOWHERE IS STILL NOWHERE...', + postTown: '', + postcode: '', +}; + +const structuredAddressBuildingNumberAndPoBoxNumberAreNumbersTemplate = { + poBoxNumber: 12345, + buildingNumber: 5, + thoroughfareName: 'DRIVE-THROUGH THOROUGHFARE', + dependentLocality: 'NOWHERE', + doubleDependentLocality: 'TWICE NOWHERE IS STILL NOWHERE...', + postTown: 'A TOWN FULL OF MAIL', + postcode: 'AC1 2DC', +}; + const internationalAddressTemplate = { line1: 'El Quinto Pino line1', line2: 'El Quinto Pino line2', @@ -59,6 +84,8 @@ const numericPartExceptionElements = { module.exports = { structuredAddressTemplate, + structuredAddressNoPostcodeOrPosttownTemplate, + structuredAddressBuildingNumberAndPoBoxNumberAreNumbersTemplate, internationalAddressTemplate, bfpoAddressTemplate, postTownAndPostcode, diff --git a/src/conversion-rules/__test__/ruleConversions.test.js b/src/conversion-rules/__test__/ruleConversions.test.js index d1d640b..b739a0f 100644 --- a/src/conversion-rules/__test__/ruleConversions.test.js +++ b/src/conversion-rules/__test__/ruleConversions.test.js @@ -6,6 +6,7 @@ const { convertRule5StructuredToUnstructured, convertRule6StructuredToUnstructured, convertRule7StructuredToUnstructured, + convertNoRuleApplicableStructuredToUnstructured, } = require('../ruleConversions'); const { structuredAddressTemplate, @@ -1138,4 +1139,43 @@ describe('convertRule7StructuredToUnstructured', () => { ...line5AndPostcode, }); }); + + it('add address elements to line 1 and 2 when building number present', () => { + // Given + const structuredAddress = { + departmentName: structuredAddressTemplate.departmentName, + buildingNumber: structuredAddressTemplate.buildingNumber, + ...postTownAndPostcode, + }; + + // When + const convertedUnstructuredAddress = convertNoRuleApplicableStructuredToUnstructured(structuredAddress); + + // Then + expect(convertedUnstructuredAddress).toEqual({ + line1: structuredAddressTemplate.departmentName, + line2: structuredAddressTemplate.buildingNumber, + ...line5AndPostcode, + }); + }); + + it('add address elements to line 1 and 2 when building number not present', () => { + // Given + const structuredAddress = { + departmentName: structuredAddressTemplate.departmentName, + thoroughfareName: structuredAddressTemplate.thoroughfareName, + + ...postTownAndPostcode, + }; + + // When + const convertedUnstructuredAddress = convertNoRuleApplicableStructuredToUnstructured(structuredAddress); + + // Then + expect(convertedUnstructuredAddress).toEqual({ + line1: structuredAddressTemplate.departmentName, + line2: structuredAddressTemplate.thoroughfareName, + ...line5AndPostcode, + }); + }); }); diff --git a/src/conversion-rules/__test__/ruleConversionsHelper.test.js b/src/conversion-rules/__test__/ruleConversionsHelper.test.js index 2a58336..a9b5587 100644 --- a/src/conversion-rules/__test__/ruleConversionsHelper.test.js +++ b/src/conversion-rules/__test__/ruleConversionsHelper.test.js @@ -233,62 +233,6 @@ describe('mapAddressElementsToUnstructuredAddress', () => { // Then expect(mappedUnstructuredAddress).toEqual(testAddressMapping); }); - - it('throws an error if addressElements is an empty array', () => { - // Given - const addressElements = []; - let error; - - // When - try { - mapAddressElementsToUnstructuredAddress( - addressElements, - testAddressToMap.postTown, - testAddressToMap.postcode - ); - } catch (err) { - error = err; - } - - // Then - expect(error.message).toEqual( - 'Cannot convert an address without at least 1 element other than postTown and postcode.' - ); - }); - - it('throws an error if postTown is null', () => { - // Given - const addressElements = testAddressToMap.elements; - const postTown = null; - let error; - - // When - try { - mapAddressElementsToUnstructuredAddress(addressElements, postTown, testAddressToMap.postcode); - } catch (err) { - error = err; - } - - // Then - expect(error.message).toEqual('Cannot convert an address without a postTown or postcode.'); - }); - - it('throws an error if postcode is null', () => { - // Given - const addressElements = testAddressToMap.elements; - const postcode = null; - let error; - - // When - try { - mapAddressElementsToUnstructuredAddress(addressElements, testAddressToMap.postTown, postcode); - } catch (err) { - error = err; - } - - // Then - expect(error.message).toEqual('Cannot convert an address without a postTown or postcode.'); - }); }); describe('isExceptionRuleIndicator', () => { diff --git a/src/conversion-rules/ruleConversions.js b/src/conversion-rules/ruleConversions.js index 039eb10..3381559 100644 --- a/src/conversion-rules/ruleConversions.js +++ b/src/conversion-rules/ruleConversions.js @@ -2,6 +2,7 @@ const { addPresentAddressElement, mapAddressElementsToUnstructuredAddress, addThoroughfareAndLocalityElementsWithPremisesPrefix, + addAllPresentOrganisationElementsAndBuildingNames, isExceptionRuleIndicator, isBuildingNameNumericPartException, getNamePartOfBuildingName, @@ -245,6 +246,30 @@ const convertRule7StructuredToUnstructured = (structuredAddress) => { ); }; +/** + * Convert a structured address to an unstructured address when none of the 7 rules apply + * + * @param structuredAddress {{}} The structured address to be converted + * @returns {{}} The converted unstructured address + */ +const convertNoRuleApplicableStructuredToUnstructured = (structuredAddress) => { + const addressElements = []; + + addAllPresentOrganisationElementsAndBuildingNames(addressElements, structuredAddress); + + if (structuredAddress.buildingNumber) { + addPresentAddressElement(addressElements, structuredAddress.buildingNumber); + } else { + addAllPresentThoroughfareAndLocalityElements(addressElements, structuredAddress); + } + + return mapAddressElementsToUnstructuredAddress( + addressElements, + structuredAddress.postTown, + structuredAddress.postcode + ); +}; + module.exports = { convertRule1StructuredToUnstructured, convertRule2StructuredToUnstructured, @@ -253,4 +278,5 @@ module.exports = { convertRule5StructuredToUnstructured, convertRule6StructuredToUnstructured, convertRule7StructuredToUnstructured, + convertNoRuleApplicableStructuredToUnstructured, }; diff --git a/src/conversion-rules/ruleConversionsHelper.js b/src/conversion-rules/ruleConversionsHelper.js index 0cdb7d6..520cd1d 100644 --- a/src/conversion-rules/ruleConversionsHelper.js +++ b/src/conversion-rules/ruleConversionsHelper.js @@ -71,6 +71,21 @@ const addAllPresentOrganisationElements = (addressElements, structuredAddress) = addPresentAddressElement(addressElements, formatPoBoxNumber(structuredAddress.poBoxNumber)); }; +/** + * Add all present organisation elements (organisation name, department name and PO Box number) and + * building names elements (building name and sub building name) to the address elements array. + * + * @param {*} addressElements {string[]} The array of address elements to append the organisation elements to + * @param {*} structuredAddress {{}} The structured address being converted + */ +const addAllPresentOrganisationElementsAndBuildingNames = (addressElements, structuredAddress) => { + addPresentAddressElement(addressElements, structuredAddress.organisationName); + addPresentAddressElement(addressElements, structuredAddress.departmentName); + addPresentAddressElement(addressElements, structuredAddress.buildingName); + addPresentAddressElement(addressElements, structuredAddress.subBuildingName); + addPresentAddressElement(addressElements, formatPoBoxNumber(structuredAddress.poBoxNumber)); +}; + /** * Add all present thoroughfare and locality elements (thoroughfare name, dependent thoroughfare name, dependent * locality and double dependent locality) to the address elements array. @@ -103,12 +118,16 @@ const addAllPresentThoroughfareAndLocalityElements = (addressElements, structure * @returns {{}} Mapped unstructured address */ const mapAddressElementsToUnstructuredAddress = (addressElements, postTown, postcode) => { - if (addressElements.length < 1) { - throw new Error('Cannot convert an address without at least 1 element other than postTown and postcode.'); - } - if (!postTown || !postcode) { - throw new Error('Cannot convert an address without a postTown or postcode.'); - } + // Errors removed from module to replicate behaviour of the postman-paf-java module + // Code commented out as the errors might be used in a future iteration + // of the library + + // if (addressElements.length < 1) { + // throw new Error('Cannot convert an address without at least 1 element other than postTown and postcode.'); + // } + // if (!postTown || !postcode) { + // throw new Error('Cannot convert an address without a postTown or postcode.'); + // } const convertedUnstructuredAddress = {}; @@ -252,6 +271,7 @@ module.exports = { addPresentAddressElement, addThoroughfareAndLocalityElementsWithPremisesPrefix, addAllPresentOrganisationElements, + addAllPresentOrganisationElementsAndBuildingNames, addAllPresentThoroughfareAndLocalityElements, mapAddressElementsToUnstructuredAddress, isExceptionRuleIndicator,