@@ -12,6 +12,7 @@ const {
1212const  cssToXPath  =  require ( 'css-to-xpath' ) ; 
1313const  {  sprintf }  =  require ( 'sprintf-js' ) ; 
1414const  lodash  =  require ( 'lodash' ) ; 
15+ const  {  retry }  =  require ( '../../../development/lib/retry' ) ; 
1516const  {  quoteXPathText }  =  require ( '../../helpers/quoteXPathText' ) ; 
1617const  {  isManifestV3 }  =  require ( '../../../shared/modules/mv3.utils' ) ; 
1718const  {  WindowHandles }  =  require ( '../background-socket/window-handles' ) ; 
@@ -118,27 +119,46 @@ until.foundElementCountIs = function foundElementCountIs(locator, n) {
118119  } ) ; 
119120} ; 
120121
122+ /** 
123+  * Error messages used by driver methods. 
124+  */ 
125+ const  errorMessages  =  { 
126+   waitUntilXWindowHandlesTimeout :
127+     'waitUntilXWindowHandles timed out polling window handles' , 
128+ } ; 
129+ 
121130/** 
122131 * This is MetaMask's custom E2E test driver, wrapping the Selenium WebDriver. 
123132 * For Selenium WebDriver API documentation, see: 
124133 * https://www.selenium.dev/selenium/docs/api/javascript/module/selenium-webdriver/index_exports_WebDriver.html 
125134 */ 
126135class  Driver  { 
127136  /** 
128-    * @param  {!ThenableWebDriver } driver - A {@code  WebDriver} instance 
129-    * @param  {string } browser - The type of browser this driver is controlling 
130-    * @param  {string } extensionUrl 
131-    * @param  {number } timeout - Defaults to 10000 milliseconds (10 seconds) 
137+    * @param  {object } args - Constructor arguments. 
138+    * @param  {!ThenableWebDriver } args.driver - A {@code  WebDriver} instance 
139+    * @param  {string } args.browser - The type of browser this driver is controlling 
140+    * @param  {string } args.extensionUrl 
141+    * @param  {number } args.timeout - Defaults to 10000 milliseconds (10 seconds) 
142+    * @param  {boolean } args.disableServerMochaToBackground - Determines whether the background mocha 
143+    * server is used. 
132144   */ 
133-   constructor ( driver ,  browser ,  extensionUrl ,  timeout  =  10  *  1000 )  { 
145+   constructor ( { 
146+     driver, 
147+     browser, 
148+     extensionUrl, 
149+     timeout =  10  *  1000 , 
150+     disableServerMochaToBackground, 
151+   } )  { 
134152    this . driver  =  driver ; 
135153    this . browser  =  browser ; 
136154    this . extensionUrl  =  extensionUrl ; 
137155    this . timeout  =  timeout ; 
138156    this . exceptions  =  [ ] ; 
139157    this . errors  =  [ ] ; 
140158    this . eventProcessingStack  =  [ ] ; 
141-     this . windowHandles  =  new  WindowHandles ( this . driver ) ; 
159+     this . windowHandles  =  disableServerMochaToBackground 
160+       ? null 
161+       : new  WindowHandles ( this . driver ) ; 
142162
143163    // The following values are found in 
144164    // https://github.com/SeleniumHQ/selenium/blob/trunk/javascript/node/selenium-webdriver/lib/input.js#L50-L110 
@@ -1060,7 +1080,9 @@ class Driver {
10601080   */ 
10611081  async  switchToWindow ( handle )  { 
10621082    await  this . driver . switchTo ( ) . window ( handle ) ; 
1063-     await  this . windowHandles . getCurrentWindowProperties ( null ,  handle ) ; 
1083+     if  ( this . windowHandles )  { 
1084+       await  this . windowHandles . getCurrentWindowProperties ( null ,  handle ) ; 
1085+     } 
10641086  } 
10651087
10661088  /** 
@@ -1089,7 +1111,10 @@ class Driver {
10891111   *     be resolved with an array of window handles. 
10901112   */ 
10911113  async  getAllWindowHandles ( )  { 
1092-     return  await  this . windowHandles . getAllWindowHandles ( ) ; 
1114+     if  ( this . windowHandles )  { 
1115+       return  await  this . windowHandles . getAllWindowHandles ( ) ; 
1116+     } 
1117+     return  await  this . driver . getAllWindowHandles ( ) ; 
10931118  } 
10941119
10951120  /** 
@@ -1160,7 +1185,7 @@ class Driver {
11601185    } 
11611186
11621187    throw  new  Error ( 
1163-       `waitUntilXWindowHandles timed out polling window handles . Expected: ${ x }  , Actual: ${ windowHandles . length }  ` , 
1188+       `${ errorMessages . waitUntilXWindowHandlesTimeout }  . Expected: ${ x }  , Actual: ${ windowHandles . length }  ` , 
11641189    ) ; 
11651190  } 
11661191
@@ -1200,7 +1225,42 @@ class Driver {
12001225   * @throws  {Error } throws an error if no window with the specified title is found 
12011226   */ 
12021227  async  switchToWindowWithTitle ( title )  { 
1203-     return  await  this . windowHandles . switchToWindowWithProperty ( 'title' ,  title ) ; 
1228+     if  ( this . windowHandles )  { 
1229+       return  await  this . windowHandles . switchToWindowWithProperty ( 
1230+         'title' , 
1231+         title , 
1232+       ) ; 
1233+     } 
1234+ 
1235+     let  windowHandles  =  await  this . driver . getAllWindowHandles ( ) ; 
1236+     let  timeElapsed  =  0 ; 
1237+ 
1238+     while  ( timeElapsed  <=  this . timeout )  { 
1239+       for  ( const  handle  of  windowHandles )  { 
1240+         // Wait 25 x 200ms = 5 seconds for the title to match the target title 
1241+         const  handleTitle  =  await  retry ( 
1242+           { 
1243+             retries : 25 , 
1244+             delay : 200 , 
1245+           } , 
1246+           async  ( )  =>  { 
1247+             await  this . driver . switchTo ( ) . window ( handle ) ; 
1248+             return  await  this . driver . getTitle ( ) ; 
1249+           } , 
1250+         ) ; 
1251+ 
1252+         if  ( handleTitle  ===  title )  { 
1253+           return  handle ; 
1254+         } 
1255+       } 
1256+       const  delayTime  =  1000 ; 
1257+       await  this . delay ( delayTime ) ; 
1258+       timeElapsed  +=  delayTime ; 
1259+       // refresh the window handles 
1260+       windowHandles  =  await  this . driver . getAllWindowHandles ( ) ; 
1261+     } 
1262+ 
1263+     throw  new  Error ( `No window with title: ${ title }  ` ) ; 
12041264  } 
12051265
12061266  /** 
@@ -1224,6 +1284,11 @@ class Driver {
12241284   * @throws  {Error } throws an error if no window with the specified URL is found 
12251285   */ 
12261286  async  switchToWindowWithUrl ( url )  { 
1287+     if  ( ! this . windowHandles )  { 
1288+       throw  new  Error ( 
1289+         'This is only supported when the Mocha background server is enabled' , 
1290+       ) ; 
1291+     } 
12271292    return  await  this . windowHandles . switchToWindowWithProperty ( 
12281293      'url' , 
12291294      new  URL ( url ) . toString ( ) ,  // Make sure the URL has a trailing slash 
@@ -1240,6 +1305,11 @@ class Driver {
12401305   * @throws  {Error } throws an error if no window with the specified URL is found 
12411306   */ 
12421307  async  switchToWindowIfKnown ( title )  { 
1308+     if  ( ! this . windowHandles )  { 
1309+       throw  new  Error ( 
1310+         'This is only supported when the Mocha background server is enabled' , 
1311+       ) ; 
1312+     } 
12431313    return  await  this . windowHandles . switchToWindowIfKnown ( title ) ; 
12441314  } 
12451315
@@ -1341,46 +1411,6 @@ class Driver {
13411411    } 
13421412  } 
13431413
1344-   /** 
1345-    * Switches to a window by its title without using the background socket. 
1346-    * To be used in specs that run against production builds. 
1347-    * 
1348-    * @param  {string } title - The target window title to switch to 
1349-    * @returns  {Promise<void> } 
1350-    * @throws  {Error } Will throw an error if the target window is not found 
1351-    */ 
1352-   async  switchToWindowByTitleWithoutSocket ( title )  { 
1353-     const  windowHandles  =  await  this . driver . getAllWindowHandles ( ) ; 
1354-     let  targetWindowFound  =  false ; 
1355- 
1356-     // Iterate through each window handle 
1357-     for  ( const  handle  of  windowHandles )  { 
1358-       await  this . driver . switchTo ( ) . window ( handle ) ; 
1359-       let  currentTitle  =  await  this . driver . getTitle ( ) ; 
1360- 
1361-       // Wait 25 x 200ms = 5 seconds for the title to match the target title 
1362-       for  ( let  i  =  0 ;  i  <  25 ;  i ++ )  { 
1363-         if  ( currentTitle  ===  title )  { 
1364-           targetWindowFound  =  true ; 
1365-           console . log ( `Switched to ${ title }   window` ) ; 
1366-           break ; 
1367-         } 
1368-         await  this . driver . sleep ( 200 ) ; 
1369-         currentTitle  =  await  this . driver . getTitle ( ) ; 
1370-       } 
1371- 
1372-       // If the target window is found, break out of the outer loop 
1373-       if  ( targetWindowFound )  { 
1374-         break ; 
1375-       } 
1376-     } 
1377- 
1378-     // If target window is not found, throw an error 
1379-     if  ( ! targetWindowFound )  { 
1380-       throw  new  Error ( `${ title }   window not found` ) ; 
1381-     } 
1382-   } 
1383- 
13841414  // Error handling 
13851415
13861416  async  verboseReportOnFailure ( testTitle ,  error )  { 
@@ -1632,4 +1662,4 @@ function sanitizeTestTitle(testTitle) {
16321662    . replace ( / ^ - + | - + $ / gu,  '' ) ;  // Trim leading/trailing dashes 
16331663} 
16341664
1635- module . exports  =  {  Driver,  PAGES  } ; 
1665+ module . exports  =  {  Driver,  PAGES ,  errorMessages  } ; 
0 commit comments