Skip to content

Commit 9b92651

Browse files
ankitakunchhalspnaik77toby-plunkettadusumillipraveenAnkita-Kumbhare
authored andcommitted
Hdpi 5336 automation (#1961)
Co-authored-by: SachinNaik <sp_naik@hotmail.com> Co-authored-by: Toby Plunkett <toby.plunkett@HMCTS.NET> Co-authored-by: Praveen Adusumilli <47391951+adusumillipraveen@users.noreply.github.com> Co-authored-by: adusumillipraveen <praveen.adusumilli@hmcts.net> Co-authored-by: Ankita-Kumbhare <kumbhare.ankita33@gmail.com> Co-authored-by: taleb <tech@benouaer.com> Co-authored-by: “Kunchhal <“ankita.kunchhal@hmcts.net”>
1 parent b52b52f commit 9b92651

4 files changed

Lines changed: 126 additions & 29 deletions

File tree

src/e2eTest/data/page-data-figma/page-data-common-component/globalSearch.page.data.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@ export const globalSearch =
1818
otherReferenceInputText: 'Test reference',
1919
otherReferenceParagraph:'Any other reference to identify a case, for example National Insurance number, or system reference',
2020
nameLabel:'Name',
21-
nameInputText: 'Smith',
21+
nameInputText: 'Possession Claims Solicitor Org',
2222
nameParagraph: 'For example, name of a party or solicitor',
2323
firstLineOfAddressLabel: 'First line of address',
2424
firstLineOfAddressInputText: '2 Second Avenue',
2525
postCodeLabel: 'Postcode',
2626
postcodeInputText: 'W3 7RX',
2727
emailAddressLabel: 'Email address',
28-
emailAddressInputText: 'test@test.com',
28+
emailAddressInputText: 'pcs-solicitor1@test.com',
2929
dateOfBirthLabel: 'Date of birth',
3030
dateOfBirthDayLabel: 'Day',
3131
dateOfBirthMonthLabel: 'Month',
@@ -46,5 +46,6 @@ export const globalSearch =
4646
searchButton: 'Search',
4747
invalidCaseReferenceInputText: '0000000000000000',
4848
invalidPostcodeInputText: 'ZZ99 9ZZ',
49-
invalidNameInputText: 'XYZ_NonExistent_Name_ABC'
49+
invalidNameInputText: 'XYZ_NonExistent_Name_ABC',
50+
nextLink: 'Next page'
5051
}

src/e2eTest/tests/CommonComponent/globalSearch.spec.ts

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { test } from '@utils/test-fixtures';
2+
import { expect, Page, BrowserContext } from '@playwright/test';
23
import { initializeExecutor, performAction, performValidation } from '@utils/controller';
34
import { globalSearch} from '@data/page-data-figma';
45
import { dismissCookieBanner } from '@config/cookie-banner';
@@ -9,8 +10,8 @@ import { user} from '@data/page-data';
910
test.use({ storageState: undefined });
1011

1112
const setupGlobalSearchUser = async (
12-
page: any,
13-
context: any,
13+
page: Page,
14+
context: BrowserContext,
1415
loggedInUser: typeof user.ctscAdministrator
1516
) => {
1617
await context.clearCookies();
@@ -43,6 +44,14 @@ test.afterEach(async () => {
4344
}
4445
});
4546

