diffux_ci 0.3.1 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/{diffux_ci → diffux} +15 -13
- data/lib/diffux_ci_runner.rb +47 -29
- data/lib/diffux_ci_version.rb +1 -1
- data/lib/public/diffux_ci-runner.js +63 -55
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e5143ca3e39e34a1ea00043f6f20814a72971b16
|
4
|
+
data.tar.gz: 6fced8ad6eccd338a886769b2ca755768ab9c0f9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 758fe05b11a9edcc343acc0cd9988615e2035432675e88de8b2837941f2c1704de1b9d6cd2a31102df05fd1b5276dc0a7b439b83a987a7e421e0b0177e7a8679
|
7
|
+
data.tar.gz: feb1f5d30adea55fc3fc0f467f1079eb629d09b15a6b0248ebfe60a91d2f2679a9e086a789c5822fbac5cf7611831358090be701aaa4ea7378e97859df8fe114
|
data/bin/{diffux_ci → diffux}
RENAMED
@@ -6,6 +6,19 @@ require 'diffux_ci_uploader'
|
|
6
6
|
require 'diffux_ci_version'
|
7
7
|
require 'fileutils'
|
8
8
|
|
9
|
+
help_text = <<-EOS
|
10
|
+
Commands:
|
11
|
+
run (default)
|
12
|
+
debug
|
13
|
+
review
|
14
|
+
clean
|
15
|
+
approve
|
16
|
+
reject
|
17
|
+
upload_diffs
|
18
|
+
--help
|
19
|
+
--version
|
20
|
+
EOS
|
21
|
+
|
9
22
|
action = ARGV[0] || 'run'
|
10
23
|
case action
|
11
24
|
when 'run'
|
@@ -44,18 +57,7 @@ when '--version'
|
|
44
57
|
puts "diffux_ci version #{DiffuxCI::VERSION}"
|
45
58
|
|
46
59
|
when '--help'
|
47
|
-
puts
|
48
|
-
Commands:
|
49
|
-
run (default)
|
50
|
-
debug
|
51
|
-
review
|
52
|
-
clean
|
53
|
-
approve
|
54
|
-
reject
|
55
|
-
upload_diffs
|
56
|
-
--help
|
57
|
-
--version
|
58
|
-
EOS
|
60
|
+
puts help_text
|
59
61
|
else
|
60
|
-
abort "Unknown action \"#{action}\""
|
62
|
+
abort "Unknown action \"#{action}\"\n\n#{help_text}"
|
61
63
|
end
|
data/lib/diffux_ci_runner.rb
CHANGED
@@ -50,30 +50,43 @@ begin
|
|
50
50
|
fail "JavaScript errors found during initialization: \n#{errors.inspect}"
|
51
51
|
end
|
52
52
|
|
53
|
-
|
54
|
-
|
55
|
-
#
|
56
|
-
#
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
53
|
+
all_examples = driver.execute_script('return window.diffux.getAllExamples()')
|
54
|
+
|
55
|
+
# To avoid the overhead of resizing the window all the time, we are going to
|
56
|
+
# render all examples for each given viewport size all in one go.
|
57
|
+
examples_by_viewport = {}
|
58
|
+
|
59
|
+
all_examples.each do |example|
|
60
|
+
viewports = resolve_viewports(example)
|
61
|
+
|
62
|
+
viewports.each do |viewport|
|
63
|
+
examples_by_viewport[viewport['name']] ||= {}
|
64
|
+
examples_by_viewport[viewport['name']][:viewport] ||= viewport
|
65
|
+
examples_by_viewport[viewport['name']][:examples] ||= []
|
66
|
+
|
67
|
+
examples_by_viewport[viewport['name']][:examples] << example
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
examples_by_viewport.each do |_, example_by_viewport|
|
72
|
+
viewport = example_by_viewport[:viewport]
|
73
|
+
examples = example_by_viewport[:examples]
|
74
|
+
|
75
|
+
puts "#{viewport['name']} (#{viewport['width']}x#{viewport['height']})"
|
76
|
+
|
77
|
+
# Resize window to the right size before rendering
|
78
|
+
driver.manage.window.resize_to(viewport['width'], viewport['height'])
|
79
|
+
|
80
|
+
examples.each do |example|
|
81
|
+
if example == examples.last
|
82
|
+
print '└─ '
|
71
83
|
else
|
72
|
-
|
84
|
+
print '├─ '
|
73
85
|
end
|
86
|
+
description = example['description']
|
87
|
+
print " #{description} "
|
74
88
|
|
75
|
-
|
76
|
-
driver.manage.window.resize_to(viewport['width'], viewport['height'])
|
89
|
+
print '.'
|
77
90
|
|
78
91
|
# Render the example
|
79
92
|
|
@@ -84,15 +97,16 @@ begin
|
|
84
97
|
# through to Rubyland), or until WebDriver's `script_timeout` is reached,
|
85
98
|
# before continuing. Since we don't define the signature of this function,
|
86
99
|
# we can't name the argument so we access it using JavaScript's magic
|
87
|
-
# arguments object and pass it down to `
|
100
|
+
# arguments object and pass it down to `renderExample()` which calls it
|
88
101
|
# when it is done--either synchronously if our example doesn't take an
|
89
102
|
# argument, or asynchronously via the Promise and `done` callback if it
|
90
103
|
# does.
|
91
104
|
script = <<-EOS
|
92
105
|
var doneFunc = arguments[arguments.length - 1];
|
93
|
-
window.diffux.
|
106
|
+
window.diffux.renderExample(arguments[0], doneFunc);
|
94
107
|
EOS
|
95
|
-
rendered = driver.execute_async_script(script)
|
108
|
+
rendered = driver.execute_async_script(script, description)
|
109
|
+
print '.'
|
96
110
|
|
97
111
|
if rendered['error']
|
98
112
|
fail <<-EOS
|
@@ -105,6 +119,7 @@ begin
|
|
105
119
|
|
106
120
|
# Crop the screenshot to the size of the rendered element
|
107
121
|
screenshot = ChunkyPNG::Image.from_blob(driver.screenshot_as(:png))
|
122
|
+
print '.'
|
108
123
|
|
109
124
|
# In our JavScript we are rounding up, which can sometimes give us a
|
110
125
|
# dimensions that are larger than the screenshot dimensions. We need to
|
@@ -122,8 +137,7 @@ begin
|
|
122
137
|
rendered['top'],
|
123
138
|
crop_width,
|
124
139
|
crop_height)
|
125
|
-
|
126
|
-
print "Checking \"#{description}\" at [#{viewport['name']}]... "
|
140
|
+
print '.'
|
127
141
|
|
128
142
|
# Run the diff if needed
|
129
143
|
baseline_path = DiffuxCIUtils.path_to(
|
@@ -136,6 +150,7 @@ begin
|
|
136
150
|
ChunkyPNG::Image.from_file(baseline_path),
|
137
151
|
screenshot
|
138
152
|
).compare!
|
153
|
+
print '.'
|
139
154
|
|
140
155
|
if comparison[:diff_image]
|
141
156
|
# There was a visual difference between the new snapshot and the
|
@@ -144,16 +159,18 @@ begin
|
|
144
159
|
diff_path = DiffuxCIUtils.path_to(
|
145
160
|
description, viewport['name'], 'diff.png')
|
146
161
|
comparison[:diff_image].save(diff_path, :fast_rgba)
|
162
|
+
print '.'
|
147
163
|
|
148
164
|
candidate_path = DiffuxCIUtils.path_to(
|
149
165
|
description, viewport['name'], 'candidate.png')
|
150
166
|
screenshot.save(candidate_path, :fast_rgba)
|
167
|
+
print '.'
|
151
168
|
|
152
|
-
puts "#{comparison[:diff_in_percent].round(1)}% (#{candidate_path})"
|
169
|
+
puts " #{comparison[:diff_in_percent].round(1)}% (#{candidate_path})"
|
153
170
|
else
|
154
171
|
# No visual difference was found, so we don't need to do any more
|
155
172
|
# work.
|
156
|
-
puts 'No diff.'
|
173
|
+
puts ' No diff.'
|
157
174
|
end
|
158
175
|
else
|
159
176
|
# There was no baseline image yet, so we want to start by saving a new
|
@@ -164,7 +181,8 @@ begin
|
|
164
181
|
FileUtils.mkdir_p(dirname)
|
165
182
|
end
|
166
183
|
screenshot.save(baseline_path, :fast_rgba)
|
167
|
-
|
184
|
+
print '.'
|
185
|
+
puts " First snapshot created (#{baseline_path})"
|
168
186
|
end
|
169
187
|
end
|
170
188
|
end
|
data/lib/diffux_ci_version.rb
CHANGED
@@ -1,52 +1,52 @@
|
|
1
1
|
'use strict';
|
2
2
|
|
3
3
|
window.diffux = {
|
4
|
-
defined:
|
5
|
-
|
6
|
-
currentExample: undefined,
|
4
|
+
defined: {},
|
5
|
+
fdefined: [],
|
7
6
|
currentRenderedElement: undefined,
|
8
7
|
errors: [],
|
9
8
|
|
10
9
|
define: function(description, func, options) {
|
11
|
-
|
10
|
+
// Make sure we don't have a duplicate description
|
11
|
+
if (this.defined[description]) {
|
12
|
+
throw 'Error while defining "' + description +
|
13
|
+
'": Duplicate description detected'
|
14
|
+
}
|
15
|
+
this.defined[description] = {
|
12
16
|
description: description,
|
13
17
|
func: func,
|
14
18
|
options: options || {}
|
15
|
-
}
|
19
|
+
};
|
16
20
|
},
|
17
21
|
|
18
|
-
fdefine: function() {
|
19
|
-
this.
|
20
|
-
this.
|
21
|
-
this.define = function() {}; // make `define` a no-op from now on
|
22
|
+
fdefine: function(description, func, options) {
|
23
|
+
this.define(description, func, options); // add the example
|
24
|
+
this.fdefined.push(description);
|
22
25
|
},
|
23
26
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
27
|
+
/**
|
28
|
+
* @return {Array.<Object>}
|
29
|
+
*/
|
30
|
+
getAllExamples: function() {
|
31
|
+
var descriptions = Object.keys(this.defined);
|
32
|
+
|
33
|
+
if (this.fdefined.length) {
|
34
|
+
// Some examples have been focused, so we want to filter out anything that
|
35
|
+
// has not been focused.
|
36
|
+
descriptions = descriptions.filter(function(description) {
|
37
|
+
return this.fdefined.indexOf(description) !== -1;
|
38
|
+
}.bind(this));
|
36
39
|
}
|
37
|
-
this.currentIndex++;
|
38
|
-
return this.currentExample;
|
39
|
-
},
|
40
40
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
41
|
+
return descriptions.map(function(description) {
|
42
|
+
var example = this.defined[description];
|
43
|
+
// We return a subset of the properties of an example (only those relevant
|
44
|
+
// for diffux_runner.rb).
|
45
|
+
return {
|
46
|
+
description: example.description,
|
47
|
+
options: example.options,
|
48
|
+
};
|
46
49
|
}.bind(this));
|
47
|
-
if (!this.currentExample) {
|
48
|
-
throw 'No example found with description "' + exampleDescription + '"';
|
49
|
-
}
|
50
50
|
},
|
51
51
|
|
52
52
|
isElementVisible: function(element) {
|
@@ -66,10 +66,10 @@ window.diffux = {
|
|
66
66
|
}
|
67
67
|
},
|
68
68
|
|
69
|
-
handleError: function(error) {
|
69
|
+
handleError: function(currentExample, error) {
|
70
70
|
console.error(error);
|
71
71
|
return {
|
72
|
-
description:
|
72
|
+
description: currentExample.description,
|
73
73
|
error: error.message
|
74
74
|
};
|
75
75
|
},
|
@@ -107,49 +107,58 @@ window.diffux = {
|
|
107
107
|
},
|
108
108
|
|
109
109
|
/**
|
110
|
+
* Clean up the DOM for a rendered element that has already been processed.
|
111
|
+
*
|
112
|
+
* @param {Object} renderedElement
|
113
|
+
*/
|
114
|
+
cleanOutElement: function(renderedElement) {
|
115
|
+
renderedElement.parentNode.removeChild(renderedElement);
|
116
|
+
},
|
117
|
+
|
118
|
+
/**
|
119
|
+
* @param {String} exampleDescription
|
110
120
|
* @param {Function} doneFunc injected by driver.execute_async_script in
|
111
121
|
* diffux_ci_runner.rb
|
112
122
|
*/
|
113
|
-
|
123
|
+
renderExample: function(exampleDescription, doneFunc) {
|
124
|
+
var currentExample = this.defined[exampleDescription];
|
125
|
+
if (!currentExample) {
|
126
|
+
throw 'No example found with description "' + exampleDescription + '"';
|
127
|
+
}
|
128
|
+
|
114
129
|
try {
|
130
|
+
if (this.currentRenderedElement) {
|
131
|
+
this.cleanOutElement(this.currentRenderedElement);
|
132
|
+
}
|
115
133
|
this.clearVisibleElements();
|
116
134
|
|
117
|
-
var func =
|
135
|
+
var func = currentExample.func;
|
118
136
|
if (func.length) {
|
119
137
|
// The function takes an argument, which is a callback that is called
|
120
138
|
// once it is done executing. This can be used to write functions that
|
121
139
|
// have asynchronous code in them.
|
122
140
|
this.tryAsync(func).then(function(elem) {
|
123
|
-
doneFunc(this.processElem(elem));
|
141
|
+
doneFunc(this.processElem(currentExample, elem));
|
124
142
|
}.bind(this)).catch(function(error) {
|
125
|
-
doneFunc(this.handleError(error));
|
143
|
+
doneFunc(this.handleError(currentExample, error));
|
126
144
|
}.bind(this));
|
127
145
|
} else {
|
128
146
|
// The function does not take an argument, so we can run it
|
129
147
|
// synchronously.
|
130
148
|
var elem = func();
|
131
|
-
doneFunc(this.processElem(elem));
|
149
|
+
doneFunc(this.processElem(currentExample, elem));
|
132
150
|
}
|
133
151
|
} catch (error) {
|
134
|
-
doneFunc(this.handleError(error));
|
152
|
+
doneFunc(this.handleError(currentExample, error));
|
135
153
|
}
|
136
154
|
},
|
137
155
|
|
138
|
-
processElem: function(elem) {
|
156
|
+
processElem: function(currentExample, elem) {
|
139
157
|
try {
|
140
|
-
// TODO: elem.getDOMNode is deprecated in React, so we need to convert
|
141
|
-
// this to ReactDOM.findDOMNode(elem) at some point, or push this
|
142
|
-
// requirement into the examples.
|
143
|
-
if (elem.getDOMNode) {
|
144
|
-
// Soft-dependency to React here. If the thing returned has a
|
145
|
-
// `getDOMNode` method, call it to get the real DOM node.
|
146
|
-
elem = elem.getDOMNode();
|
147
|
-
}
|
148
|
-
|
149
158
|
this.currentRenderedElement = elem;
|
150
159
|
|
151
160
|
var rect;
|
152
|
-
if (
|
161
|
+
if (currentExample.options.snapshotEntireScreen) {
|
153
162
|
rect = {
|
154
163
|
width: window.innerWidth,
|
155
164
|
height: window.innerHeight,
|
@@ -168,14 +177,14 @@ window.diffux = {
|
|
168
177
|
}
|
169
178
|
|
170
179
|
return {
|
171
|
-
description:
|
180
|
+
description: currentExample.description,
|
172
181
|
width: Math.ceil(rect.width),
|
173
182
|
height: Math.ceil(rect.height),
|
174
183
|
top: Math.floor(rect.top),
|
175
184
|
left: Math.floor(rect.left),
|
176
185
|
};
|
177
186
|
} catch (error) {
|
178
|
-
return this.handleError(error);
|
187
|
+
return this.handleError(currentExample, error);
|
179
188
|
}
|
180
189
|
}
|
181
190
|
};
|
@@ -186,8 +195,7 @@ window.addEventListener('load', function() {
|
|
186
195
|
return;
|
187
196
|
}
|
188
197
|
var example = decodeURIComponent(matches[1]);
|
189
|
-
window.diffux.
|
190
|
-
window.diffux.renderCurrent(function() {});
|
198
|
+
window.diffux.renderExample(example, function() {});
|
191
199
|
});
|
192
200
|
|
193
201
|
// We need to redefine a few global functions that halt execution. Without this,
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: diffux_ci
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Henric Trotzig
|
@@ -130,11 +130,11 @@ email:
|
|
130
130
|
- henric.trotzig@gmail.com
|
131
131
|
- joe.lencioni@gmail.com
|
132
132
|
executables:
|
133
|
-
-
|
133
|
+
- diffux
|
134
134
|
extensions: []
|
135
135
|
extra_rdoc_files: []
|
136
136
|
files:
|
137
|
-
- bin/
|
137
|
+
- bin/diffux
|
138
138
|
- lib/diffux_ci-diffs.html.erb
|
139
139
|
- lib/diffux_ci_action.rb
|
140
140
|
- lib/diffux_ci_runner.rb
|
@@ -167,7 +167,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
167
167
|
version: '0'
|
168
168
|
requirements: []
|
169
169
|
rubyforge_project:
|
170
|
-
rubygems_version: 2.4.5
|
170
|
+
rubygems_version: 2.4.5.1
|
171
171
|
signing_key:
|
172
172
|
specification_version: 4
|
173
173
|
summary: Diffux-CI
|