@@ -4,7 +4,7 @@ import fetch from 'node-fetch';
44import flagsmith from 'flagsmith/isomorphic' ;
55import { IFlagsmith } from 'flagsmith/types' ;
66
7- export const LONG_TIMEOUT = 15000 ;
7+ export const LONG_TIMEOUT = 20000 ;
88
99// Browser debugging - console and network logging
1010export const setupBrowserLogging = ( page : Page ) => {
@@ -97,7 +97,10 @@ export const setupBrowserLogging = (page: Page) => {
9797 url . includes ( '/usage-data/' ) ||
9898 url . includes ( '/invite-links/' ) ||
9999 url . includes ( '/roles/' ) ||
100- url . includes ( '/change-requests/' ) ) {
100+ url . includes ( '/change-requests/' ) ||
101+ url . includes ( '/api-keys/' ) ||
102+ url . includes ( '/metrics/' ) ||
103+ url . includes ( '/invites/' ) ) {
101104 return ;
102105 }
103106 }
@@ -214,11 +217,11 @@ export class E2EHelpers {
214217 }
215218 }
216219
217- async waitForElementVisible ( selector : string ) {
220+ async waitForElementVisible ( selector : string , timeout : number = LONG_TIMEOUT ) {
218221 logUsingLastSection ( `Waiting element visible ${ selector } ` ) ;
219222 await this . page . locator ( selector ) . first ( ) . waitFor ( {
220223 state : 'visible' ,
221- timeout : LONG_TIMEOUT
224+ timeout
222225 } ) ;
223226 }
224227
@@ -249,9 +252,45 @@ export class E2EHelpers {
249252 await expect ( this . page . locator ( selector ) ) . toHaveCount ( 0 , { timeout : 10000 } ) ;
250253 }
251254
255+ async waitForNetworkIdle ( ) {
256+ await this . page . waitForLoadState ( 'networkidle' , { timeout : 10000 } ) . catch ( ( ) => {
257+ // Silently continue if timeout - page might already be idle
258+ } ) ;
259+ }
260+
261+ async waitForDomContentLoaded ( ) {
262+ await this . page . waitForLoadState ( 'domcontentloaded' , { timeout : 10000 } ) . catch ( ( ) => {
263+ // Silently continue if timeout - DOM might already be loaded
264+ } ) ;
265+ }
266+
267+ async waitForPageFullyLoaded ( ) {
268+ await this . waitForDomContentLoaded ( ) ;
269+ await this . waitForNetworkIdle ( ) ;
270+ }
271+
272+ async getInputValue ( selector : string ) : Promise < string > {
273+ const element = this . page . locator ( selector ) . first ( ) ;
274+ await element . waitFor ( { state : 'visible' , timeout : LONG_TIMEOUT } ) ;
275+ return await element . inputValue ( ) ;
276+ }
277+
278+ async scrollBy ( x : number , y : number ) {
279+ await this . page . evaluate ( ( { x, y } ) => {
280+ window . scrollBy ( x , y ) ;
281+ } , { x, y } ) ;
282+ }
283+
284+ async scrollToBottom ( ) {
285+ await this . page . evaluate ( ( ) => {
286+ window . scrollTo ( 0 , document . body . scrollHeight ) ;
287+ } ) ;
288+ }
289+
252290 async gotoFeatures ( ) {
253291 await this . click ( '#features-link' ) ;
254292 await this . waitForElementVisible ( '#show-create-feature-btn' ) ;
293+ await this . waitForPageFullyLoaded ( ) ;
255294 }
256295
257296 async click ( selector : string ) {
@@ -449,11 +488,11 @@ export const setText = async (page: Page, selector: string, text: string) => {
449488} ;
450489
451490// Wait for an element to be visible
452- export const waitForElementVisible = async ( page : Page , selector : string ) => {
491+ export const waitForElementVisible = async ( page : Page , selector : string , timeout : number = LONG_TIMEOUT ) => {
453492 logUsingLastSection ( `Waiting element visible ${ selector } ` ) ;
454493 await page . locator ( selector ) . first ( ) . waitFor ( {
455494 state : 'visible' ,
456- timeout : LONG_TIMEOUT
495+ timeout
457496 } ) ;
458497} ;
459498
@@ -488,10 +527,52 @@ export const waitForElementNotExist = async (page: Page, selector: string) => {
488527 await expect ( page . locator ( selector ) ) . toHaveCount ( 0 , { timeout : 10000 } ) ;
489528} ;
490529
530+ // Wait for network to be idle
531+ export const waitForNetworkIdle = async ( page : Page ) => {
532+ await page . waitForLoadState ( 'networkidle' , { timeout : 10000 } ) . catch ( ( ) => {
533+ // Silently continue if timeout - page might already be idle
534+ } ) ;
535+ } ;
536+
537+ // Wait for DOM content to be loaded
538+ export const waitForDomContentLoaded = async ( page : Page ) => {
539+ await page . waitForLoadState ( 'domcontentloaded' , { timeout : 10000 } ) . catch ( ( ) => {
540+ // Silently continue if timeout - DOM might already be loaded
541+ } ) ;
542+ } ;
543+
544+ // Wait for page to be fully loaded (DOM + network)
545+ export const waitForPageFullyLoaded = async ( page : Page ) => {
546+ await waitForDomContentLoaded ( page ) ;
547+ await waitForNetworkIdle ( page ) ;
548+ } ;
549+
550+ // Get input value from an element
551+ export const getInputValue = async ( page : Page , selector : string ) : Promise < string > => {
552+ const element = page . locator ( selector ) . first ( ) ;
553+ await element . waitFor ( { state : 'visible' , timeout : LONG_TIMEOUT } ) ;
554+ return await element . inputValue ( ) ;
555+ } ;
556+
557+ // Scroll the page by x and y pixels
558+ export const scrollBy = async ( page : Page , x : number , y : number ) => {
559+ await page . evaluate ( ( { x, y } ) => {
560+ window . scrollBy ( x , y ) ;
561+ } , { x, y } ) ;
562+ } ;
563+
564+ // Scroll to bottom of page
565+ export const scrollToBottom = async ( page : Page ) => {
566+ await page . evaluate ( ( ) => {
567+ window . scrollTo ( 0 , document . body . scrollHeight ) ;
568+ } ) ;
569+ } ;
570+
491571// Navigate to features page
492572export const gotoFeatures = async ( page : Page ) => {
493573 await click ( page , '#features-link' ) ;
494574 await waitForElementVisible ( page , '#show-create-feature-btn' ) ;
575+ await waitForPageFullyLoaded ( page ) ;
495576} ;
496577
497578// Click an element
@@ -869,9 +950,7 @@ export const createRemoteConfig = async (
869950 await page . waitForTimeout ( 100 ) ;
870951 }
871952 // Wait for form validation to complete after all variations added
872- if ( mvs . length > 0 ) {
873- await page . waitForTimeout ( 500 ) ;
874- }
953+ await page . waitForTimeout ( 500 ) ;
875954 await click ( page , byId ( 'create-feature-btn' ) ) ;
876955 // Wait for the feature to be created and modal to close
877956 await page . waitForTimeout ( 2000 ) ; // Increased wait for API to process
@@ -989,6 +1068,7 @@ export const createFeature = async (
9891068 if ( value ) {
9901069 await click ( page , byId ( 'toggle-feature-button' ) ) ;
9911070 }
1071+ await page . waitForTimeout ( 500 ) ;
9921072 await click ( page , byId ( 'create-feature-btn' ) ) ;
9931073 // Wait for feature creation to complete
9941074 await page . waitForTimeout ( 1500 ) ;
@@ -1159,4 +1239,4 @@ export const setUserPermission = async (
11591239 await click ( page , byId ( `permission-switch-${ permission } ` ) ) ;
11601240 }
11611241 await closeModal ( page ) ;
1162- } ;
1242+ } ;
0 commit comments