47+
const runFieldSearch = async (label: string, value: string) => {
48+
await performAction('accessingTheSearch');
49+
await performAction('inputText', label, value);
50+
await performAction('select', globalSearch.servicesLabel, globalSearch.servicesDropdownOption2);
51+
await performAction('executeSearch');
52+
await performAction('validateResultsWithRetry');
53+
};
54+
4655
const runGlobalSearchScenarios = () => {
4756
test('Global search menu @smoke', async () => {
4857
await performAction('accessingTheSearch');
@@ -51,16 +60,32 @@ const runGlobalSearchScenarios = () => {
5160

5261
test('Valid case reference using Mortgage and Landlord Possession Claim Service', async () => {
5362
await performAction('accessingTheSearch');
54-
await performAction('searchByCaseReference', process.env.CASE_NUMBER);
63+
await performAction('searchByCaseReference', process.env.CASE_NUMBER, globalSearch.servicesDropdownOption2);
5564
await performAction('validateResults');
5665
});
5766

5867
test('Valid case reference using All Services', async () => {
5968
await performAction('accessingTheSearch');
60-
await performAction('searchByCaseReference', process.env.CASE_NUMBER);
69+
await performAction('searchByCaseReference', process.env.CASE_NUMBER, globalSearch.servicesDropdownOption1);
6170
await performAction('validateResults');
6271
});
6372

73+
test('Search by postcode', async () => {
74+
await runFieldSearch(globalSearch.postCodeLabel, globalSearch.postcodeInputText);
75+
});
76+
77+
test('Search by email address', async () => {
78+
await runFieldSearch(globalSearch.emailAddressLabel, globalSearch.emailAddressInputText);
79+
});
80+
81+
test('first line of address', async () => {
82+
await runFieldSearch(globalSearch.firstLineOfAddressLabel, globalSearch.firstLineOfAddressInputText);
83+
});
84+
85+
test('Search by party name', async () => {
86+
await runFieldSearch(globalSearch.nameLabel, globalSearch.nameInputText);
87+
});
88+
6489
test('Invalid case reference', async () => {
6590
await performAction('accessingTheSearch');
6691
await performAction('invalidCaseReferenceSearch', globalSearch.invalidCaseReferenceInputText);
@@ -75,9 +100,9 @@ const runGlobalSearchScenarios = () => {
75100

76101
[
77102
{ roleName: 'CTSC User', account: user.ctscAdministrator },
78-
{ roleName: 'Judge', account: user.judge }
103+
{ roleName: 'Judge User', account: user.judge }
79104
].forEach(({ roleName, account }) => {
80-
test.describe(`[Global Search - ${roleName} - @nightly @CC @caseFlags]`, () => {
105+
test.describe(`[Common Component Global Search] - ${roleName} - @nightly @CC @caseFlags`, () => {
81106
test.beforeEach(async ({ page, context }) => {
82107
await setupGlobalSearchUser(page, context, account);
83108
});
Lines changed: 88 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
1-
import { expect, Page } from '@playwright/test';
1+
import { expect, Locator, Page } from '@playwright/test';
22
import { performAction, performValidation } from '../../../controller';
33
import { actionRecord, IAction } from '@utils/interfaces';
44
import { globalSearch, noResultFound, searchResults, workAccess } from '@data/page-data-figma';
55
import { caseList, home } from '@data/page-data';
66

77
export class GlobalSearchCaseAction implements IAction {
8-
async execute(page: Page, action: string, fieldName: string | actionRecord): Promise<void> {
8+
async execute(page: Page, action: string, fieldName: string | actionRecord, value?: string | actionRecord): Promise<void> {
99
const actionsMap = new Map<string, () => Promise<void>>([
1010
['accessingTheSearch', () => this.accessingTheSearch(page)],
11-
['searchByCaseReference', () => this.searchByCaseReference(fieldName as string, page)],
12-
['invalidCaseReferenceSearch', () => this.invalidCaseReferenceSearch(fieldName as string, page)],
13-
['changeSearchLink', () => this.changeSearchLink(fieldName as string, page)],
11+
['searchByCaseReference', () => this.searchByCaseReference(fieldName as string, page, value as string | undefined)],
12+
['invalidCaseReferenceSearch', () => this.invalidCaseReferenceSearch(page)],
13+
['changeSearchLink', () => this.changeSearchLink(page)],
1414
['handleJudgeBookingPage', () => this.handleJudgeBookingPage(page)],
15-
['validateResults', () => this.validateResults(page)]
15+
['submitGlobalSearch', () => this.submitGlobalSearch(page)],
16+
['executeSearch', () => this.executeSearch(page)],
17+
['validateResults', () => this.validateResults(page)],
18+
['validateResultsWithRetry', () => this.validateResultsWithRetry(page)]
1619
]);
1720

1821
const actionToPerform = actionsMap.get(action);
@@ -24,23 +27,21 @@ export class GlobalSearchCaseAction implements IAction {
2427
await performAction('clickButton', home.globalSearchTab);
2528
}
2629

27-
private async searchByCaseReference(caseReference: string, page: Page): Promise<void> {
30+
private async searchByCaseReference(caseReference: string, page: Page, serviceOption?: string): Promise<void> {
2831
await performAction('inputText', globalSearch.DigitCaseReferenceLabel, caseReference);
29-
await performAction('select', globalSearch.servicesLabel, globalSearch.servicesDropdownOption2);
30-
await performAction('clickButton', globalSearch.searchButton);
31-
await page.locator('button[type="submit"]').click();
32+
await performAction('select', globalSearch.servicesLabel, serviceOption ?? globalSearch.servicesDropdownOption2);
33+
await this.executeSearch(page);
3234
await performValidation('mainHeader', searchResults.mainHeader);
3335
}
3436

35-
private async invalidCaseReferenceSearch(invalidCaseReference: string, page: Page): Promise<void> {
37+
private async invalidCaseReferenceSearch(page: Page): Promise<void> {
3638
await performAction('inputText', globalSearch.DigitCaseReferenceLabel, globalSearch.invalidCaseReferenceInputText);
3739
await performAction('select', globalSearch.servicesLabel, globalSearch.servicesDropdownOption1);
38-
await performAction('clickButton', globalSearch.searchButton);
39-
await page.locator('button[type="submit"]').click();
40+
await this.executeSearch(page);
4041
await performValidation('mainHeader', noResultFound.mainHeader);
4142
}
4243

43-
private async changeSearchLink(changeSearch: string, page: Page): Promise<void> {
44+
private async changeSearchLink(page: Page): Promise<void> {
4445
await performAction('clickLink', searchResults.changeSearchLink);
4546
await performValidation('mainHeader', globalSearch.mainHeader);
4647
}
@@ -53,15 +54,27 @@ export class GlobalSearchCaseAction implements IAction {
5354
await performValidation('mainHeader', caseList.mainHeader);
5455
}
5556

57+
private async submitGlobalSearch(page: Page): Promise<void> {
58+
await page.locator('button[type="submit"]').click();
59+
}
60+
61+
private async executeSearch(page: Page): Promise<void> {
62+
await performAction('clickButton', globalSearch.searchButton);
63+
await this.submitGlobalSearch(page);
64+
}
65+
5666
private async validateResults(page: Page): Promise<void> {
5767
const caseReference = String(process.env.CASE_NUMBER ?? '');
58-
const resultRow = page.locator('tr').filter({ hasText: caseReference });
59-
const caseCell = resultRow.locator('td').first();
68+
const normalizedCaseReference = caseReference.replace(/\D/g, '');
6069
await expect(page.getByRole('heading', { name: searchResults.mainHeader })).toBeVisible();
61-
await expect(resultRow).toContainText(caseReference);
62-
await expect(caseCell).toContainText(caseReference);
70+
71+
const resultRow = await this.findCaseReferenceRowAcrossPages(page, normalizedCaseReference);
72+
const caseCell = resultRow.locator('td').first();
6373
const caseCellText = (await caseCell.innerText()).trim();
64-
const caseNameText = caseCellText.replace(caseReference, '').trim();
74+
const normalizedCellText = caseCellText.replace(/\D/g, '');
75+
const formattedCaseReference = caseReference.replace(/(\d{4})(?=\d)/g, '$1-');
76+
expect(normalizedCellText).toContain(normalizedCaseReference);
77+
const caseNameText = caseCellText.replace(caseReference, '').replace(formattedCaseReference, '').trim();
6578
expect(caseNameText.length).toBeGreaterThan(0);
6679
await expect(resultRow).toContainText(searchResults.serviceLabel);
6780
await expect(resultRow).toContainText(searchResults.stateLabel);
@@ -71,4 +84,60 @@ export class GlobalSearchCaseAction implements IAction {
7184
await performAction('clickTab', home.caseSummary);
7285
await performValidation('mainHeader', home.caseSummary);
7386
}
87+
88+
private async validateResultsWithRetry(page: Page): Promise<void> {
89+
const maxRetries = 6;
90+
91+
for (let retryCount = 0; retryCount < maxRetries; retryCount++) {
92+
try {
93+
await this.validateResults(page);
94+
return;
95+
} catch (error: any) {
96+
const shouldRetry = String(error?.message ?? '').includes(
97+
'was not found on any paginated search result page'
98+
);
99+
100+
if (!shouldRetry || retryCount === maxRetries - 1) {
101+
throw error;
102+
}
103+
104+
await page.reload({ waitUntil: 'domcontentloaded' });
105+
await expect(
106+
page.getByRole('heading', { name: searchResults.mainHeader })
107+
).toBeVisible();
108+
}
109+
}
110+
}
111+
112+
private async findCaseReferenceRowAcrossPages(page: Page, normalizedCaseReference: string): Promise<Locator> {
113+
const maxPagesToScan = 50;
114+
const rows = page.locator('tbody tr');
115+
116+
for (let pageIndex = 0; pageIndex < maxPagesToScan; pageIndex++) {
117+
const rowCount = await rows.count();
118+
for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {
119+
const row = rows.nth(rowIndex);
120+
const firstCellText = (await row.locator('td').first().innerText()).trim();
121+
const normalizedRowCaseReference = firstCellText.replace(/\D/g, '');
122+
if (normalizedRowCaseReference.includes(normalizedCaseReference)) {
123+
return row;
124+
}
125+
}
126+
127+
const nextPageLink = page.getByRole('link', { name: globalSearch.nextLink, exact: true });
128+
if ((await nextPageLink.count()) === 0 || !(await nextPageLink.isVisible())) {
129+
break;
130+
}
131+
132+
const currentPageMarker = page.locator('.hmcts-pagination__item--current').first();
133+
const previousMarkerText = (await currentPageMarker.count()) > 0 ? (await currentPageMarker.innerText()).trim() : '';
134+
await nextPageLink.click();
135+
if (previousMarkerText) {
136+
await expect(currentPageMarker).not.toHaveText(previousMarkerText, { timeout: 10000 });
137+
}
138+
await expect(rows.first()).toBeVisible({ timeout: 10000 });
139+
}
140+
141+
throw new Error(`Case reference '${normalizedCaseReference}' was not found on any paginated search result page.`);
142+
}
74143
}

src/e2eTest/utils/registry/action.registry.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,10 @@ export class ActionRegistry {
9797
['searchByCaseReference', new GlobalSearchCaseAction()],
9898
['invalidCaseReferenceSearch', new GlobalSearchCaseAction()],
9999
['changeSearchLink', new GlobalSearchCaseAction()],
100-
['handleJudgeBookingPage', new GlobalSearchCaseAction()],
100+
['submitGlobalSearch', new GlobalSearchCaseAction()],
101+
['executeSearch', new GlobalSearchCaseAction()],
101102
['validateResults', new GlobalSearchCaseAction()],
103+
['validateResultsWithRetry', new GlobalSearchCaseAction()],
102104
['selectClaimingCosts', new CreateCaseAction()],
103105
['wantToUploadDocuments', new CreateCaseAction()],
104106
['uploadAdditionalDocs', new CreateCaseAction()],

0 commit comments

Comments
 (0)