neft
Version:
Universal Platform
132 lines (112 loc) • 3.27 kB
text/coffeescript
'use strict'
fs = require 'fs-extra'
childProcess = require 'child_process'
which = require 'which'
utils = require 'src/utils'
signal = require 'src/signal'
config = require '../cli/config'
{log} = Neft
USER_DATA_DIR = "tmp/chrome-#{utils.uid()}"
CHROME_PATHS = [
'chromium',
'google-chrome',
'chromium-browser',
'/Applications/Chromium.app/Contents/MacOS/Chromium',
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
]
CHROME_ARGS = [
'--enable-logging=stderr',
'--v=1',
'--no-first-run',
"--user-data-dir=#{USER_DATA_DIR}",
'--no-sandbox', # TODO: run chrome on travis in sandbox mode
'--window-position=0,0'
]
CHROME_LOG_RE = ///
# declaration
^\[
# pid, date, severity
(?:[0-9A-Z/]*:){4}
# type
(.*?)
\([0-9]*\)
\]
(?:.*)
# content
"(.*)"
(?:.*)$
///
CHROME_CONSOLE_LOG_TYPE = 'CONSOLE'
###
Returns path to the Chrome or Chromium process available on the machine
###
getChromePath = (callback) ->
utils.async.forEach CHROME_PATHS, (path, index, array, next) ->
which path, (err, resolvedPath) ->
if err
next()
else
log "Chrome path resolved to #{resolvedPath}"
callback null, resolvedPath
, ->
callback new Error 'Cannot resolve Chrome path'
###
Returns JavaScript console logs from Chrome logs
###
getConsoleLogs = (stdout) ->
lines = String(stdout).split '\n'
logs = []
for line in lines
parsedLine = CHROME_LOG_RE.exec line
unless parsedLine?
continue
[_, type, content] = parsedLine
if type is CHROME_CONSOLE_LOG_TYPE
logs.push content
logs
###
Runs the given URI in Chrome
###
runOnPathWithUri = (env, uri, callback) ->
args = utils.clone CHROME_ARGS
args.push "--app=#{uri}"
if env.width? and env.height?
args.push "--window-size=#{env.width},#{env.height}"
chrome = childProcess.spawn env.path, args, env: config.getProcessEnv()
chrome.on 'exit', ->
log "Chrome terminated"
fs.removeSync USER_DATA_DIR
callback()
chrome.stderr.on 'data', (data) ->
for logMsg in getConsoleLogs(data)
onLog.emit logMsg
return
process.once 'SIGINT', ->
chrome.kill()
onLog: onLog = signal.create()
kill: ->
chrome?.kill()
runAndLog = (env, logsReader, callback) ->
url = config.getBrowserHttpServerUrl()
chromeProcess = runOnPathWithUri env, url, ->
unless logsReader.terminated
error = "Chrome tests terminated before all tests ended"
callback error or logsReader.error
chromeProcess.onLog (msg) ->
logsReader.log msg
if logsReader.terminated
chromeProcess.kill()
exports.getName = (env) ->
{path} = env
if path
"Chrome #{env.path} #{env.platform} tests"
else
"Chrome #{env.platform} tests"
exports.run = (env, logsReader, callback) ->
if env.path
return runAndLog env, logsReader, callback
getChromePath (err, path) ->
if err
return callback err
env.path = path
exports.run env, logsReader, callback