| 
									
										
										
										
											2020-08-25 19:09:30 -07:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Copyright Microsoft Corporation. All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
					
						
							|  |  |  |  * you may not use this file except in compliance with the License. | 
					
						
							|  |  |  |  * You may obtain a copy of the License at | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *     http://www.apache.org/licenses/LICENSE-2.0
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Unless required by applicable law or agreed to in writing, software | 
					
						
							|  |  |  |  * distributed under the License is distributed on an "AS IS" BASIS, | 
					
						
							|  |  |  |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
					
						
							|  |  |  |  * See the License for the specific language governing permissions and | 
					
						
							|  |  |  |  * limitations under the License. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-12 09:16:02 -07:00
										 |  |  | import { folio as base } from './fixtures'; | 
					
						
							| 
									
										
										
										
											2020-08-25 19:09:30 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | import path from 'path'; | 
					
						
							|  |  |  | import { spawn } from 'child_process'; | 
					
						
							| 
									
										
										
										
											2020-08-26 14:16:35 -07:00
										 |  |  | import type { BrowserType, Browser, LaunchOptions } from '..'; | 
					
						
							| 
									
										
										
										
											2020-08-25 19:09:30 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-10 21:31:46 -07:00
										 |  |  | type ServerFixtures = { | 
					
						
							|  |  |  |   remoteServer: RemoteServer; | 
					
						
							|  |  |  |   stallingRemoteServer: RemoteServer; | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2020-10-13 22:40:25 -07:00
										 |  |  | const fixtures = base.extend<ServerFixtures>(); | 
					
						
							| 
									
										
										
										
											2020-10-05 17:03:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-13 13:18:36 -07:00
										 |  |  | fixtures.remoteServer.init(async ({ browserType, browserOptions }, run) => { | 
					
						
							| 
									
										
										
										
											2020-10-12 09:16:02 -07:00
										 |  |  |   const remoteServer = new RemoteServer(); | 
					
						
							| 
									
										
										
										
											2020-10-13 13:18:36 -07:00
										 |  |  |   await remoteServer._start(browserType, browserOptions); | 
					
						
							| 
									
										
										
										
											2020-10-12 09:16:02 -07:00
										 |  |  |   await run(remoteServer); | 
					
						
							|  |  |  |   await remoteServer.close(); | 
					
						
							| 
									
										
										
										
											2020-10-05 17:03:24 -07:00
										 |  |  | }); | 
					
						
							| 
									
										
										
										
											2020-08-25 19:09:30 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-13 13:18:36 -07:00
										 |  |  | fixtures.stallingRemoteServer.init(async ({ browserType, browserOptions }, run) => { | 
					
						
							| 
									
										
										
										
											2020-10-12 09:16:02 -07:00
										 |  |  |   const remoteServer = new RemoteServer(); | 
					
						
							| 
									
										
										
										
											2020-10-13 13:18:36 -07:00
										 |  |  |   await remoteServer._start(browserType, browserOptions, { stallOnClose: true }); | 
					
						
							| 
									
										
										
										
											2020-10-12 09:16:02 -07:00
										 |  |  |   await run(remoteServer); | 
					
						
							|  |  |  |   await remoteServer.close(); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export const folio = fixtures.build(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-25 19:09:30 -07:00
										 |  |  | const playwrightPath = path.join(__dirname, '..'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-10 21:31:46 -07:00
										 |  |  | export class RemoteServer { | 
					
						
							| 
									
										
										
										
											2020-08-25 19:09:30 -07:00
										 |  |  |   _output: Map<any, any>; | 
					
						
							|  |  |  |   _outputCallback: Map<any, any>; | 
					
						
							|  |  |  |   _browserType: BrowserType<Browser>; | 
					
						
							| 
									
										
										
										
											2020-08-28 04:20:29 -07:00
										 |  |  |   _child: import('child_process').ChildProcess; | 
					
						
							| 
									
										
										
										
											2020-08-25 19:09:30 -07:00
										 |  |  |   _exitPromise: Promise<unknown>; | 
					
						
							|  |  |  |   _exitAndDisconnectPromise: Promise<any>; | 
					
						
							|  |  |  |   _browser: Browser; | 
					
						
							|  |  |  |   _didExit: boolean; | 
					
						
							|  |  |  |   _wsEndpoint: string; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-13 13:18:36 -07:00
										 |  |  |   async _start(browserType: BrowserType<Browser>, browserOptions: LaunchOptions, extraOptions?: { stallOnClose: boolean; }) { | 
					
						
							| 
									
										
										
										
											2020-08-25 19:09:30 -07:00
										 |  |  |     this._output = new Map(); | 
					
						
							|  |  |  |     this._outputCallback = new Map(); | 
					
						
							|  |  |  |     this._didExit = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     this._browserType = browserType; | 
					
						
							| 
									
										
										
										
											2020-10-13 13:18:36 -07:00
										 |  |  |     const launchOptions = {...browserOptions, | 
					
						
							| 
									
										
										
										
											2020-08-25 19:09:30 -07:00
										 |  |  |       handleSIGINT: true, | 
					
						
							|  |  |  |       handleSIGTERM: true, | 
					
						
							|  |  |  |       handleSIGHUP: true, | 
					
						
							| 
									
										
										
										
											2020-10-13 13:18:36 -07:00
										 |  |  |       executablePath: browserOptions.executablePath || browserType.executablePath(), | 
					
						
							| 
									
										
										
										
											2020-08-25 19:09:30 -07:00
										 |  |  |       logger: undefined, | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     const options = { | 
					
						
							|  |  |  |       playwrightPath, | 
					
						
							|  |  |  |       browserTypeName: browserType.name(), | 
					
						
							|  |  |  |       launchOptions, | 
					
						
							|  |  |  |       ...extraOptions, | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     this._child = spawn('node', [path.join(__dirname, 'fixtures', 'closeme.js'), JSON.stringify(options)]); | 
					
						
							| 
									
										
										
										
											2020-08-28 04:20:29 -07:00
										 |  |  |     this._child.on('error', (...args) => console.log('ERROR', ...args)); | 
					
						
							| 
									
										
										
										
											2020-08-25 19:09:30 -07:00
										 |  |  |     this._exitPromise = new Promise(resolve => this._child.on('exit', (exitCode, signal) => { | 
					
						
							|  |  |  |       this._didExit = true; | 
					
						
							|  |  |  |       resolve(exitCode); | 
					
						
							|  |  |  |     })); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     let outputString = ''; | 
					
						
							|  |  |  |     this._child.stdout.on('data', data => { | 
					
						
							|  |  |  |       outputString += data.toString(); | 
					
						
							|  |  |  |       // Uncomment to debug.
 | 
					
						
							|  |  |  |       // console.log(data.toString());
 | 
					
						
							|  |  |  |       let match; | 
					
						
							| 
									
										
										
										
											2020-08-28 04:20:29 -07:00
										 |  |  |       while ((match = outputString.match(/\(([^()]+)=>([^()]+)\)/))) { | 
					
						
							| 
									
										
										
										
											2020-08-25 19:09:30 -07:00
										 |  |  |         const key = match[1]; | 
					
						
							|  |  |  |         const value = match[2]; | 
					
						
							|  |  |  |         this._addOutput(key, value); | 
					
						
							|  |  |  |         outputString = outputString.substring(match.index + match[0].length); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     this._wsEndpoint = await this.out('wsEndpoint'); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   _addOutput(key, value) { | 
					
						
							|  |  |  |     this._output.set(key, value); | 
					
						
							|  |  |  |     const cb = this._outputCallback.get(key); | 
					
						
							|  |  |  |     this._outputCallback.delete(key); | 
					
						
							|  |  |  |     if (cb) | 
					
						
							|  |  |  |       cb(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   async out(key) { | 
					
						
							|  |  |  |     if (!this._output.has(key)) | 
					
						
							|  |  |  |       await new Promise(f => this._outputCallback.set(key, f)); | 
					
						
							|  |  |  |     return this._output.get(key); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   wsEndpoint() { | 
					
						
							|  |  |  |     return this._wsEndpoint; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   child() { | 
					
						
							|  |  |  |     return this._child; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   async childExitCode() { | 
					
						
							|  |  |  |     return await this._exitPromise; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-26 12:46:30 -07:00
										 |  |  |   async close() { | 
					
						
							| 
									
										
										
										
											2020-08-25 19:09:30 -07:00
										 |  |  |     if (!this._didExit) | 
					
						
							|  |  |  |       this._child.kill(); | 
					
						
							|  |  |  |     return await this.childExitCode(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } |