import * as assert from "assert" ; import * as path from "path" ; import { Application } from "spectron" ; import { ensureProcessNotRunning } from "./ensureProcessNotRunning" ; const log = ( msg ) => { console . log ( msg ) ; } ; const isCiBuild = ( ) => { const ciBuild = ! ! ( process . env . ONI_AUTOMATION_USE_DIST_BUILD || process . env . CONTINUOUS_INTEGRATION || process . env . APPVEYOR ) ; log ( "isCiBuild: " + ciBuild ) ; return ciBuild ; } ; const getWindowsExecutablePathOnCiMachine = ( ) => { switch ( process . env . PLATFORM ) { case "x86" : return path . join ( __dirname , ".." , ".." , ".." , "dist" , "win-ia32-unpacked" , "Oni.exe" ) ; case "x64" : return path . join ( __dirname , ".." , ".." , ".." , "dist" , "win-unpacked" , "Oni.exe" ) ; default : throw new Error ( `Unable to find Oni executable for Windows arch ${ process . arch }` ) ; } } ; const getExecutablePathOnCiMachine = ( ) => { switch ( process . platform ) { case "win32" : return getWindowsExecutablePathOnCiMachine ( ) ; case "darwin" : return path . join ( __dirname , ".." , ".." , ".." , "dist" , "mac" , "Oni.app" , "Contents" , "MacOS" , "Oni" ) ; case "linux" : const archFlag = process . arch === "x64" ? "" : "ia32-" ; return path . join ( __dirname , ".." , ".." , ".." , "dist" , `linux-${ archFlag }unpacked` , "oni" ) ; default : throw new Error ( `Unable to find Oni executable for platform ${ process . platform }` ) ; } } ; const getExecutablePathLocally = ( ) => { const nodeModulesBinPath = path . join ( __dirname , ".." , ".." , ".." , "node_modules" , ".bin" ) ; return process . platform === "win32" ? path . join ( nodeModulesBinPath , "electron.cmd" ) : path . join ( nodeModulesBinPath , "electron" ) ; } ; const getArgsForCiMachine = ( ) => [ ] ; const getArgsForLocalExecution = ( ) => [ path . join ( __dirname , ".." , ".." , ".." , "lib" , "main" , "src" , "main.js" ) , ] ; export interface OniStartOptions { env ? : { ONI_CONFIG_FILE ? : string ; MYVIMRC ? : string ; [ key ] : string ; } ; } export class Oni { private _app : Application ; public get client ( ) : any { return this . _app . client ; } public async start ( options = { } ) { const ciBuild = isCiBuild ( ) ; const executablePath = ciBuild ? getExecutablePathOnCiMachine ( ) : getExecutablePathLocally ( ) ; const executableArgs = ciBuild ? getArgsForCiMachine ( ) : getArgsForLocalExecution ( ) ; log ( "Using executable path: " + executablePath ) ; log ( "Using executable args: " + executableArgs ) ; log ( "Start options: " + JSON . stringify ( options ) ) ; this . _app = new Application ( { path : executablePath , args : executableArgs , env : options . env , } ) ; log ( "Oni starting..." ) ; await this . _app . start ( ) ; log ( "Oni started. Waiting for window load.." ) ; await this . client . waitUntilWindowLoaded ( ) ; const count = await this . client . getWindowCount ( ) ; assert . ok ( count > 0 ) ; log ( `Window loaded. Reports ${ count } windows.` ) ; } public async close ( ) { log ( "Closing Oni..." ) ; const windowCount = await Promise . race ( [ this . client . getWindowCount ( ) , new Promise ( resolve => { setTimeout ( ( ) => { resolve ( "Timed out waiting for window count" ) ; } , 1000 ) ; } ) , ] ) ; log ( `- current window count: ${ windowCount }` ) ; if ( this . _app ) { let attempts = 1 ; while ( attempts < 5 ) { if ( ! this . _app . isRunning ( ) ) { log ( "- _app.isRunning() is now false" ) ; break ; } log ( "- Calling _app.stop" ) ; let didStop = false ; const promise1 = this . _app . stop ( ) . then ( ( ) => { log ( "_app.stop promise completed!" ) ; didStop = true ; } , err => { console . error ( err ) ; } ) ; const promise2 = sleep ( 15000 ) ; log ( "- Racing with 15s timer..." ) ; const race = Promise . race ( [ promise1 , promise2 ] ) ; await race ; log ( "- Race complete. didStop: " + didStop ) ; if ( ! didStop ) { log ( "- Attempting to force close processes:" ) ; await ensureProcessNotRunning ( "nvim" ) ; await ensureProcessNotRunning ( "oni" ) ; await ensureProcessNotRunning ( "chromedriver" ) ; log ( "- Force close complete" ) ; } attempts ++ ; } } log ( "Oni closed." ) ; } } const sleep = ( timeout = 1000 ) => { return new Promise ( resolve => { setTimeout ( resolve , timeout ) ; } ) ; } ;