From af61a75374ca628a4b08134bce0abba176bf6d59 Mon Sep 17 00:00:00 2001 From: Chris Hopkins Date: Thu, 31 Oct 2024 13:54:16 +0000 Subject: [PATCH] Add contact consent to sandbox --- .../ContactDetails/ConsentDetails.jsx | 98 ++++--- .../__test__/transformers.test.js | 76 ++++++ .../Contacts/ContactDetails/transformers.js | 30 +++ .../specs/Contacts/ConsentDetails.cy.jsx | 243 ++++++++++++++++-- .../cypress/specs/DIT/companies-spec.js | 2 +- .../cypress/specs/contacts/details-spec.js | 8 + .../fixtures/v3/contact/contact-by-id-uk.json | 77 +++--- .../contact/contact-complete-details-uk.json | 93 +++---- 8 files changed, 492 insertions(+), 135 deletions(-) create mode 100644 src/client/modules/Contacts/ContactDetails/__test__/transformers.test.js create mode 100644 src/client/modules/Contacts/ContactDetails/transformers.js diff --git a/src/client/modules/Contacts/ContactDetails/ConsentDetails.jsx b/src/client/modules/Contacts/ContactDetails/ConsentDetails.jsx index e24d183ea5a..3965a64856d 100644 --- a/src/client/modules/Contacts/ContactDetails/ConsentDetails.jsx +++ b/src/client/modules/Contacts/ContactDetails/ConsentDetails.jsx @@ -1,53 +1,69 @@ import React from 'react' +import { isNil } from 'lodash' -import Table from '@govuk-react/table' +import { SectionHeader } from '../../../components' +import { transformContactConsents } from './transformers' -import { SummaryTable } from '../../../components' +const ConsentText = ({ consent }) => { + const message = (domain, topicNames, consentGiven) => { + let consentedMessage = `This contact has ${consentGiven ? 'given' : 'not given'} consent to ${domain}` + if (!topicNames) { + return '' + } else if (topicNames.length == 1) { + consentedMessage += ` and topic ${topicNames[0]}` + } else if (topicNames.length > 1) { + consentedMessage += ` and topics: ${topicNames.join(', ')}` + } + return consentedMessage + '.' + } + + const topicsWithNames = (topics) => + topics.length > 0 + ? topics.filter((topic) => topic.name).map((topic) => topic.name) + : undefined + + const consentedTopicNames = topicsWithNames(consent.consentedTopics) + const notConsentedTopicNames = topicsWithNames(consent.notConsentedTopics) -const getConsentRows = (consentData) => { - const domainGroupedConsent = Object.groupBy( - consentData, - ({ consentDomain }) => consentDomain + const consentedMessage = message(consent.domain, consentedTopicNames, true) + const notConsentedMessage = message( + consent.domain, + notConsentedTopicNames, + false ) - const domainRows = Object.entries(domainGroupedConsent).map((domain) => { - { - const domainTitle = domain[0] - const domainTopics = domain[1] - return domainTopics.map((topic, index) => ( - - {index == 0 && {domainTitle}} - {topic.topic} - - {topic.emailContactConsent || topic.telephoneContactConsent - ? 'Yes' - : 'No'} - - - )) + + const finalMessage = [] + if (consentedMessage) { + finalMessage.push(consentedMessage) + } + if (notConsentedMessage) { + if (consentedMessage) { + finalMessage.push(' ') } - }) + finalMessage.push(notConsentedMessage) + } + + return

{finalMessage.join('')}

+} +const ConsentDetails = ({ contact }) => { + const consents = transformContactConsents(contact) return ( - <> - - Domain - Topic - Consent Given - - {domainRows} - +
+ Contact consents + {isNil(consents) ? ( +

+ There is no consent data available for this contact +

+ ) : ( + <> + {consents.map((consent) => { + return + })} + + )} +
) } -const ConsentDetails = ({ contact }) => ( - - {contact.consentData ? ( - getConsentRows(contact.consentData) - ) : ( - - No consent data is available for this contact - - )} - -) export default ConsentDetails diff --git a/src/client/modules/Contacts/ContactDetails/__test__/transformers.test.js b/src/client/modules/Contacts/ContactDetails/__test__/transformers.test.js new file mode 100644 index 00000000000..23a0a991aab --- /dev/null +++ b/src/client/modules/Contacts/ContactDetails/__test__/transformers.test.js @@ -0,0 +1,76 @@ +import 'core-js/proposals/array-grouping-v2' +import { transformContactConsents } from '../transformers' + +describe('transformContactConsents', () => { + context('When a falsey contact is passed', () => { + it('Should return undefined', () => { + expect(transformContactConsents(undefined)).to.be.undefined + }) + }) + + context('When a contact has no consent data', () => { + it('Should return undefined', () => { + expect(transformContactConsents({})).to.be.undefined + }) + }) + + context('When a contact with a single unique value for domain', () => { + it('Should return a single domain with a single topic', () => { + expect( + transformContactConsents({ + consentData: [ + { + topic: 'Topic 1', + sourceSystem: 'System A', + consentDomain: 'International', + emailContactConsent: false, + telephoneContactConsent: false, + }, + ], + }) + ).to.deep.equal([ + { + domain: 'International', + consentedTopics: [], + notConsentedTopics: [{ consent: false, name: 'Topic 1' }], + }, + ]) + }) + }) + + context('When a contact has multiple values for domain', () => { + it('Should return a single domain with multiple topics', () => { + expect( + transformContactConsents({ + consentData: [ + { + topic: 'Topic 1', + sourceSystem: 'System A', + consentDomain: 'International', + emailContactConsent: false, + telephoneContactConsent: false, + }, + { + topic: 'Topic 2', + sourceSystem: 'System A', + consentDomain: 'International', + emailContactConsent: false, + telephoneContactConsent: true, + }, + ], + }) + ).to.deep.equal([ + { + domain: 'International', + consentedTopics: [ + { + consent: true, + name: 'Topic 2', + }, + ], + notConsentedTopics: [{ consent: false, name: 'Topic 1' }], + }, + ]) + }) + }) +}) diff --git a/src/client/modules/Contacts/ContactDetails/transformers.js b/src/client/modules/Contacts/ContactDetails/transformers.js new file mode 100644 index 00000000000..c64c24f0e56 --- /dev/null +++ b/src/client/modules/Contacts/ContactDetails/transformers.js @@ -0,0 +1,30 @@ +export const transformContactConsents = (contact) => { + if (!contact || !contact.consentData) { + return undefined + } + + const domainGroupedConsent = Object.groupBy( + contact.consentData, + ({ consentDomain }) => consentDomain + ) + + return Object.entries(domainGroupedConsent).map((domain) => ({ + domain: domain[0], + consentedTopics: domain[1] + .filter( + (topic) => topic.emailContactConsent || topic.telephoneContactConsent + ) + .map((topic) => ({ + consent: true, + name: topic.topic, + })), + notConsentedTopics: domain[1] + .filter( + (topic) => !topic.emailContactConsent && !topic.telephoneContactConsent + ) + .map((topic) => ({ + consent: false, + name: topic.topic, + })), + })) +} diff --git a/test/component/cypress/specs/Contacts/ConsentDetails.cy.jsx b/test/component/cypress/specs/Contacts/ConsentDetails.cy.jsx index 1cddca90864..34d6098fcfc 100644 --- a/test/component/cypress/specs/Contacts/ConsentDetails.cy.jsx +++ b/test/component/cypress/specs/Contacts/ConsentDetails.cy.jsx @@ -1,7 +1,6 @@ import React from 'react' import ConsentDetails from '../../../../../src/client/modules/Contacts/ContactDetails/ConsentDetails' -import { assertGovReactTable } from '../../../../functional/cypress/support/assertions' describe('ConsentDetails', () => { context('When contact has no consent data', () => { @@ -10,10 +9,214 @@ describe('ConsentDetails', () => { }) it('should render a message that this data is missing for this contact', () => { - cy.get('[data-test=no-contact-consents]').should('exist') + cy.get('p').should( + 'have.text', + 'There is no consent data available for this contact' + ) }) }) + context( + 'When a contact has consent data with a single domain and a single topic without a name where they have given consent', + () => { + beforeEach(() => { + cy.mount( + + ) + }) + + it('should render the expected message', () => { + cy.get('p').should( + 'have.text', + 'This contact has given consent to Domain 1.' + ) + }) + } + ) + + context( + 'When a contact has consent data with a single domain and a single topic with a name where they have given consent', + () => { + beforeEach(() => { + cy.mount( + + ) + }) + + it('should render the expected message', () => { + cy.get('p').should( + 'have.text', + 'This contact has given consent to Domain 1 and topic Topic 2.' + ) + }) + } + ) + + context( + 'When a contact has consent data with a single domain and multiple topics with a name where they have given consent', + () => { + beforeEach(() => { + cy.mount( + + ) + }) + + it('should render the expected message', () => { + cy.get('p').should( + 'have.text', + 'This contact has given consent to Domain 1 and topics: Topic 1, Topic 2.' + ) + }) + } + ) + + context( + 'When a contact has consent data with a single domain and multiple topics with a name where they have given and not given consent', + () => { + beforeEach(() => { + cy.mount( + + ) + }) + + it('should render the expected message', () => { + cy.get('p').should( + 'have.text', + 'This contact has given consent to Domain 1 and topic Topic 1. This contact has not given consent to Domain 1 and topics: Topic 2, Topic 3.' + ) + }) + } + ) + + context( + 'When a contact has consent data with a single domain and multiple topics with and without a name where they have given and not given consent', + () => { + beforeEach(() => { + cy.mount( + + ) + }) + + it('should render the expected message', () => { + cy.get('p').should( + 'have.text', + 'This contact has given consent to Domain 1 and topic Topic 1. This contact has not given consent to Domain 1 and topic Topic 2.' + ) + }) + } + ) + + context( + 'When a contact has consent data with a single domain and no topics where they have not given consent', + () => { + beforeEach(() => { + cy.mount( + + ) + }) + + it('should render the expected message', () => { + cy.get('p').should( + 'have.text', + 'This contact has not given consent to Domain 1.' + ) + }) + } + ) + context('When contact has consent data with multiple domains', () => { beforeEach(() => { cy.mount( @@ -27,7 +230,6 @@ describe('ConsentDetails', () => { telephoneContactConsent: false, }, { - topic: 'Topic 2', consentDomain: 'Domain 2', emailContactConsent: true, telephoneContactConsent: true, @@ -41,7 +243,7 @@ describe('ConsentDetails', () => { { topic: 'Topic 3', consentDomain: 'Domain 4', - emailContactConsent: true, + emailContactConsent: false, telephoneContactConsent: false, }, ], @@ -50,17 +252,28 @@ describe('ConsentDetails', () => { ) }) - it('should render a row for each domain', () => { - assertGovReactTable({ - element: '[data-test="contact-consent-table"]', - rows: [ - ['Domain', 'Topic', 'Consent Given'], - ['Domain 1', 'Topic 2', 'No'], - ['Domain 2', 'Topic 2', 'Yes'], - ['Domain 3', 'Topic 1', 'Yes'], - ['Domain 4', 'Topic 3', 'Yes'], - ], - }) + it('should render the expected message', () => { + cy.get('p') + .eq(0) + .should( + 'have.text', + 'This contact has not given consent to Domain 1 and topic Topic 2.' + ) + cy.get('p') + .eq(1) + .should('have.text', 'This contact has given consent to Domain 2.') + cy.get('p') + .eq(2) + .should( + 'have.text', + 'This contact has given consent to Domain 3 and topic Topic 1.' + ) + cy.get('p') + .eq(3) + .should( + 'have.text', + 'This contact has not given consent to Domain 4 and topic Topic 3.' + ) }) }) }) diff --git a/test/end-to-end/cypress/specs/DIT/companies-spec.js b/test/end-to-end/cypress/specs/DIT/companies-spec.js index bc140513164..5964b0e8809 100644 --- a/test/end-to-end/cypress/specs/DIT/companies-spec.js +++ b/test/end-to-end/cypress/specs/DIT/companies-spec.js @@ -49,7 +49,7 @@ describe('Contacts', () => { cy.contains('You have successfully added a new contact Company Contact') - assertKeyValueTable('bodyMainContent', { + assertKeyValueTable('contact-details-table', { 'Job title': 'Coffee machine operator', 'Phone number': '44 0778877778800', Address: '100 Path, A town, 12345, United States', diff --git a/test/functional/cypress/specs/contacts/details-spec.js b/test/functional/cypress/specs/contacts/details-spec.js index a0a95bc13da..abc35e56965 100644 --- a/test/functional/cypress/specs/contacts/details-spec.js +++ b/test/functional/cypress/specs/contacts/details-spec.js @@ -60,6 +60,10 @@ describe('View contact details', () => { .should('have.attr', 'href', contacts.edit(completeUKContact.id)) }) + it('should render consent detail', () => { + cy.get('[data-test=no-contact-consents]').should('not.exist') + }) + it('should render the archive container', () => { cy.get('[data-test=archive-contact-container]').should('exist') cy.get('[data-test=archive-header]') @@ -204,6 +208,10 @@ describe('View contact details', () => { }) }) + it('should not render consent detail', () => { + cy.get('[data-test=no-contact-consents]').should('exist') + }) + it('should not render the Edit Contact button', () => { cy.get('[data-test=edit-contact-button]').should('not.exist') }) diff --git a/test/sandbox/fixtures/v3/contact/contact-by-id-uk.json b/test/sandbox/fixtures/v3/contact/contact-by-id-uk.json index 323ff2911d8..b3eef423adb 100644 --- a/test/sandbox/fixtures/v3/contact/contact-by-id-uk.json +++ b/test/sandbox/fixtures/v3/contact/contact-by-id-uk.json @@ -1,43 +1,50 @@ { - "id":"f3d19ea7-d4cf-43e0-8e97-755c57cae313", - "title":null, - "first_name":"Joseph", - "last_name":"Woof", - "name":"Joseph Woof", - "job_title":"Dog master", - "company":{ - "name":"Zboncak Group|271eb29e-425b-4cd8-b386-3208c3a5f978", - "id":"4cd4128b-1bad-4f1e-9146-5d4678c6a018" + "id": "f3d19ea7-d4cf-43e0-8e97-755c57cae313", + "title": null, + "first_name": "Joseph", + "last_name": "Woof", + "name": "Joseph Woof", + "job_title": "Dog master", + "company": { + "name": "Zboncak Group|271eb29e-425b-4cd8-b386-3208c3a5f978", + "id": "4cd4128b-1bad-4f1e-9146-5d4678c6a018" }, - "adviser":{ - "name":"DBT Staff", - "first_name":"DBT", - "last_name":"Staff", - "id":"7d19d407-9aec-4d06-b190-d3f404627f21" + "adviser": { + "name": "DBT Staff", + "first_name": "DBT", + "last_name": "Staff", + "id": "7d19d407-9aec-4d06-b190-d3f404627f21" }, - "primary":true, - "telephone_countrycode":"", - "telephone_number":"", - "full_telephone_number":"222 3453454", - "email":"contact@bob.com", - "address_same_as_company":false, + "primary": true, + "telephone_countrycode": "", + "telephone_number": "", + "full_telephone_number": "222 3453454", + "email": "contact@bob.com", + "address_same_as_company": false, "address_1": null, - "address_2":null, - "address_town":null, - "address_county":null, + "address_2": null, + "address_town": null, + "address_county": null, "address_country": { "id": "80756b9a-5d95-e211-a939-e4115bead28a" }, - "address_postcode":"E14 8RJ", - "telephone_alternative":null, - "email_alternative":null, - "notes":null, - "accepts_dit_email_marketing":false, - "archived":false, - "archived_documents_url_path":"/document/123", - "archived_on":null, - "archived_reason":null, - "archived_by":null, - "created_on":"2019-02-04T15:59:14.267412Z", - "modified_on":"2019-02-05T13:17:23.112153Z" + "address_postcode": "E14 8RJ", + "telephone_alternative": null, + "email_alternative": null, + "notes": null, + "accepts_dit_email_marketing": false, + "archived": false, + "archived_documents_url_path": "/document/123", + "archived_on": null, + "archived_reason": null, + "archived_by": null, + "created_on": "2019-02-04T15:59:14.267412Z", + "modified_on": "2019-02-05T13:17:23.112153Z", + "consent_data": [ + { + "source_system": "System A", + "consent_domain": "Domestic", + "consent": false + } + ] } diff --git a/test/sandbox/fixtures/v3/contact/contact-complete-details-uk.json b/test/sandbox/fixtures/v3/contact/contact-complete-details-uk.json index 5874086a9c2..954ea12b46f 100644 --- a/test/sandbox/fixtures/v3/contact/contact-complete-details-uk.json +++ b/test/sandbox/fixtures/v3/contact/contact-complete-details-uk.json @@ -1,44 +1,51 @@ { - "id":"2676ea91-9dd7-4cf3-a4a3-67b06f841b54", - "title":null, - "first_name":"Joseph", - "last_name":"Woof", - "name":"Joseph Woof", - "job_title":"Dog master", - "company":{ - "name":"Zboncak Group|271eb29e-425b-4cd8-b386-3208c3a5f978", - "id":"4cd4128b-1bad-4f1e-9146-5d4678c6a018" - }, - "adviser":{ - "name":"DBT Staff", - "first_name":"DBT", - "last_name":"Staff", - "id":"7d19d407-9aec-4d06-b190-d3f404627f21" - }, - "primary":true, - "telephone_countrycode":"", - "telephone_number":"", - "full_telephone_number":"222 3453454", - "email":"contact@bob.com", - "address_same_as_company":false, - "address_1":"123 Test Street", - "address_2":"Address Line 2", - "address_town":"Sandbox Town", - "address_county":"Test County", - "address_country": { - "id": "80756b9a-5d95-e211-a939-e4115bead28a", - "name": "United Kingdom" - }, - "address_postcode":"AB1 2CD", - "telephone_alternative":null, - "email_alternative":null, - "notes":"An example of a contact for testing purposes", - "accepts_dit_email_marketing":true, - "archived":false, - "archived_documents_url_path":"/document/123", - "archived_on":null, - "archived_reason":null, - "archived_by":null, - "created_on":"2019-02-04T15:59:14.267412Z", - "modified_on":"2019-02-05T13:17:23.112153Z" - } + "id": "2676ea91-9dd7-4cf3-a4a3-67b06f841b54", + "title": null, + "first_name": "Joseph", + "last_name": "Woof", + "name": "Joseph Woof", + "job_title": "Dog master", + "company": { + "name": "Zboncak Group|271eb29e-425b-4cd8-b386-3208c3a5f978", + "id": "4cd4128b-1bad-4f1e-9146-5d4678c6a018" + }, + "adviser": { + "name": "DBT Staff", + "first_name": "DBT", + "last_name": "Staff", + "id": "7d19d407-9aec-4d06-b190-d3f404627f21" + }, + "primary": true, + "telephone_countrycode": "", + "telephone_number": "", + "full_telephone_number": "222 3453454", + "email": "contact@bob.com", + "address_same_as_company": false, + "address_1": "123 Test Street", + "address_2": "Address Line 2", + "address_town": "Sandbox Town", + "address_county": "Test County", + "address_country": { + "id": "80756b9a-5d95-e211-a939-e4115bead28a", + "name": "United Kingdom" + }, + "address_postcode": "AB1 2CD", + "telephone_alternative": null, + "email_alternative": null, + "notes": "An example of a contact for testing purposes", + "accepts_dit_email_marketing": true, + "archived": false, + "archived_documents_url_path": "/document/123", + "archived_on": null, + "archived_reason": null, + "archived_by": null, + "created_on": "2019-02-04T15:59:14.267412Z", + "modified_on": "2019-02-05T13:17:23.112153Z", + "consent_data": [ + { + "source_system": "System B", + "consent_domain": "International", + "consent": true + } + ] +}