@@ -117,16 +117,9 @@ async function waitForPasswordInputAfterUsernameSubmit(page: Page, usernameSelec
117117
118118 if ( isUsernameLoginStep ( currentUrl ) && isIdentityLoginInputPage ( currentUrl , targetHost ) ) {
119119 const now = Date . now ( ) ;
120- if ( now - lastResubmit > 5000 && await canResubmitUsername ( page , usernameSelector ) ) {
120+ if ( now - lastResubmit > 5000 ) {
121121 lastResubmit = now ;
122- if ( isPasswordLoginStep ( page . url ( ) ) ) {
123- continue ;
124- }
125- await typeInto ( page , usernameSelector , userEmail ) ;
126- if ( isPasswordLoginStep ( page . url ( ) ) ) {
127- continue ;
128- }
129- await submitIdentityForm ( page , usernameSelector , USERNAME_SUBMIT_SELECTORS ) ;
122+ await resubmitUsernameIfStillOnUsernameStep ( page , userEmail ) ;
130123 await page . waitForTimeout ( 1000 ) ;
131124 continue ;
132125 }
@@ -160,15 +153,54 @@ async function visiblePasswordInputSelector(page: Page, timeoutMs: number): Prom
160153 return undefined ;
161154}
162155
163- async function canResubmitUsername ( page : Page , usernameSelector : string ) : Promise < boolean > {
164- if ( ! isUsernameLoginStep ( page . url ( ) ) ) {
165- return false ;
166- }
156+ async function resubmitUsernameIfStillOnUsernameStep ( page : Page , userEmail : string ) : Promise < void > {
157+ await maybeWithTimeout (
158+ page
159+ . evaluate (
160+ ( { selectors, value } ) => {
161+ if ( ! location . pathname . toLowerCase ( ) . startsWith ( "/ui/v2/login/loginname" ) ) {
162+ return ;
163+ }
164+
165+ const input = selectors
166+ . map ( ( selector ) => document . querySelector ( selector ) )
167+ . find ( ( element ) : element is HTMLInputElement => element instanceof HTMLInputElement && ! element . disabled && ! element . readOnly ) ;
168+ if ( ! input ) {
169+ return ;
170+ }
167171
168- const locator = page . locator ( usernameSelector ) . first ( ) ;
169- return ( await locatorVisible ( locator ) ) && ( await waitForEditableInput ( locator ) ) && isUsernameLoginStep ( page . url ( ) ) ;
172+ input . focus ( ) ;
173+ input . value = value ;
174+ input . dispatchEvent ( new InputEvent ( "input" , { bubbles : true , inputType : "insertText" } ) ) ;
175+ input . dispatchEvent ( new Event ( "change" , { bubbles : true } ) ) ;
176+
177+ const form = input . closest ( "form" ) ;
178+ if ( form && typeof form . requestSubmit === "function" ) {
179+ form . requestSubmit ( ) ;
180+ return ;
181+ }
182+
183+ const submit = Array . from ( document . querySelectorAll ( "button,input" ) )
184+ . find ( ( element ) : element is HTMLButtonElement | HTMLInputElement => {
185+ if ( ! ( element instanceof HTMLButtonElement || element instanceof HTMLInputElement ) || element . disabled ) {
186+ return false ;
187+ }
188+ const text = `${ element . textContent ?? "" } ${ element . value ?? "" } ` . toLowerCase ( ) ;
189+ return element . type === "submit" || text . includes ( "continue" ) || text . includes ( "next" ) || text . includes ( "sign in" ) ;
190+ } ) ;
191+ submit ?. click ( ) ;
192+ } ,
193+ { selectors : USERNAME_INPUT_SELECTORS , value : userEmail }
194+ )
195+ . catch ( ( ) => undefined ) ,
196+ 3000
197+ ) ;
170198}
171199
200+ export const __browserTestHooks = {
201+ resubmitUsernameIfStillOnUsernameStep
202+ } ;
203+
172204function isUsernameLoginStep ( currentUrl : string ) : boolean {
173205 const parsedUrl = parseBrowserUrl ( currentUrl ) ;
174206 return parsedUrl ?. pathname . toLowerCase ( ) . startsWith ( "/ui/v2/login/loginname" ) ?? false ;
0 commit comments