@@ -16,114 +16,114 @@ export function SaucelabsLauncher(args,
1616 captureTimeoutLauncherDecorator ,
1717 retryLauncherDecorator ) {
1818
19- // Apply base class mixins. This would be nice to have typed, but this is a low-priority now.
20- baseLauncherDecorator ( this ) ;
21- captureTimeoutLauncherDecorator ( this ) ;
22- retryLauncherDecorator ( this ) ;
23-
24- // initiate driver with null to not close the tunnel too early
25- connectedDrivers . set ( this . id , null )
26-
27- const log = logger . create ( 'SaucelabsLauncher' ) ;
28- const {
29- startConnect,
30- sauceConnectOptions,
31- seleniumCapabilities,
32- browserName
33- } = processConfig ( config , args ) ;
34-
35- // Setup Browser name that will be printed out by Karma.
36- this . name = browserName + ' on SauceLabs' ;
37-
38- // Listen for the start event from Karma. I know, the API is a bit different to how you
39- // would expect, but we need to follow this approach unless we want to spend more work
40- // improving type safety.
41- this . on ( 'start' , async ( pageUrl : string ) => {
42- if ( startConnect ) {
43- try {
44- // In case the "startConnect" option has been enabled, establish a tunnel and wait
45- // for it being ready. In case a tunnel is already active, this will just continue
46- // without establishing a new one.
47- await sauceConnect . establishTunnel ( seleniumCapabilities , sauceConnectOptions ) ;
48- } catch ( error ) {
49- log . error ( error ) ;
50-
51- this . _done ( 'failure' ) ;
52- return ;
53- }
54- }
55-
56- try {
57- // See the following link for public API of the selenium server.
58- // https://wiki.saucelabs.com/display/DOCS/Instant+Selenium+Node.js+Tests
59- const driver = await remote ( seleniumCapabilities ) ;
60-
61- // Keep track of all connected drivers because it's possible that there are multiple
62- // driver instances (e.g. when running with concurrency)
63- connectedDrivers . set ( this . id , driver ) ;
64-
65- const sessionId = driver . sessionId
66-
67- log . info ( '%s session at https://saucelabs.com/tests/%s' , browserName , sessionId ) ;
68- log . debug ( 'Opening "%s" on the selenium client' , pageUrl ) ;
69-
70- // Store the information about the current session in the browserMap. This is necessary
71- // because otherwise the Saucelabs reporter is not able to report results.
72- browserMap . set ( this . id , {
73- sessionId,
74- username : seleniumCapabilities . user ,
75- accessKey : seleniumCapabilities . key ,
76- region : seleniumCapabilities . region ,
77- headless : seleniumCapabilities . headless ,
78- results :[ ] ,
79- } ) ;
80-
81- await driver . url ( pageUrl ) ;
82- } catch ( e ) {
83- log . error ( e ) ;
84-
85- // Notify karma about the failure.
86- this . _done ( 'failure' ) ;
87- }
88- } ) ;
89-
90- this . on ( 'kill' , async ( done : ( ) => void ) => {
91- try {
92- const driver = connectedDrivers . get ( this . id ) ;
93- const { sessionId} = driver ;
94- await driver . deleteSession ( ) ;
95-
96- const browserData = browserMap . get ( this . id ) ;
97- const api = new SauceLabs ( {
98- user : browserData . username ,
99- key : browserData . accessKey ,
100- region : browserData . region ,
101- } ) ;
102-
103- // Wait until the vm is destroyed and the assets are stored
104- await new Promise ( resolve => setTimeout ( ( ) => resolve ( ) , 5000 ) ) ;
105- // Create a tmp dir
106- mkdirSync ( sessionId ) ;
107- writeFileSync ( `${ sessionId } /log.json` , JSON . stringify ( browserData . results , null , 2 ) ) ;
108- // Update the log assets
109- // @ts -ignore
110- await api . uploadJobAssets (
111- sessionId ,
112- { files : [ `${ sessionId } /log.json` ] } ,
113- ) ;
114- // remove the temporary folder
115- removeSync ( sessionId ) ;
116-
117- } catch ( e ) {
118- // We need to ignore the exception here because we want to make sure that Karma is still
119- // able to retry connecting if Saucelabs itself terminated the session (and not Karma)
120- // For example if the "idleTimeout" is exceeded and Saucelabs errored the session. See:
121- // https://wiki.saucelabs.com/display/DOCS/Test+Didn%27t+See+a+New+Command+for+90+Seconds
122- log . error ( 'Could not quit the Saucelabs selenium connection. Failure message:' ) ;
123- log . error ( e ) ;
124- }
125-
126- connectedDrivers . delete ( this . id )
127- return process . nextTick ( done ) ;
128- } )
19+ // Apply base class mixins. This would be nice to have typed, but this is a low-priority now.
20+ baseLauncherDecorator ( this ) ;
21+ captureTimeoutLauncherDecorator ( this ) ;
22+ retryLauncherDecorator ( this ) ;
23+
24+ // initiate driver with null to not close the tunnel too early
25+ connectedDrivers . set ( this . id , null )
26+
27+ const log = logger . create ( 'SaucelabsLauncher' ) ;
28+ const {
29+ startConnect,
30+ sauceConnectOptions,
31+ seleniumCapabilities,
32+ browserName
33+ } = processConfig ( config , args ) ;
34+
35+ // Setup Browser name that will be printed out by Karma.
36+ this . name = browserName + ' on SauceLabs' ;
37+
38+ // Listen for the start event from Karma. I know, the API is a bit different to how you
39+ // would expect, but we need to follow this approach unless we want to spend more work
40+ // improving type safety.
41+ this . on ( 'start' , async ( pageUrl : string ) => {
42+ if ( startConnect ) {
43+ try {
44+ // In case the "startConnect" option has been enabled, establish a tunnel and wait
45+ // for it being ready. In case a tunnel is already active, this will just continue
46+ // without establishing a new one.
47+ await sauceConnect . establishTunnel ( seleniumCapabilities , sauceConnectOptions ) ;
48+ } catch ( error ) {
49+ log . error ( error ) ;
50+
51+ this . _done ( 'failure' ) ;
52+ return ;
53+ }
54+ }
55+
56+ try {
57+ // See the following link for public API of the selenium server.
58+ // https://wiki.saucelabs.com/display/DOCS/Instant+Selenium+Node.js+Tests
59+ const driver = await remote ( seleniumCapabilities ) ;
60+
61+ // Keep track of all connected drivers because it's possible that there are multiple
62+ // driver instances (e.g. when running with concurrency)
63+ connectedDrivers . set ( this . id , driver ) ;
64+
65+ const sessionId = driver . sessionId
66+
67+ log . info ( '%s session at https://saucelabs.com/tests/%s' , browserName , sessionId ) ;
68+ log . debug ( 'Opening "%s" on the selenium client' , pageUrl ) ;
69+
70+ // Store the information about the current session in the browserMap. This is necessary
71+ // because otherwise the Saucelabs reporter is not able to report results.
72+ browserMap . set ( this . id , {
73+ sessionId,
74+ username : seleniumCapabilities . user ,
75+ accessKey : seleniumCapabilities . key ,
76+ region : seleniumCapabilities . region ,
77+ headless : seleniumCapabilities . headless ,
78+ results : [ ] ,
79+ } ) ;
80+
81+ await driver . url ( pageUrl ) ;
82+ } catch ( e ) {
83+ log . error ( e ) ;
84+
85+ // Notify karma about the failure.
86+ this . _done ( 'failure' ) ;
87+ }
88+ } ) ;
89+
90+ this . on ( 'kill' , async ( done : ( ) => void ) => {
91+ try {
92+ const driver = connectedDrivers . get ( this . id ) ;
93+ const { sessionId} = driver ;
94+ await driver . deleteSession ( ) ;
95+
96+ const browserData = browserMap . get ( this . id ) ;
97+ const api = new SauceLabs ( {
98+ user : browserData . username ,
99+ key : browserData . accessKey ,
100+ region : browserData . region ,
101+ } ) ;
102+
103+ // Wait until the vm is destroyed and the assets are stored
104+ await new Promise ( resolve => setTimeout ( ( ) => resolve ( ) , 5000 ) ) ;
105+ // Create a tmp dir
106+ mkdirSync ( sessionId ) ;
107+ writeFileSync ( `${ sessionId } /log.json` , JSON . stringify ( browserData . results , null , 2 ) ) ;
108+ // Update the log assets
109+ // @ts -ignore
110+ await api . uploadJobAssets (
111+ sessionId ,
112+ { files : [ `${ sessionId } /log.json` ] } ,
113+ ) ;
114+ // remove the temporary folder
115+ removeSync ( sessionId ) ;
116+
117+ } catch ( e ) {
118+ // We need to ignore the exception here because we want to make sure that Karma is still
119+ // able to retry connecting if Saucelabs itself terminated the session (and not Karma)
120+ // For example if the "idleTimeout" is exceeded and Saucelabs errored the session. See:
121+ // https://wiki.saucelabs.com/display/DOCS/Test+Didn%27t+See+a+New+Command+for+90+Seconds
122+ log . error ( 'Could not quit the Saucelabs selenium connection. Failure message:' ) ;
123+ log . error ( e ) ;
124+ }
125+
126+ connectedDrivers . delete ( this . id )
127+ return process . nextTick ( done ) ;
128+ } )
129129}
0 commit comments