neft
Version:
Universal Platform
136 lines (114 loc) • 4.18 kB
text/coffeescript
'use strict'
fs = require 'fs-extra'
pathUtils = require 'path'
childProcess = require 'child_process'
driver = require './driver'
findWindow = require './server/findWindow'
testScreenshot = require './server/testScreenshot'
server = require '../server'
targets = require '../cli/targets'
{utils, log} = Neft
DEST = 'tests_results'
INITIALIZATION_FILE_PATH = pathUtils.join DEST, 'initialization.png'
INITIALIZATION_TRIES = 20
INITIALIZATION_TRY_DELAY_SEC = 1
CUSTOM_SCREENSHOT_MAX_DELAY_MS = 1000
{LOG_SCREENSHOT_DATA_URI} = process.env
if LOG_SCREENSHOT_DATA_URI
imgur = require 'imgur'
imgur.setClientId '2ea624e59d38a21'
fs.emptyDirSync DEST
rects = {}
getPathWithBasename = (path, basename) ->
pathUtils.format utils.mergeAll {}, pathUtils.parse(path),
name: basename
base: undefined
getErrorFileUri = (path) ->
if LOG_SCREENSHOT_DATA_URI
file = fs.readFileSync path
base64 = new Buffer(file).toString 'base64'
return "data:image/png;base64,#{base64}"
path
getScreenshotError = (opts) ->
diffUri = do ->
if fs.existsSync(opts.diff)
getErrorFileUri opts.diff
else
'not found; image widths or heights differ'
expectedUri = do ->
if fs.existsSync(opts.expected)
getErrorFileUri opts.expected
else
'not found'
new Error """
Screenshot doesn't match with expected;
Path: #{getErrorFileUri opts.path}
Diff: #{diffUri}
Expected: #{expectedUri}
"""
takeScreenshot = (opts) ->
# use target-specified screenshot function
if opts.env
handler = targets.getEnvHandler(opts.env)
if handler.takeScreenshot
startTime = Date.now()
maxDelay = handler.TAKE_SCREENSHOT_DELAY_MS ? CUSTOM_SCREENSHOT_MAX_DELAY_MS
itertion = 0
while Date.now() < startTime + maxDelay
if itertion++ % 10 is 0
handler.takeScreenshot opts
try
stats = fs.statSync opts.path
if stats?.size
break
childProcess.execSync "sleep 0.1"
if stats?.size
return
else
log.warn """
#{opts.env.platform} custom screenshot handler failed; \
waited #{maxDelay} ms for a file; \
the whole screen is captured
"""
# take the whole screen screenshot
driver.takeScreenshot opts
return
server.onInitializeScreenshots (opts) ->
log "🎞 Initialize screenshots"
fs.emptyDirSync DEST
unless driver
throw new Error "Screenshots on this platform are not supported"
if opts.env
handler = targets.getEnvHandler(opts.env)
handler.onInitializeScreenshots? opts.env
opts.path = INITIALIZATION_FILE_PATH
tryNo = 0
while not rect and tryNo++ < INITIALIZATION_TRIES
takeScreenshot opts
rect = findWindow opts
unless rect
log "Cannot initialize screenshots; try #{tryNo} / #{INITIALIZATION_TRIES}"
childProcess.execSync "sleep #{INITIALIZATION_TRY_DELAY_SEC}"
if LOG_SCREENSHOT_DATA_URI
imgur.uploadFile(INITIALIZATION_FILE_PATH)
.then (json) -> log.info "Initialization screenshot: #{json.data.link}"
unless rect
throw new Error "Cannot find application on screenshot; check '#{opts.path}' file"
rects[opts.clientUid] = rect
return
server.onScreenshot (opts) ->
log "🎞 Take screenshot"
path = pathUtils.parse opts.expected
opts.name ?= path.name
opts.path = getPathWithBasename pathUtils.join(DEST, path.base), path.name
opts.diff = getPathWithBasename opts.path, "#{path.name}_diff"
opts.rect = rects[opts.clientUid]
takeScreenshot opts
if testScreenshot(opts)
fs.unlinkSync opts.diff
fs.unlinkSync opts.path
else
expectedCopyPath = getPathWithBasename opts.path, "#{path.name}_expected"
try fs.copySync opts.expected, expectedCopyPath
throw getScreenshotError opts
return