@@ -67,6 +67,7 @@ export class BackfillPage extends BasePage {
6767 const { fromDate, reprocessBehavior, toDate } = options ;
6868
6969 await this . navigateToDagDetail ( dagName ) ;
70+ await this . waitForNoActiveBackfill ( ) ;
7071 await this . openBackfillDialog ( ) ;
7172
7273 await this . backfillFromDateInput . fill ( fromDate ) ;
@@ -78,29 +79,33 @@ export class BackfillPage extends BasePage {
7879
7980 await expect ( runsMessage ) . toBeVisible ( { timeout : 10_000 } ) ;
8081
81- await expect ( this . backfillRunButton ) . toBeEnabled ( { timeout : 5000 } ) ;
82+ const hasRuns = await this . page . locator ( "text=/\\d+ runs? will be triggered/" ) . isVisible ( ) ;
83+
84+ if ( ! hasRuns ) {
85+ await this . page . keyboard . press ( "Escape" ) ;
86+
87+ return ;
88+ }
89+
90+ await expect ( this . backfillRunButton ) . toBeEnabled ( { timeout : 15_000 } ) ;
8291 await this . backfillRunButton . click ( ) ;
8392 }
8493
85- // Get backfill details
8694 public async getBackfillDetails ( rowIndex : number = 0 ) : Promise < {
8795 createdAt : string ;
8896 fromDate : string ;
8997 reprocessBehavior : string ;
9098 toDate : string ;
9199 } > {
92- // Get the row data
93100 const row = this . page . locator ( "table tbody tr" ) . nth ( rowIndex ) ;
94101 const cells = row . locator ( "td" ) ;
95102
96103 await expect ( row ) . toBeVisible ( { timeout : 10_000 } ) ;
97104
98- // Get column headers to map column names to indices
99105 const headers = this . page . locator ( "table thead th" ) ;
100106 const headerTexts = await headers . allTextContents ( ) ;
101107 const columnMap = new Map < string , number > ( headerTexts . map ( ( text , index ) => [ text . trim ( ) , index ] ) ) ;
102108
103- // Extract data using column headers
104109 const fromDateIndex = columnMap . get ( "From" ) ?? 0 ;
105110 const toDateIndex = columnMap . get ( "To" ) ?? 1 ;
106111 const reprocessBehaviorIndex = columnMap . get ( "Reprocess Behavior" ) ?? 2 ;
@@ -124,41 +129,53 @@ export class BackfillPage extends BasePage {
124129 public async getBackfillsTableRows ( ) : Promise < number > {
125130 const rows = this . page . locator ( "table tbody tr" ) ;
126131
127- await rows . first ( ) . waitFor ( { state : "visible" , timeout : 10_000 } ) ;
128- const count = await rows . count ( ) ;
132+ try {
133+ await rows . first ( ) . waitFor ( { state : "visible" , timeout : 5000 } ) ;
134+ } catch {
135+ return 0 ;
136+ }
129137
130- return count ;
138+ return await rows . count ( ) ;
131139 }
132140
133- // Get backfill status
134- public async getBackfillStatus ( ) : Promise < string > {
135- const statusIcon = this . page . getByTestId ( "state-badge" ) . first ( ) ;
141+ public async getBackfillStatus ( rowIndex : number = 0 ) : Promise < string > {
142+ const row = this . page . locator ( "table tbody tr" ) . nth ( rowIndex ) ;
136143
137- await expect ( statusIcon ) . toBeVisible ( ) ;
138- await statusIcon . click ( ) ;
144+ await expect ( row ) . toBeVisible ( { timeout : 10_000 } ) ;
139145
140- await this . page . waitForLoadState ( "networkidle" ) ;
146+ const headers = this . page . locator ( "table thead th" ) ;
147+ const headerTexts = await headers . allTextContents ( ) ;
148+ const statusIndex = headerTexts . findIndex ( ( text ) => text . toLowerCase ( ) . includes ( "status" ) ) ;
149+
150+ if ( statusIndex === - 1 ) {
151+ const statusBadge = row
152+ . locator ( '[data-testid="state-badge"], [class*="status"], [class*="badge"]' )
153+ . first ( ) ;
154+ const isVisible = await statusBadge . isVisible ( ) . catch ( ( ) => false ) ;
141155
142- const statusBadge = this . page . getByTestId ( "state-badge" ) . first ( ) ;
156+ if ( isVisible ) {
157+ return ( await statusBadge . textContent ( ) ) ?? "" ;
158+ }
143159
144- await expect ( statusBadge ) . toBeVisible ( ) ;
160+ return "" ;
161+ }
145162
146- const statusText = ( await statusBadge . textContent ( ) ) ?? "" ;
163+ const statusCell = row . locator ( "td" ) . nth ( statusIndex ) ;
164+ const statusText = ( await statusCell . textContent ( ) ) ?? "" ;
147165
148166 return statusText . trim ( ) ;
149167 }
150168
151- // Get column header locator for assertions
152169 public getColumnHeader ( columnName : string ) : Locator {
153170 return this . page . locator ( `th:has-text("${ columnName } ")` ) ;
154171 }
155172
156- // Get filter button
157173 public getFilterButton ( ) : Locator {
158- return this . page . locator ( 'button[aria-label*="filter"], button[aria-label*="Filter"]' ) ;
174+ return this . page . locator (
175+ 'button[aria-label*="Filter table columns"], button:has-text("Filter table columns")' ,
176+ ) ;
159177 }
160178
161- // Get number of table columns
162179 public async getTableColumnCount ( ) : Promise < number > {
163180 const headers = this . page . locator ( "table thead th" ) ;
164181
@@ -172,6 +189,7 @@ export class BackfillPage extends BasePage {
172189 public async navigateToBackfillsTab ( dagName : string ) : Promise < void > {
173190 await this . navigateTo ( BackfillPage . getBackfillsUrl ( dagName ) ) ;
174191 await this . page . waitForLoadState ( "networkidle" ) ;
192+ await expect ( this . backfillsTable ) . toBeVisible ( { timeout : 10_000 } ) ;
175193 }
176194
177195 public async navigateToDagDetail ( dagName : string ) : Promise < void > {
@@ -189,13 +207,11 @@ export class BackfillPage extends BasePage {
189207 await expect ( this . backfillFromDateInput ) . toBeVisible ( { timeout : 5000 } ) ;
190208 }
191209
192- // Open the filter menu
193210 public async openFilterMenu ( ) : Promise < void > {
194211 const filterButton = this . getFilterButton ( ) ;
195212
196213 await filterButton . click ( ) ;
197214
198- // Wait for menu to appear
199215 const filterMenu = this . page . locator ( '[role="menu"]' ) ;
200216
201217 await filterMenu . waitFor ( { state : "visible" , timeout : 5000 } ) ;
@@ -215,10 +231,15 @@ export class BackfillPage extends BasePage {
215231 await radioItem . click ( ) ;
216232 }
217233
218- // Toggle a column's visibility in the filter menu
219234 public async toggleColumn ( columnName : string ) : Promise < void > {
220235 const menuItem = this . page . locator ( `[role="menuitem"]:has-text("${ columnName } ")` ) ;
221236
222237 await menuItem . click ( ) ;
223238 }
239+
240+ public async waitForNoActiveBackfill ( ) : Promise < void > {
241+ const backfillInProgress = this . page . locator ( 'text="Backfill in progress:"' ) ;
242+
243+ await expect ( backfillInProgress ) . not . toBeVisible ( { timeout : 120_000 } ) ;
244+ }
224245}
0 commit comments