Skip to content
Merged

PO-2391 #2890

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Comment thread
CadeFaulkner marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -1,48 +1,90 @@
import 'cypress-axe';
import { AccountNavDetailsLocators } from '../../../shared/selectors/account-details/account.nav.details.locators';
import { DEFENDANT_HEADER_MOCK } from './mocks/defendant_details_mock';
import { OPAL_FINES_ACCOUNT_DEFENDANT_ACCOUNT_PARTY_MOCK } from '@services/fines/opal-fines-service/mocks/opal-fines-account-defendant-account-party.mock';
import { OPAL_FINES_ACCOUNT_DEFENDANT_AT_A_GLANCE_MOCK } from '@services/fines/opal-fines-service/mocks/opal-fines-account-defendant-at-a-glance.mock';
import { USER_STATE_MOCK_PERMISSION_BU77 } from '../../CommonIntercepts/CommonUserState.mocks';
import { OPAL_FINES_ACCOUNT_DEFENDANT_DETAILS_CONSOLIDATED_ACCOUNTS_MOCK } from '@services/fines/opal-fines-service/mocks/opal-fines-account-defendant-details-consolidated-accounts.mock';
import { interceptAuthenticatedUser, interceptUserState } from 'cypress/component/CommonIntercepts/CommonIntercepts';
import {
interceptDefendantDetails,
interceptDefendantHeader,
interceptAtAGlance,
} from './intercept/defendantAccountIntercepts';
import { setupAccountEnquiryComponent } from './setup/SetupComponent';
import { USER_STATE_MOCK_PERMISSION_BU77 } from '../../CommonIntercepts/CommonUserState.mocks';
import { ConsolidatedAccountsLocators } from '../../../shared/selectors/account-details/account.consolidated-accounts.locators';
import { DEFENDANT_HEADER_MOCK } from './mocks/defendant_details_mock';
import { interceptConsolidatedAccounts, interceptDefendantHeader } from './intercept/defendantAccountIntercepts';
import { IComponentProperties } from './setup/setupComponent.interface';
import { setupAccountEnquiryComponent } from './setup/SetupComponent';
import 'cypress-axe';

const ACCOUNT_ENQUIRY_JIRA_LABEL = '@JIRA-LABEL:account-enquiry';

const buildTags = (...tags: string[]): string[] => [...tags, ACCOUNT_ENQUIRY_JIRA_LABEL, '@R1B'];

