1- import { expect , Page } from '@playwright/test' ;
1+ import { expect , Locator , Page } from '@playwright/test' ;
22import { performAction , performValidation } from '../../../controller' ;
33import { actionRecord , IAction } from '@utils/interfaces' ;
44import { globalSearch , noResultFound , searchResults , workAccess } from '@data/page-data-figma' ;
55import { caseList , home } from '@data/page-data' ;
66
77export 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}
0 commit comments