-
Notifications
You must be signed in to change notification settings - Fork 25
/
Copy pathviff.coffee
140 lines (108 loc) · 4.12 KB
/
viff.coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
_ = require 'underscore'
util = require 'util'
{EventEmitter} = require 'events'
Q = require 'q'
async = require 'async'
wd = require 'wd'
Comparison = require './comparison'
Testcase = require './testcase'
Capability = require './capability'
partialCanvas = require './canvas.drawimage'
dataUrlHelper = require './image.dataurl.helper'
class Viff extends EventEmitter
constructor: (seleniumHost) ->
EventEmitter.call @
@builder = wd.promiseChainRemote seleniumHost
@drivers = {}
takeScreenshot: (capability, host, url, callback) ->
that = @
defer = Q.defer()
defer.promise.then callback
capability = new Capability capability
unless driver = @drivers[capability.key()]
@drivers[capability.key()] = driver = @builder.init capability
[parsedUrl, selector, preHandle] = Testcase.parseUrl url
driver.get(host + parsedUrl).then ->
if _.isFunction preHandle
prepromise = Q.fcall () -> preHandle driver, wd
else
prepromise = Q()
prepromise.then ->
driver.takeScreenshot((err, base64Img) ->
if _.isString selector
Viff.dealWithPartial(base64Img, driver, selector, defer.resolve)
.catch defer.reject
else
defer.resolve new Buffer(base64Img, 'base64')
)
.catch defer.reject
defer.promise
@constructCases: (capabilities, envHosts, links) ->
cases = []
_.each links, (url) ->
_.each capabilities, (capability) ->
if _.isArray capability
[capabilityFrom, capabilityTo] = capability
_.each envHosts, (host, envName) ->
cases.push new Testcase(capabilityFrom, capabilityTo, host, host, envName, envName, url)
else
[[from, envFromHost], [to, envToHost]] = _.pairs envHosts
cases.push new Testcase(capability, capability, envFromHost, envToHost, from, to, url)
cases
@split: (cases, count) ->
groups = []
groups.push [] while count--
groups[idx % groups.length].push _case for idx, _case of cases
groups
run: (cases, callback) ->
defer = Q.defer()
defer.promise.then callback
that = this
@emit 'before', cases
start = Date.now()
async.eachSeries cases, (_case, next) ->
startcase = Date.now()
that.emit 'beforeEach', _case, 0
compareFrom = that.takeScreenshot _case.from.capability, _case.from.host, _case.url
Q.allSettled([compareFrom]).then ([fs]) ->
compareTo = that.takeScreenshot _case.to.capability, _case.to.host, _case.url
Q.allSettled([compareTo]).then ([ts]) ->
if fs.reason or ts.reason
that.emit 'afterEach', _case, 0, fs.reason, ts.reason
next()
else if fs.value and ts.value
Viff.runCase(_case, fs.value, ts.value).then (c) ->
that.emit 'afterEach', _case, Date.now() - startcase, fs.reason, ts.reason
next()
else
that.emit 'afterEach', _case, 0, fs.reason, ts.reason
next()
, (err) ->
endTime = Date.now() - start
that.emit 'after', cases, endTime
defer.resolve [cases, endTime]
that.closeDrivers()
defer.promise
@runCase: (_case, fromImage, toImage, callback) ->
imgWithEnvs = _.object [[_case.from.capability.key() + '-' + _case.from.name, fromImage], [_case.to.capability.key() + '-' + _case.to.name, toImage]]
comparison = new Comparison imgWithEnvs
diff = comparison.diff (diffImg) ->
_case.result = comparison
_case
callback && diff.then callback
diff
closeDrivers: () ->
@drivers[browser].quit() for browser of @drivers
@dealWithPartial: (base64Img, driver, selector, callback) ->
driver.elementByCss(selector)
.then (elem) ->
Q.all([elem.getLocation(), elem.getSize()]).then ([location, size]) ->
defer = Q.defer()
cvs = partialCanvas.get()
cvs.drawImage dataUrlHelper.toDataURL(base64Img), location, size, (data) ->
if data
defer.resolve new Buffer(dataUrlHelper.toData(data), 'base64')
else defer.resolve ''
defer.promise
.then callback
module.exports = Viff