describe('Account Enquiry consolidated accounts tab', () => {
const componentProperties: IComponentProperties = {
accountId: '77',
fragments: 'defendant',
interceptedRoutes: ['/access-denied'],
};
const componentProperties: IComponentProperties = {
accountId: '77',
fragments: 'consolidated-accounts',
interceptedRoutes: ['/access-denied'],
};

type ConsolidatedAccountsMock = typeof OPAL_FINES_ACCOUNT_DEFENDANT_DETAILS_CONSOLIDATED_ACCOUNTS_MOCK;

const setupShell = (hasConsolidatedAccounts: boolean) => {
const headerMock = structuredClone(DEFENDANT_HEADER_MOCK);
headerMock.has_consolidated_accounts = hasConsolidatedAccounts;
const accountId = headerMock.defendant_account_party_id;
const cell = (columnKey: string, rowIndex: number): string => ConsolidatedAccountsLocators.cell(columnKey, rowIndex);
const normaliseText = (value: string): string =>
value
.replace(/\u00A0/g, ' ')
.replace(/\s+/g, ' ')
.trim();

interceptAuthenticatedUser();
interceptUserState(USER_STATE_MOCK_PERMISSION_BU77);
interceptDefendantHeader(accountId, headerMock, '123');
interceptDefendantDetails(accountId, OPAL_FINES_ACCOUNT_DEFENDANT_ACCOUNT_PARTY_MOCK, '123');
interceptAtAGlance(accountId, OPAL_FINES_ACCOUNT_DEFENDANT_AT_A_GLANCE_MOCK, '123');
const expectCellText = (selector: string, expected: string) => {
cy.get(selector)
.invoke('text')
.then((text) => {
expect(normaliseText(text)).to.eq(expected);
});
};

const consolidatedAccountsMock: ConsolidatedAccountsMock = {
...structuredClone(OPAL_FINES_ACCOUNT_DEFENDANT_DETAILS_CONSOLIDATED_ACCOUNTS_MOCK),
consolidated_accounts: [
{
account_id: 99000000990002,
account_number: '99009902C',
date_imposed: '2025-01-12',
first_name: 'Casey',
imposed_by: 'Seed Child Court',
last_name: 'Child',
reference: 'LOCAL-CONSOL-CHILD',
},
{
account_id: 99000000990003,
account_number: '99009903D',
date_imposed: '2026-02-03',
first_name: 'Robin',
imposed_by: 'Central London Magistrates Court',
last_name: 'Bridge',
reference: 'Ref/Mixed-Case/123',
},
],
};

setupAccountEnquiryComponent({ ...componentProperties, accountId });
cy.get(AccountNavDetailsLocators.root).should('exist');
const setupConsolidatedAccountsScreen = (
hasConsolidatedAccounts: boolean = true,
mockData: ConsolidatedAccountsMock = consolidatedAccountsMock,
) => {
const headerMock = {
...structuredClone(DEFENDANT_HEADER_MOCK),
has_consolidated_accounts: hasConsolidatedAccounts,
};
const accountId = headerMock.defendant_account_party_id;

interceptAuthenticatedUser();
interceptUserState(USER_STATE_MOCK_PERMISSION_BU77);
interceptDefendantHeader(accountId, headerMock, '123');
interceptConsolidatedAccounts(accountId, mockData.consolidated_accounts, '123');

setupAccountEnquiryComponent({ ...componentProperties, accountId });
cy.wait('@getConsolidatedAccounts').its('response.body').should('have.length', 2);
};

describe('Account Enquiry Consolidated Accounts Tab', () => {
it(
"AC1a. should display 'Consolidated accounts' to the right of 'History and notes' when consolidated accounts exist",
{ tags: [...buildTags('@JIRA-STORY:PO-2389'), '@JIRA-EPIC:PO-976'] },
() => {
setupShell(true);
setupConsolidatedAccountsScreen(true);

cy.get(AccountNavDetailsLocators.subNav.historyAndNotesTab).should('exist');
cy.get(AccountNavDetailsLocators.subNav.consolidatedAccountsTab).should('exist');
Expand All @@ -54,23 +96,62 @@ describe('Account Enquiry consolidated accounts tab', () => {
expect(labels).to.include('Consolidated accounts');
expect(labels.indexOf('History and notes')).to.be.lessThan(labels.indexOf('Consolidated accounts'));
});

cy.injectAxe();
cy.checkA11y(AccountNavDetailsLocators.subNav.root);
},
);

it(
"AC2a. should not display 'Consolidated accounts' when no consolidated accounts exist",
{ tags: [...buildTags('@JIRA-STORY:PO-2389'), '@JIRA-EPIC:PO-976'] },
() => {
setupShell(false);
setupConsolidatedAccountsScreen(false);

cy.get(AccountNavDetailsLocators.subNav.historyAndNotesTab).should('exist');
cy.get(AccountNavDetailsLocators.subNav.consolidatedAccountsTab).should('not.exist');
},
);

it(
'AC1a, AC1b, AC1c, AC1d, AC1e, AC1f: fetches consolidated child accounts and renders the read-only table',
{
tags: [...buildTags('@JIRA-STORY:PO-2391'), '@JIRA-EPIC:PO-2332'],
},
() => {
setupConsolidatedAccountsScreen();

cy.get(ConsolidatedAccountsLocators.tabLink)
.should('have.attr', 'aria-current', 'page')
.and('contain.text', 'Consolidated accounts');
cy.get(ConsolidatedAccountsLocators.heading).should('contain.text', 'Consolidated accounts');
cy.get(`${ConsolidatedAccountsLocators.tabRoot} th.govuk-table__header`).then((headers) => {
expect([...headers].map((header) => normaliseText(header.textContent ?? ''))).to.deep.eq([
'Account',
'Name',
'Date imposed',
'Imposed by',
'Reference',
]);
});
cy.get(ConsolidatedAccountsLocators.tableRows).should('have.length', 2);
cy.get(ConsolidatedAccountsLocators.tabRoot).within(() => {
cy.get('input, textarea, select, button, [contenteditable="true"]').should('not.exist');
});

expectCellText(cell('name', 0), 'CHILD, Casey');
expectCellText(cell('date-imposed', 0), '12 Jan 2025');
expectCellText(cell('imposed-by', 0), 'Seed Child Court');
expectCellText(cell('reference', 0), 'LOCAL-CONSOL-CHILD');
expectCellText(cell('name', 1), 'BRIDGE, Robin');
expectCellText(cell('date-imposed', 1), '03 Feb 2026');
expectCellText(cell('imposed-by', 1), 'Central London Magistrates Court');
expectCellText(cell('reference', 1), 'Ref/Mixed-Case/123');

cy.injectAxe();
cy.checkA11y(AccountNavDetailsLocators.subNav.root);
cy.get(cell('number', 0))
.find('a')
.should(($link) => {
expect(normaliseText($link.text())).to.eq('99009902C');
})
.and('have.attr', 'href', '/fines/account/defendant/99000000990002/details#at-a-glance')
.and('have.attr', 'target', '_blank');
},
);
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { IOpalFinesAccountDefendantDetailsFixedPenaltyTabRefData } from '@servic
import { IOpalFinesAccountDefendantDetailsHistoryAndNotesTabRefData } from '@services/fines/opal-fines-service/interfaces/opal-fines-account-defendant-details-history-and-notes-tab-ref-data.interface';
import { IOpalFinesAccountDefendantDetailsImpositionsTabRefData } from '@services/fines/opal-fines-service/interfaces/opal-fines-account-defendant-details-impositions-tab-ref-data.interface';
import { IOpalFinesAccountDefendantDetailsPaymentTermsLatest } from '@services/fines/opal-fines-service/interfaces/opal-fines-account-defendant-details-payment-terms-latest.interface';
import { IOpalFinesAccountDefendantDetailsConsolidatedAccount } from 'src/app/flows/fines/services/opal-fines-service/interfaces/opal-fines-account-defendant-account-consolidated-account.interface';
import { IOpalFinesAccountMinorCreditorAtAGlance } from 'src/app/flows/fines/services/opal-fines-service/interfaces/opal-fines-account-minor-creditor-at-a-glance.interface';
import { IOpalFinesAccountMinorCreditorCreditor } from 'src/app/flows/fines/services/opal-fines-service/interfaces/opal-fines-account-minor-creditor-creditor.interface';
import { IOpalFinesAccountMinorCreditorDetailsHistoryAndNotesTabRefData } from 'src/app/flows/fines/services/opal-fines-service/interfaces/opal-fines-account-minor-creditor-details-history-and-notes-tab-ref-data.interface';
Expand All @@ -29,6 +30,28 @@ export function interceptAddNotes() {
.as('postAddNotes');
}

/**
* Intercepts the GET request to the defendant accounts "consolidated-accounts" endpoint and mocks the response.
*
* @param accountId - The unique identifier for the account.
* @param consolidatedAccounts - The consolidated accounts to be returned in the response body.
* @param respHeaderEtag - The value to set for the ETag response header.
* @returns Cypress chainable object with the intercepted request aliased as 'getConsolidatedAccounts'.
*/
export function interceptConsolidatedAccounts(
accountId: string | number,
consolidatedAccounts: IOpalFinesAccountDefendantDetailsConsolidatedAccount[],
respHeaderEtag: string,
) {
return cy
.intercept('GET', `**/defendant-accounts/${accountId}/consolidated-accounts`, {
statusCode: 200,
headers: { ETag: respHeaderEtag },
body: consolidatedAccounts,
})
.as('getConsolidatedAccounts');
}

/**
* Intercepts the GET request to the defendant accounts "at-a-glance" endpoint and mocks the response.
*
Expand Down
Loading