@@ -33,6 +33,26 @@ export function SaucelabsLauncher(args,
3333 // Setup Browser name that will be printed out by Karma.
3434 this . name = browserName + ' on SauceLabs' ;
3535
36+ let pendingHeartBeat ;
37+ // Heartbeat function to keep alive sessions on Sauce Labs via WebDriver calls
38+ const heartbeat = ( ) => {
39+ const driver = connectedDrivers . get ( this . id ) ;
40+
41+ pendingHeartBeat = setTimeout ( async ( ) => {
42+ if ( driver ) {
43+ try {
44+ await driver . getTitle ( ) ;
45+ log . debug ( 'Heartbeat to Sauce Labs (%s) - fetching title' , browserName )
46+ heartbeat ( ) ;
47+ } catch ( ign ) {
48+ // Do nothing, just clear the timeout
49+ clearTimeout ( pendingHeartBeat )
50+ }
51+ }
52+ return ;
53+ } , 60000 ) ;
54+ }
55+
3656 // Listen for the start event from Karma. I know, the API is a bit different to how you
3757 // would expect, but we need to follow this approach unless we want to spend more work
3858 // improving type safety.
@@ -76,6 +96,7 @@ export function SaucelabsLauncher(args,
7696 } ) ;
7797
7898 await driver . url ( pageUrl ) ;
99+ heartbeat ( ) ;
79100 } catch ( e ) {
80101 log . error ( e ) ;
81102
@@ -85,6 +106,11 @@ export function SaucelabsLauncher(args,
85106 } ) ;
86107
87108 this . on ( 'kill' , async ( done : ( ) => void ) => {
109+ // If there is still pending heartbeats, clear the timeout
110+ if ( pendingHeartBeat ) {
111+ clearTimeout ( pendingHeartBeat ) ;
112+ }
113+
88114 try {
89115 const driver = connectedDrivers . get ( this . id ) ;
90116 await driver . deleteSession ( ) ;
0 commit comments