diff --git a/app/presenters/notifications/setup/review.presenter.js b/app/presenters/notifications/setup/review.presenter.js index aeb83724e2..7d96a58373 100644 --- a/app/presenters/notifications/setup/review.presenter.js +++ b/app/presenters/notifications/setup/review.presenter.js @@ -13,7 +13,7 @@ const { defaultPageSize } = require('../../../../config/database.config.js') * * @param {object[]} recipients - List of recipient objects, each containing recipient details like email or name. * @param {number|string} page - The currently selected page - * @param {object} pagination - + * @param {object} pagination - The result from `PaginatorPresenter` * * @returns {object} - The data formatted for the view template */ @@ -29,13 +29,10 @@ function go(recipients, page, pagination) { /** * Contact can be an email or an address (letter) * - * If it is an address then we convert the contact CSV string to an array + * If it is an address then we convert the contact CSV string to an array. If it is an email we return the email in + * array for the UI to have consistent formatting. * - * If it is an email we return the email in array for the UI to have consistent formatting - * - * @param {object} recipient - * - * @returns {string[]} + * @private */ function _contact(recipient) { if (recipient.email) { @@ -44,17 +41,18 @@ function _contact(recipient) { const name = contactName(recipient.contact) const address = contactAddress(recipient.contact) + return [name, ...address] } -/** - * Convert the licence CSV string to an array - * - * @param {string} licences - * @returns {string[]} - */ -function _licences(licences) { - return licences.split(',') +function _formatRecipients(recipients) { + return recipients.map((recipient) => { + return { + contact: _contact(recipient), + licences: recipient.licence_refs.split(','), + method: `${recipient.message_type} - ${recipient.contact_type}` + } + }) } function _pageTitle(page, pagination) { @@ -66,24 +64,55 @@ function _pageTitle(page, pagination) { } /** - * Due to the complexity of the query to get the recipients data, we handle pagination in the presenter. + * Due to the complexity of the query we had to use a raw query to get the recipients data. This means we need to handle + * pagination (which recipients to display based on selected page and page size) in here. * * @private */ -function _pagination(recipients, page) { +function _paginateRecipients(recipients, page) { const pageNumber = Number(page) * defaultPageSize + return recipients.slice(pageNumber - defaultPageSize, pageNumber) } +/** + * Sorts, maps, and paginates the recipients list. + * + * This function first maps over the recipients to transform each recipient object into a new format, then sorts the + * resulting array of transformed recipients alphabetically by their contact's name. After sorting, it uses pagination + * to return only the relevant subset of recipients for the given page. + * + * The map and sort are performed before pagination, as it is necessary to have the recipients in a defined order before + * determining which recipients should appear on the page. + * + * @private + */ function _recipients(recipients, page) { - const paginatedRecipients = _pagination(recipients, page) + const formattedRecipients = _formatRecipients(recipients) + const sortedRecipients = _sortRecipients(formattedRecipients) - return paginatedRecipients.map((recipient) => { - return { - contact: _contact(recipient), - licences: _licences(recipient.licence_refs), - method: `${recipient.message_type} - ${recipient.contact_type}` + return _paginateRecipients(sortedRecipients, page) +} + +/** + * Sorts the recipients alphabetically by their 'contact name'. + * + * The contact name is the first element in the recipient's `contact` array. For letter-based recipients this will + * be either the person or organisation name, and for email recipients this will be the email address. + * + * @private + */ +function _sortRecipients(recipients) { + return recipients.sort((a, b) => { + if (a.contact[0] < b.contact[0]) { + return -1 + } + + if (a.contact[0] > b.contact[0]) { + return 1 } + + return 0 }) } diff --git a/package-lock.json b/package-lock.json index 61e1611df3..d100076f74 100644 --- a/package-lock.json +++ b/package-lock.json @@ -313,16 +313,16 @@ } }, "node_modules/@aws-sdk/client-s3": { - "version": "3.735.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.735.0.tgz", - "integrity": "sha512-6NcxX06c4tnnu6FTFiyS8shoYLy+8TvIDkYjJ5r9tvbaysOptUKQdolOuh7+Lz95QyaqiznpCsNTxsfywLXcqw==", + "version": "3.738.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.738.0.tgz", + "integrity": "sha512-1Im/p5yfoV15ydVY+QlffsWQkQm7iGVI+3V9tCHEUT6SdmukYEpN3G8Y+lWofRBidxzUE2Xd+MbChCXfzLAoAg==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha1-browser": "5.2.0", "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.734.0", - "@aws-sdk/credential-provider-node": "3.734.0", + "@aws-sdk/credential-provider-node": "3.738.0", "@aws-sdk/middleware-bucket-endpoint": "3.734.0", "@aws-sdk/middleware-expect-continue": "3.734.0", "@aws-sdk/middleware-flexible-checksums": "3.735.0", @@ -801,9 +801,9 @@ } }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.734.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.734.0.tgz", - "integrity": "sha512-9NOSNbkPVb91JwaXOhyfahkzAwWdMsbWHL6fh5/PHlXYpsDjfIfT23I++toepNF2nODAJNLnOEHGYIxgNgf6jQ==", + "version": "3.738.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.738.0.tgz", + "integrity": "sha512-3MuREsazwBxghKb2sQQHvie+uuK4dX4/ckFYiSoffzJQd0YHxaGxf8cr4NOSCQCUesWu8D3Y0SzlnHGboVSkpA==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/credential-provider-env": "3.734.0", @@ -3586,12 +3586,12 @@ } }, "node_modules/@smithy/core": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.1.1.tgz", - "integrity": "sha512-hhUZlBWYuh9t6ycAcN90XOyG76C1AzwxZZgaCVPMYpWqqk9uMFo7HGG5Zu2cEhCJn7DdOi5krBmlibWWWPgdsw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.1.2.tgz", + "integrity": "sha512-htwQXkbdF13uwwDevz9BEzL5ABK+1sJpVQXywwGSH973AVOvisHNfpcB8A8761G6XgHoS2kHPqc9DqHJ2gp+/Q==", "license": "Apache-2.0", "dependencies": { - "@smithy/middleware-serde": "^4.0.1", + "@smithy/middleware-serde": "^4.0.2", "@smithy/protocol-http": "^5.0.1", "@smithy/types": "^4.1.0", "@smithy/util-body-length-browser": "^4.0.0", @@ -4037,13 +4037,13 @@ } }, "node_modules/@smithy/middleware-endpoint": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.0.2.tgz", - "integrity": "sha512-Z9m67CXizGpj8CF/AW/7uHqYNh1VXXOn9Ap54fenWsCa0HnT4cJuE61zqG3cBkTZJDCy0wHJphilI41co/PE5g==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.0.3.tgz", + "integrity": "sha512-YdbmWhQF5kIxZjWqPIgboVfi8i5XgiYMM7GGKFMTvBei4XjNQfNv8sukT50ITvgnWKKKpOtp0C0h7qixLgb77Q==", "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.1.1", - "@smithy/middleware-serde": "^4.0.1", + "@smithy/core": "^3.1.2", + "@smithy/middleware-serde": "^4.0.2", "@smithy/node-config-provider": "^4.0.1", "@smithy/shared-ini-file-loader": "^4.0.1", "@smithy/types": "^4.1.0", @@ -4068,15 +4068,15 @@ } }, "node_modules/@smithy/middleware-retry": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.0.3.tgz", - "integrity": "sha512-TiKwwQTwUDeDtwWW8UWURTqu7s6F3wN2pmziLU215u7bqpVT9Mk2oEvURjpRLA+5XeQhM68R5BpAGzVtomsqgA==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.0.4.tgz", + "integrity": "sha512-wmxyUBGHaYUqul0wZiset4M39SMtDBOtUr2KpDuftKNN74Do9Y36Go6Eqzj9tL0mIPpr31ulB5UUtxcsCeGXsQ==", "license": "Apache-2.0", "dependencies": { "@smithy/node-config-provider": "^4.0.1", "@smithy/protocol-http": "^5.0.1", "@smithy/service-error-classification": "^4.0.1", - "@smithy/smithy-client": "^4.1.2", + "@smithy/smithy-client": "^4.1.3", "@smithy/types": "^4.1.0", "@smithy/util-middleware": "^4.0.1", "@smithy/util-retry": "^4.0.1", @@ -4113,9 +4113,9 @@ } }, "node_modules/@smithy/middleware-serde": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.0.1.tgz", - "integrity": "sha512-Fh0E2SOF+S+P1+CsgKyiBInAt3o2b6Qk7YOp2W0Qx2XnfTdfMuSDKUEcnrtpxCzgKJnqXeLUZYqtThaP0VGqtA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.0.2.tgz", + "integrity": "sha512-Sdr5lOagCn5tt+zKsaW+U2/iwr6bI9p08wOkCp6/eL6iMbgdtc2R5Ety66rf87PeohR0ExI84Txz9GYv5ou3iQ==", "license": "Apache-2.0", "dependencies": { "@smithy/types": "^4.1.0", @@ -4385,13 +4385,13 @@ } }, "node_modules/@smithy/smithy-client": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.1.2.tgz", - "integrity": "sha512-0yApeHWBqocelHGK22UivZyShNxFbDNrgREBllGh5Ws0D0rg/yId/CJfeoKKpjbfY2ju8j6WgDUGZHYQmINZ5w==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.1.3.tgz", + "integrity": "sha512-A2Hz85pu8BJJaYFdX8yb1yocqigyqBzn+OVaVgm+Kwi/DkN8vhN2kbDVEfADo6jXf5hPKquMLGA3UINA64UZ7A==", "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.1.1", - "@smithy/middleware-endpoint": "^4.0.2", + "@smithy/core": "^3.1.2", + "@smithy/middleware-endpoint": "^4.0.3", "@smithy/middleware-stack": "^4.0.1", "@smithy/protocol-http": "^5.0.1", "@smithy/types": "^4.1.0", @@ -4528,13 +4528,13 @@ } }, "node_modules/@smithy/util-defaults-mode-browser": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.3.tgz", - "integrity": "sha512-7c5SF1fVK0EOs+2EOf72/qF199zwJflU1d02AevwKbAUPUZyE9RUZiyJxeUmhVxfKDWdUKaaVojNiaDQgnHL9g==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.4.tgz", + "integrity": "sha512-Ej1bV5sbrIfH++KnWxjjzFNq9nyP3RIUq2c9Iqq7SmMO/idUR24sqvKH2LUQFTSPy/K7G4sB2m8n7YYlEAfZaw==", "license": "Apache-2.0", "dependencies": { "@smithy/property-provider": "^4.0.1", - "@smithy/smithy-client": "^4.1.2", + "@smithy/smithy-client": "^4.1.3", "@smithy/types": "^4.1.0", "bowser": "^2.11.0", "tslib": "^2.6.2" @@ -4556,16 +4556,16 @@ } }, "node_modules/@smithy/util-defaults-mode-node": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.3.tgz", - "integrity": "sha512-CVnD42qYD3JKgDlImZ9+On+MqJHzq9uJgPbMdeBE8c2x8VJ2kf2R3XO/yVFx+30ts5lD/GlL0eFIShY3x9ROgQ==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.4.tgz", + "integrity": "sha512-HE1I7gxa6yP7ZgXPCFfZSDmVmMtY7SHqzFF55gM/GPegzZKaQWZZ+nYn9C2Cc3JltCMyWe63VPR3tSFDEvuGjw==", "license": "Apache-2.0", "dependencies": { "@smithy/config-resolver": "^4.0.1", "@smithy/credential-provider-imds": "^4.0.1", "@smithy/node-config-provider": "^4.0.1", "@smithy/property-provider": "^4.0.1", - "@smithy/smithy-client": "^4.1.2", + "@smithy/smithy-client": "^4.1.3", "@smithy/types": "^4.1.0", "tslib": "^2.6.2" }, @@ -11731,15 +11731,15 @@ } }, "@aws-sdk/client-s3": { - "version": "3.735.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.735.0.tgz", - "integrity": "sha512-6NcxX06c4tnnu6FTFiyS8shoYLy+8TvIDkYjJ5r9tvbaysOptUKQdolOuh7+Lz95QyaqiznpCsNTxsfywLXcqw==", + "version": "3.738.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.738.0.tgz", + "integrity": "sha512-1Im/p5yfoV15ydVY+QlffsWQkQm7iGVI+3V9tCHEUT6SdmukYEpN3G8Y+lWofRBidxzUE2Xd+MbChCXfzLAoAg==", "requires": { "@aws-crypto/sha1-browser": "5.2.0", "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.734.0", - "@aws-sdk/credential-provider-node": "3.734.0", + "@aws-sdk/credential-provider-node": "3.738.0", "@aws-sdk/middleware-bucket-endpoint": "3.734.0", "@aws-sdk/middleware-expect-continue": "3.734.0", "@aws-sdk/middleware-flexible-checksums": "3.735.0", @@ -12119,9 +12119,9 @@ } }, "@aws-sdk/credential-provider-node": { - "version": "3.734.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.734.0.tgz", - "integrity": "sha512-9NOSNbkPVb91JwaXOhyfahkzAwWdMsbWHL6fh5/PHlXYpsDjfIfT23I++toepNF2nODAJNLnOEHGYIxgNgf6jQ==", + "version": "3.738.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.738.0.tgz", + "integrity": "sha512-3MuREsazwBxghKb2sQQHvie+uuK4dX4/ckFYiSoffzJQd0YHxaGxf8cr4NOSCQCUesWu8D3Y0SzlnHGboVSkpA==", "requires": { "@aws-sdk/credential-provider-env": "3.734.0", "@aws-sdk/credential-provider-http": "3.734.0", @@ -14186,11 +14186,11 @@ } }, "@smithy/core": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.1.1.tgz", - "integrity": "sha512-hhUZlBWYuh9t6ycAcN90XOyG76C1AzwxZZgaCVPMYpWqqk9uMFo7HGG5Zu2cEhCJn7DdOi5krBmlibWWWPgdsw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.1.2.tgz", + "integrity": "sha512-htwQXkbdF13uwwDevz9BEzL5ABK+1sJpVQXywwGSH973AVOvisHNfpcB8A8761G6XgHoS2kHPqc9DqHJ2gp+/Q==", "requires": { - "@smithy/middleware-serde": "^4.0.1", + "@smithy/middleware-serde": "^4.0.2", "@smithy/protocol-http": "^5.0.1", "@smithy/types": "^4.1.0", "@smithy/util-body-length-browser": "^4.0.0", @@ -14529,12 +14529,12 @@ } }, "@smithy/middleware-endpoint": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.0.2.tgz", - "integrity": "sha512-Z9m67CXizGpj8CF/AW/7uHqYNh1VXXOn9Ap54fenWsCa0HnT4cJuE61zqG3cBkTZJDCy0wHJphilI41co/PE5g==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.0.3.tgz", + "integrity": "sha512-YdbmWhQF5kIxZjWqPIgboVfi8i5XgiYMM7GGKFMTvBei4XjNQfNv8sukT50ITvgnWKKKpOtp0C0h7qixLgb77Q==", "requires": { - "@smithy/core": "^3.1.1", - "@smithy/middleware-serde": "^4.0.1", + "@smithy/core": "^3.1.2", + "@smithy/middleware-serde": "^4.0.2", "@smithy/node-config-provider": "^4.0.1", "@smithy/shared-ini-file-loader": "^4.0.1", "@smithy/types": "^4.1.0", @@ -14554,14 +14554,14 @@ } }, "@smithy/middleware-retry": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.0.3.tgz", - "integrity": "sha512-TiKwwQTwUDeDtwWW8UWURTqu7s6F3wN2pmziLU215u7bqpVT9Mk2oEvURjpRLA+5XeQhM68R5BpAGzVtomsqgA==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.0.4.tgz", + "integrity": "sha512-wmxyUBGHaYUqul0wZiset4M39SMtDBOtUr2KpDuftKNN74Do9Y36Go6Eqzj9tL0mIPpr31ulB5UUtxcsCeGXsQ==", "requires": { "@smithy/node-config-provider": "^4.0.1", "@smithy/protocol-http": "^5.0.1", "@smithy/service-error-classification": "^4.0.1", - "@smithy/smithy-client": "^4.1.2", + "@smithy/smithy-client": "^4.1.3", "@smithy/types": "^4.1.0", "@smithy/util-middleware": "^4.0.1", "@smithy/util-retry": "^4.0.1", @@ -14589,9 +14589,9 @@ } }, "@smithy/middleware-serde": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.0.1.tgz", - "integrity": "sha512-Fh0E2SOF+S+P1+CsgKyiBInAt3o2b6Qk7YOp2W0Qx2XnfTdfMuSDKUEcnrtpxCzgKJnqXeLUZYqtThaP0VGqtA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.0.2.tgz", + "integrity": "sha512-Sdr5lOagCn5tt+zKsaW+U2/iwr6bI9p08wOkCp6/eL6iMbgdtc2R5Ety66rf87PeohR0ExI84Txz9GYv5ou3iQ==", "requires": { "@smithy/types": "^4.1.0", "tslib": "^2.6.2" @@ -14796,12 +14796,12 @@ } }, "@smithy/smithy-client": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.1.2.tgz", - "integrity": "sha512-0yApeHWBqocelHGK22UivZyShNxFbDNrgREBllGh5Ws0D0rg/yId/CJfeoKKpjbfY2ju8j6WgDUGZHYQmINZ5w==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.1.3.tgz", + "integrity": "sha512-A2Hz85pu8BJJaYFdX8yb1yocqigyqBzn+OVaVgm+Kwi/DkN8vhN2kbDVEfADo6jXf5hPKquMLGA3UINA64UZ7A==", "requires": { - "@smithy/core": "^3.1.1", - "@smithy/middleware-endpoint": "^4.0.2", + "@smithy/core": "^3.1.2", + "@smithy/middleware-endpoint": "^4.0.3", "@smithy/middleware-stack": "^4.0.1", "@smithy/protocol-http": "^5.0.1", "@smithy/types": "^4.1.0", @@ -14900,12 +14900,12 @@ } }, "@smithy/util-defaults-mode-browser": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.3.tgz", - "integrity": "sha512-7c5SF1fVK0EOs+2EOf72/qF199zwJflU1d02AevwKbAUPUZyE9RUZiyJxeUmhVxfKDWdUKaaVojNiaDQgnHL9g==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.4.tgz", + "integrity": "sha512-Ej1bV5sbrIfH++KnWxjjzFNq9nyP3RIUq2c9Iqq7SmMO/idUR24sqvKH2LUQFTSPy/K7G4sB2m8n7YYlEAfZaw==", "requires": { "@smithy/property-provider": "^4.0.1", - "@smithy/smithy-client": "^4.1.2", + "@smithy/smithy-client": "^4.1.3", "@smithy/types": "^4.1.0", "bowser": "^2.11.0", "tslib": "^2.6.2" @@ -14922,15 +14922,15 @@ } }, "@smithy/util-defaults-mode-node": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.3.tgz", - "integrity": "sha512-CVnD42qYD3JKgDlImZ9+On+MqJHzq9uJgPbMdeBE8c2x8VJ2kf2R3XO/yVFx+30ts5lD/GlL0eFIShY3x9ROgQ==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.4.tgz", + "integrity": "sha512-HE1I7gxa6yP7ZgXPCFfZSDmVmMtY7SHqzFF55gM/GPegzZKaQWZZ+nYn9C2Cc3JltCMyWe63VPR3tSFDEvuGjw==", "requires": { "@smithy/config-resolver": "^4.0.1", "@smithy/credential-provider-imds": "^4.0.1", "@smithy/node-config-provider": "^4.0.1", "@smithy/property-provider": "^4.0.1", - "@smithy/smithy-client": "^4.1.2", + "@smithy/smithy-client": "^4.1.3", "@smithy/types": "^4.1.0", "tslib": "^2.6.2" }, diff --git a/test/fixtures/recipients.fixtures.js b/test/fixtures/recipients.fixtures.js index a5936515da..4382f1f475 100644 --- a/test/fixtures/recipients.fixtures.js +++ b/test/fixtures/recipients.fixtures.js @@ -25,9 +25,11 @@ function recipients() { */ function duplicateRecipients() { const duplicateLicenceRef = generateLicenceRef() + const licenceDuplicateLicenceRef = generateLicenceRef() + return { - duplicateLicenceHolder: _addDuplicateLicenceHolder(duplicateLicenceRef), - duplicateReturnsTo: _addDuplicateReturnsTo(duplicateLicenceRef), + duplicateLicenceHolder: _addDuplicateLicenceHolder(licenceDuplicateLicenceRef), + duplicateReturnsTo: _addDuplicateReturnsTo(licenceDuplicateLicenceRef), duplicatePrimaryUser: _addDuplicatePrimaryUser(duplicateLicenceRef), duplicateReturnsAgent: _addDuplicateReturnsAgent(duplicateLicenceRef) } @@ -45,7 +47,7 @@ function _addDuplicateLicenceHolder(licenceRef) { function _addDuplicateReturnsTo(licenceRef) { return { licence_refs: licenceRef, - contact_type: 'Returns To', + contact_type: 'Returns to', contact: _contact('4', 'Duplicate Returns to', 'Returns to'), contact_hash_id: 'b1b355491c7d42778890c545e08797ea' } @@ -96,7 +98,7 @@ function _addDuplicateReturnsAgent(licenceRef) { contact: null, contact_hash_id: '2e6918568dfbc1d78e2fbe279fftt990', contact_type: 'Returns agent', - recipient: 'returns.agent@important.com' + email: 'returns.agent@important.com' } } diff --git a/test/presenters/notifications/setup/review.presenter.test.js b/test/presenters/notifications/setup/review.presenter.test.js index 89c3c0346e..dd689ddd19 100644 --- a/test/presenters/notifications/setup/review.presenter.test.js +++ b/test/presenters/notifications/setup/review.presenter.test.js @@ -18,6 +18,7 @@ describe('Notifications Setup - Review presenter', () => { let pagination let testInput let testRecipients + let testDuplicateRecipients beforeEach(() => { page = 1 @@ -26,8 +27,12 @@ describe('Notifications Setup - Review presenter', () => { } testRecipients = RecipientsFixture.recipients() + // This data is used to ensure the recipients are grouped when they have the same licence ref / name. + // Ignore the fact that these would be considered duplicates elsewhere in the code + // (e.g. contact hash / address being identical) + testDuplicateRecipients = RecipientsFixture.duplicateRecipients() - testInput = Object.values(testRecipients).map((recipient) => { + testInput = [...Object.values(testRecipients), ...Object.values(testDuplicateRecipients)].map((recipient) => { return { ...recipient, // The determine recipients service will add the message_type relevant to the recipient @@ -39,7 +44,7 @@ describe('Notifications Setup - Review presenter', () => { }) describe('when provided with "recipients"', () => { - it('correctly presents the data', () => { + it('correctly presents the data (in alphabetical order)', () => { const result = ReviewPresenter.go(testInput, page, pagination) expect(result).to.equal({ @@ -47,25 +52,20 @@ describe('Notifications Setup - Review presenter', () => { pageTitle: 'Send returns invitations', recipients: [ { - contact: ['primary.user@important.com'], - licences: [testRecipients.primaryUser.licence_refs], - method: 'Letter or email - Primary user' + contact: ['Mr H J Duplicate Licence holder', '4', 'Privet Drive', 'Little Whinging', 'Surrey', 'WD25 7LR'], + licences: [testDuplicateRecipients.duplicateLicenceHolder.licence_refs], + method: 'Letter or email - Licence holder' }, { - contact: ['returns.agent@important.com'], - licences: [testRecipients.returnsAgent.licence_refs], - method: 'Letter or email - Returns agent' + contact: ['Mr H J Duplicate Returns to', '4', 'Privet Drive', 'Little Whinging', 'Surrey', 'WD25 7LR'], + licences: [testDuplicateRecipients.duplicateReturnsTo.licence_refs], + method: 'Letter or email - Returns to' }, { contact: ['Mr H J Licence holder', '1', 'Privet Drive', 'Little Whinging', 'Surrey', 'WD25 7LR'], licences: [testRecipients.licenceHolder.licence_refs], method: 'Letter or email - Licence holder' }, - { - contact: ['Mr H J Returns to', '2', 'Privet Drive', 'Little Whinging', 'Surrey', 'WD25 7LR'], - licences: [testRecipients.returnsTo.licence_refs], - method: 'Letter or email - Returns to' - }, { contact: [ 'Mr H J Licence holder with multiple licences', @@ -77,9 +77,34 @@ describe('Notifications Setup - Review presenter', () => { ], licences: testRecipients.licenceHolderWithMultipleLicences.licence_refs.split(','), method: 'Letter or email - Licence holder' + }, + { + contact: ['Mr H J Returns to', '2', 'Privet Drive', 'Little Whinging', 'Surrey', 'WD25 7LR'], + licences: [testRecipients.returnsTo.licence_refs], + method: 'Letter or email - Returns to' + }, + { + contact: ['primary.user@important.com'], + licences: [testRecipients.primaryUser.licence_refs], + method: 'Letter or email - Primary user' + }, + { + contact: ['primary.user@important.com'], + licences: [testDuplicateRecipients.duplicatePrimaryUser.licence_refs], + method: 'Letter or email - Primary user' + }, + { + contact: ['returns.agent@important.com'], + licences: [testRecipients.returnsAgent.licence_refs], + method: 'Letter or email - Returns agent' + }, + { + contact: ['returns.agent@important.com'], + licences: [testDuplicateRecipients.duplicateReturnsAgent.licence_refs], + method: 'Letter or email - Returns agent' } ], - recipientsAmount: 5 + recipientsAmount: 9 }) }) @@ -90,25 +115,27 @@ describe('Notifications Setup - Review presenter', () => { expect(result.recipients).to.equal([ { - contact: ['primary.user@important.com'], - licences: [testRecipients.primaryUser.licence_refs], - method: 'Letter or email - Primary user' + contact: [ + 'Mr H J Duplicate Licence holder', + '4', + 'Privet Drive', + 'Little Whinging', + 'Surrey', + 'WD25 7LR' + ], + licences: [testDuplicateRecipients.duplicateLicenceHolder.licence_refs], + method: 'Letter or email - Licence holder' }, { - contact: ['returns.agent@important.com'], - licences: [testRecipients.returnsAgent.licence_refs], - method: 'Letter or email - Returns agent' + contact: ['Mr H J Duplicate Returns to', '4', 'Privet Drive', 'Little Whinging', 'Surrey', 'WD25 7LR'], + licences: [testDuplicateRecipients.duplicateReturnsTo.licence_refs], + method: 'Letter or email - Returns to' }, { contact: ['Mr H J Licence holder', '1', 'Privet Drive', 'Little Whinging', 'Surrey', 'WD25 7LR'], licences: [testRecipients.licenceHolder.licence_refs], method: 'Letter or email - Licence holder' }, - { - contact: ['Mr H J Returns to', '2', 'Privet Drive', 'Little Whinging', 'Surrey', 'WD25 7LR'], - licences: [testRecipients.returnsTo.licence_refs], - method: 'Letter or email - Returns to' - }, { contact: [ 'Mr H J Licence holder with multiple licences', @@ -120,6 +147,31 @@ describe('Notifications Setup - Review presenter', () => { ], licences: testRecipients.licenceHolderWithMultipleLicences.licence_refs.split(','), method: 'Letter or email - Licence holder' + }, + { + contact: ['Mr H J Returns to', '2', 'Privet Drive', 'Little Whinging', 'Surrey', 'WD25 7LR'], + licences: [testRecipients.returnsTo.licence_refs], + method: 'Letter or email - Returns to' + }, + { + contact: ['primary.user@important.com'], + licences: [testRecipients.primaryUser.licence_refs], + method: 'Letter or email - Primary user' + }, + { + contact: ['primary.user@important.com'], + licences: [testDuplicateRecipients.duplicatePrimaryUser.licence_refs], + method: 'Letter or email - Primary user' + }, + { + contact: ['returns.agent@important.com'], + licences: [testRecipients.returnsAgent.licence_refs], + method: 'Letter or email - Returns agent' + }, + { + contact: ['returns.agent@important.com'], + licences: [testDuplicateRecipients.duplicateReturnsAgent.licence_refs], + method: 'Letter or email - Returns agent' } ]) }) @@ -199,7 +251,7 @@ describe('Notifications Setup - Review presenter', () => { describe('and there are >= 25 recipients', () => { beforeEach(() => { - testInput = [...testInput, ...testInput, ...testInput, ...testInput, ...testInput, ...testInput] + testInput = [...testInput, ...testInput, ...testInput] pagination = { numberOfPages: 2 @@ -228,7 +280,7 @@ describe('Notifications Setup - Review presenter', () => { it('returns the remaining recipients', () => { const result = ReviewPresenter.go(testInput, page, pagination) - expect(result.recipients.length).to.equal(5) + expect(result.recipients.length).to.equal(2) }) it('returns the updated "pageTitle"', () => { diff --git a/test/services/notifications/setup/determine-recipients.service.test.js b/test/services/notifications/setup/determine-recipients.service.test.js index 382828f523..46955367d9 100644 --- a/test/services/notifications/setup/determine-recipients.service.test.js +++ b/test/services/notifications/setup/determine-recipients.service.test.js @@ -132,7 +132,7 @@ describe('Notifications Setup - Determine Recipients service', () => { type: 'Person' }, contact_hash_id: 'b1b355491c7d42778890c545e08797ea', - contact_type: 'Licence holder', + contact_type: 'both', email: null, licence_refs: testDuplicateRecipients.duplicateLicenceHolder.licence_refs, message_type: 'Letter' @@ -194,7 +194,7 @@ describe('Notifications Setup - Determine Recipients service', () => { type: 'Person' }, contact_hash_id: 'b1b355491c7d42778890c545e08797ea', - contact_type: 'Licence holder', + contact_type: 'both', email: null, licence_refs: testDuplicateRecipients.duplicateLicenceHolder.licence_refs, message_type: 'Letter'