diffux_ci 0.1.0 → 0.2.0
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 +21 -3
- data/lib/diffux_ci-diffs.html.erb +1 -1
- data/lib/diffux_ci_action.rb +13 -11
- data/lib/diffux_ci_runner.rb +70 -33
- data/lib/diffux_ci_server.rb +7 -2
- data/lib/diffux_ci_uploader.rb +5 -6
- data/lib/diffux_ci_utils.rb +18 -19
- data/lib/diffux_ci_version.rb +4 -0
- data/lib/public/diffux_ci-runner.js +23 -14
- data/lib/public/diffux_ci-styles.css +8 -0
- data/lib/views/debug.erb +28 -0
- data/lib/views/review.erb +5 -13
- metadata +8 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2670d7b6c223c5706a067d1ca10528f02a7b4e7d
|
4
|
+
data.tar.gz: 1192da6f79d208279ef7fba9ae5ac8339f425893
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d09b57e16639125db313eb1786533bc26899ac703de45d04c4aa558c33588ce6f772ceb17e3d899e5f9c36c5fbd0ec45b64bbf0f224a100b735b90941a3df56f
|
7
|
+
data.tar.gz: bc514a8739c934f932393b2face0dbd06f0d7a926561f526ea6baddccb8b18ee7a3f63e296bedfa760197f7e598508c9e5722abd506718983b493de7d3fcee82
|
data/bin/diffux_ci
CHANGED
@@ -15,6 +15,10 @@ when 'run'
|
|
15
15
|
end
|
16
16
|
require 'diffux_ci_server'
|
17
17
|
|
18
|
+
when 'debug'
|
19
|
+
system 'open', DiffuxCIUtils.construct_url('/debug')
|
20
|
+
require 'diffux_ci_server'
|
21
|
+
|
18
22
|
when 'review'
|
19
23
|
system 'open', DiffuxCIUtils.construct_url('/review')
|
20
24
|
require 'diffux_ci_server'
|
@@ -25,13 +29,27 @@ when 'clean'
|
|
25
29
|
end
|
26
30
|
|
27
31
|
when 'approve', 'reject'
|
28
|
-
|
29
|
-
abort 'Missing
|
30
|
-
|
32
|
+
example_description = ARGV[1]
|
33
|
+
abort 'Missing example description' unless example_description
|
34
|
+
viewport_name = ARGV[2]
|
35
|
+
abort 'Missing viewport name' unless viewport_name
|
36
|
+
DiffuxCIAction.new(example_description, viewport_name).send(action)
|
31
37
|
|
32
38
|
when 'upload_diffs'
|
33
39
|
# `upload_diffs` returns a URL to a static html file
|
34
40
|
puts DiffuxCIUploader.new.upload_diffs
|
41
|
+
|
42
|
+
when '--help'
|
43
|
+
puts <<-EOS
|
44
|
+
Commands:
|
45
|
+
run (default)
|
46
|
+
debug
|
47
|
+
review
|
48
|
+
clean
|
49
|
+
approve
|
50
|
+
reject
|
51
|
+
upload_diffs
|
52
|
+
EOS
|
35
53
|
else
|
36
54
|
abort "Unknown action \"#{action}\""
|
37
55
|
end
|
data/lib/diffux_ci_action.rb
CHANGED
@@ -2,26 +2,28 @@ require 'diffux_ci_utils'
|
|
2
2
|
require 'fileutils'
|
3
3
|
|
4
4
|
class DiffuxCIAction
|
5
|
-
def initialize(
|
6
|
-
@
|
5
|
+
def initialize(example_description, viewport_name)
|
6
|
+
@example_description = example_description
|
7
7
|
@viewport_name = viewport_name
|
8
8
|
end
|
9
9
|
|
10
10
|
def approve
|
11
|
-
diff_path = DiffuxCIUtils.path_to(
|
12
|
-
|
13
|
-
|
11
|
+
diff_path = DiffuxCIUtils.path_to(
|
12
|
+
@example_description, @viewport_name, 'diff.png')
|
13
|
+
baseline_path = DiffuxCIUtils.path_to(
|
14
|
+
@example_description, @viewport_name, 'baseline.png')
|
15
|
+
candidate_path = DiffuxCIUtils.path_to(
|
16
|
+
@example_description, @viewport_name, 'candidate.png')
|
14
17
|
|
15
18
|
FileUtils.rm(diff_path, force: true)
|
16
|
-
|
17
|
-
if File.exist? candidate_path
|
18
|
-
FileUtils.mv(candidate_path, baseline_path)
|
19
|
-
end
|
19
|
+
FileUtils.mv(candidate_path, baseline_path) if File.exist? candidate_path
|
20
20
|
end
|
21
21
|
|
22
22
|
def reject
|
23
|
-
diff_path = DiffuxCIUtils.path_to(
|
24
|
-
|
23
|
+
diff_path = DiffuxCIUtils.path_to(
|
24
|
+
@example_description, @viewport_name, 'diff.png')
|
25
|
+
candidate_path = DiffuxCIUtils.path_to(
|
26
|
+
@example_description, @viewport_name, 'candidate.png')
|
25
27
|
|
26
28
|
FileUtils.rm(diff_path, force: true)
|
27
29
|
FileUtils.rm(candidate_path, force: true)
|
data/lib/diffux_ci_runner.rb
CHANGED
@@ -5,26 +5,32 @@ require 'diffux_core/snapshot_comparison_image/gutter'
|
|
5
5
|
require 'diffux_core/snapshot_comparison_image/before'
|
6
6
|
require 'diffux_core/snapshot_comparison_image/overlayed'
|
7
7
|
require 'diffux_core/snapshot_comparison_image/after'
|
8
|
-
require '
|
8
|
+
require 'oily_png'
|
9
9
|
require 'diffux_ci_utils'
|
10
10
|
require 'fileutils'
|
11
11
|
|
12
12
|
def resolve_viewports(example)
|
13
13
|
configured_viewports = DiffuxCIUtils.config['viewports']
|
14
14
|
|
15
|
-
|
15
|
+
viewports =
|
16
|
+
example['options']['viewports'] || [configured_viewports.first.first]
|
17
|
+
|
18
|
+
viewports.map do |viewport|
|
16
19
|
configured_viewports[viewport].merge('name' => viewport)
|
17
20
|
end
|
18
21
|
end
|
19
22
|
|
23
|
+
tries = 0
|
20
24
|
begin
|
21
25
|
driver = Selenium::WebDriver.for DiffuxCIUtils.config['driver'].to_sym
|
22
|
-
rescue Selenium::WebDriver::Error::WebDriverError
|
26
|
+
rescue Selenium::WebDriver::Error::WebDriverError => e
|
23
27
|
# "unable to obtain stable firefox connection in 60 seconds"
|
24
28
|
#
|
25
29
|
# This seems to happen sporadically for some versions of Firefox, so we want
|
26
|
-
# to retry it in case it will work the second time around.
|
27
|
-
|
30
|
+
# to retry a couple of times it in case it will work the second time around.
|
31
|
+
tries += 1
|
32
|
+
retry if tries <= 3
|
33
|
+
raise e
|
28
34
|
end
|
29
35
|
|
30
36
|
begin
|
@@ -37,8 +43,28 @@ begin
|
|
37
43
|
fail "JavaScript errors found during initialization: \n#{errors.inspect}"
|
38
44
|
end
|
39
45
|
|
46
|
+
# We use the description of the example to store the snapshot. If a
|
47
|
+
# description is duplicated with different code, it can cause seemingly random
|
48
|
+
# and confusing differences. To avoid this issue, we want to keep track of the
|
49
|
+
# descriptions that we've seen and fail if we come across the same description
|
50
|
+
# twice.
|
51
|
+
seen_descriptions = {}
|
52
|
+
|
40
53
|
while current = driver.execute_script('return window.diffux.next()') do
|
54
|
+
description = current['description']
|
55
|
+
|
41
56
|
resolve_viewports(current).each do |viewport|
|
57
|
+
# Make sure we don't have a duplicate description
|
58
|
+
seen_descriptions[description] ||= {}
|
59
|
+
if seen_descriptions[description][viewport['name']]
|
60
|
+
fail <<-EOS
|
61
|
+
Error while rendering "#{description}" @#{viewport['name']}:
|
62
|
+
Duplicate description detected
|
63
|
+
EOS
|
64
|
+
else
|
65
|
+
seen_descriptions[description][viewport['name']] = true
|
66
|
+
end
|
67
|
+
|
42
68
|
# Resize window to the right size before rendering
|
43
69
|
driver.manage.window.resize_to(viewport['width'], viewport['height'])
|
44
70
|
|
@@ -63,51 +89,62 @@ begin
|
|
63
89
|
|
64
90
|
if rendered['error']
|
65
91
|
fail <<-EOS
|
66
|
-
Error while rendering "#{
|
92
|
+
Error while rendering "#{description}" @#{viewport['name']}:
|
67
93
|
#{rendered['error']}
|
68
94
|
Debug by pointing your browser to
|
69
|
-
#{DiffuxCIUtils.construct_url('/',
|
95
|
+
#{DiffuxCIUtils.construct_url('/', description: description)}
|
70
96
|
EOS
|
71
97
|
end
|
72
|
-
output_file = DiffuxCIUtils.path_to(
|
73
|
-
current['name'], viewport['name'], 'candidate.png')
|
74
|
-
|
75
|
-
# Create the folder structure if it doesn't already exist
|
76
|
-
unless File.directory?(dirname = File.dirname(output_file))
|
77
|
-
FileUtils.mkdir_p(dirname)
|
78
|
-
end
|
79
98
|
|
80
|
-
#
|
81
|
-
driver.
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
[rendered['height'], 1].max)
|
87
|
-
cropped.save(output_file)
|
99
|
+
# Crop the screenshot to the size of the rendered element
|
100
|
+
screenshot = ChunkyPNG::Image.from_blob(driver.screenshot_as(:png))
|
101
|
+
screenshot.crop!(rendered['left'],
|
102
|
+
rendered['top'],
|
103
|
+
[rendered['width'], 1].max,
|
104
|
+
[rendered['height'], 1].max)
|
88
105
|
|
89
|
-
print "Checking \"#{
|
106
|
+
print "Checking \"#{description}\" at [#{viewport['name']}]... "
|
90
107
|
|
91
108
|
# Run the diff if needed
|
92
|
-
|
109
|
+
baseline_path = DiffuxCIUtils.path_to(
|
110
|
+
description, viewport['name'], 'baseline.png')
|
93
111
|
|
94
|
-
if File.exist?
|
112
|
+
if File.exist? baseline_path
|
113
|
+
# A baseline image exists, so we want to compare the new snapshot
|
114
|
+
# against the baseline.
|
95
115
|
comparison = Diffux::SnapshotComparer.new(
|
96
|
-
ChunkyPNG::Image.from_file(
|
97
|
-
|
116
|
+
ChunkyPNG::Image.from_file(baseline_path),
|
117
|
+
screenshot
|
98
118
|
).compare!
|
99
119
|
|
100
|
-
if
|
101
|
-
|
102
|
-
|
120
|
+
if comparison[:diff_image]
|
121
|
+
# There was a visual difference between the new snapshot and the
|
122
|
+
# baseline, so we want to write the diff image and the new snapshot
|
123
|
+
# image to disk. This will allow it to be reviewed by someone.
|
124
|
+
diff_path = DiffuxCIUtils.path_to(
|
125
|
+
description, viewport['name'], 'diff.png')
|
126
|
+
comparison[:diff_image].save(diff_path)
|
127
|
+
|
128
|
+
candidate_path = DiffuxCIUtils.path_to(
|
129
|
+
description, viewport['name'], 'candidate.png')
|
130
|
+
screenshot.save(candidate_path)
|
131
|
+
|
103
132
|
puts "#{comparison[:diff_in_percent].round(1)}% (#{diff_output})"
|
104
133
|
else
|
105
|
-
|
134
|
+
# No visual difference was found, so we don't need to do any more
|
135
|
+
# work.
|
106
136
|
puts 'No diff.'
|
107
137
|
end
|
108
138
|
else
|
109
|
-
|
110
|
-
|
139
|
+
# There was no baseline image yet, so we want to start by saving a new
|
140
|
+
# baseline image.
|
141
|
+
|
142
|
+
# Create the folder structure if it doesn't already exist
|
143
|
+
unless File.directory?(dirname = File.dirname(baseline_path))
|
144
|
+
FileUtils.mkdir_p(dirname)
|
145
|
+
end
|
146
|
+
screenshot.save(baseline_path)
|
147
|
+
puts "First snapshot created (#{baseline_path})"
|
111
148
|
end
|
112
149
|
end
|
113
150
|
end
|
data/lib/diffux_ci_server.rb
CHANGED
@@ -14,6 +14,11 @@ class DiffuxCIServer < Sinatra::Base
|
|
14
14
|
erb :index
|
15
15
|
end
|
16
16
|
|
17
|
+
get '/debug' do
|
18
|
+
@config = DiffuxCIUtils.config
|
19
|
+
erb :debug
|
20
|
+
end
|
21
|
+
|
17
22
|
get '/review' do
|
18
23
|
@snapshots = DiffuxCIUtils.current_snapshots
|
19
24
|
erb :review
|
@@ -29,12 +34,12 @@ class DiffuxCIServer < Sinatra::Base
|
|
29
34
|
end
|
30
35
|
|
31
36
|
post '/reject' do
|
32
|
-
DiffuxCIAction.new(params[:
|
37
|
+
DiffuxCIAction.new(params[:description], params[:viewport]).reject
|
33
38
|
redirect back
|
34
39
|
end
|
35
40
|
|
36
41
|
post '/approve' do
|
37
|
-
DiffuxCIAction.new(params[:
|
42
|
+
DiffuxCIAction.new(params[:description], params[:viewport]).approve
|
38
43
|
redirect back
|
39
44
|
end
|
40
45
|
|
data/lib/diffux_ci_uploader.rb
CHANGED
@@ -19,7 +19,8 @@ class DiffuxCIUploader
|
|
19
19
|
dir = SecureRandom.uuid
|
20
20
|
|
21
21
|
diff_images = current_snapshots[:diffs].map do |diff|
|
22
|
-
image = bucket.objects.build(
|
22
|
+
image = bucket.objects.build(
|
23
|
+
"#{dir}/#{diff[:description]}_#{diff[:viewport]}.png")
|
23
24
|
image.content = open(diff[:file])
|
24
25
|
image.content_type = 'image/png'
|
25
26
|
image.save
|
@@ -28,11 +29,9 @@ class DiffuxCIUploader
|
|
28
29
|
end
|
29
30
|
|
30
31
|
html = bucket.objects.build("#{dir}/index.html")
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
File.join(File.dirname(__FILE__), 'diffux_ci-diffs.html.erb')))
|
35
|
-
).result(binding)
|
32
|
+
path = File.expand_path(
|
33
|
+
File.join(File.dirname(__FILE__), 'diffux_ci-diffs.html.erb'))
|
34
|
+
html.content = ERB.new(File.read(path)).result(binding)
|
36
35
|
html.content_type = 'text/html'
|
37
36
|
html.save
|
38
37
|
html.url
|
data/lib/diffux_ci_utils.rb
CHANGED
@@ -3,6 +3,7 @@ require 'erb'
|
|
3
3
|
|
4
4
|
class DiffuxCIUtils
|
5
5
|
def self.config
|
6
|
+
config_file_name = ENV['DIFFUX_CI_CONFIG_FILE'] || '.diffux_ci.yaml'
|
6
7
|
@@config ||= {
|
7
8
|
'snapshots_folder' => './snapshots',
|
8
9
|
'source_files' => [],
|
@@ -23,46 +24,44 @@ class DiffuxCIUtils
|
|
23
24
|
'height' => 444
|
24
25
|
}
|
25
26
|
}
|
26
|
-
}.merge(YAML.load(ERB.new(File.read(
|
27
|
-
ENV['DIFFUX_CI_CONFIG_FILE'] || '.diffux_ci.yaml')).result))
|
27
|
+
}.merge(YAML.load(ERB.new(File.read(config_file_name)).result))
|
28
28
|
end
|
29
29
|
|
30
|
-
def self.
|
31
|
-
|
30
|
+
def self.normalize_description(description)
|
31
|
+
description.gsub(/[^a-zA-Z0-9\-_]/, '_')
|
32
32
|
end
|
33
33
|
|
34
|
-
def self.path_to(
|
34
|
+
def self.path_to(description, viewport_name, file_name)
|
35
35
|
File.join(
|
36
36
|
config['snapshots_folder'],
|
37
|
-
|
37
|
+
normalize_description(description),
|
38
38
|
"@#{viewport_name}",
|
39
39
|
file_name
|
40
40
|
)
|
41
41
|
end
|
42
42
|
|
43
43
|
def self.construct_url(absolute_path, params = {})
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
params_str = "?#{params_str}"
|
49
|
-
end
|
50
|
-
|
51
|
-
return "http://localhost:#{config['port']}#{absolute_path}#{params_str}"
|
44
|
+
URI::HTTP.build(host: 'localhost',
|
45
|
+
port: config['port'],
|
46
|
+
path: absolute_path,
|
47
|
+
query: URI.encode_www_form(params))
|
52
48
|
end
|
53
49
|
|
54
50
|
def self.current_snapshots
|
55
51
|
prepare_file = lambda do |file|
|
56
52
|
viewport_dir = File.expand_path('..', file)
|
57
|
-
|
53
|
+
description_dir = File.expand_path('..', viewport_dir)
|
58
54
|
{
|
59
|
-
|
55
|
+
description: File.basename(description_dir),
|
60
56
|
viewport: File.basename(viewport_dir).sub('@', ''),
|
61
|
-
file: file
|
57
|
+
file: file
|
62
58
|
}
|
63
59
|
end
|
64
|
-
|
65
|
-
|
60
|
+
|
61
|
+
snapshots_folder = DiffuxCIUtils.config['snapshots_folder']
|
62
|
+
diff_files = Dir.glob("#{snapshots_folder}/**/diff.png")
|
63
|
+
baselines = Dir.glob("#{snapshots_folder}/**/baseline.png")
|
64
|
+
|
66
65
|
{
|
67
66
|
diffs: diff_files.map(&prepare_file),
|
68
67
|
baselines: baselines.map(&prepare_file)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
1
3
|
window.diffux = {
|
2
4
|
defined: [],
|
3
5
|
currentIndex: 0,
|
@@ -5,9 +7,9 @@ window.diffux = {
|
|
5
7
|
currentRenderedElement: undefined,
|
6
8
|
errors: [],
|
7
9
|
|
8
|
-
define: function(
|
10
|
+
define: function(description, func, options) {
|
9
11
|
this.defined.push({
|
10
|
-
|
12
|
+
description: description,
|
11
13
|
func: func,
|
12
14
|
options: options || {}
|
13
15
|
});
|
@@ -24,7 +26,8 @@ window.diffux = {
|
|
24
26
|
if (window.React) {
|
25
27
|
window.React.unmountComponentAtNode(document.body.lastChild);
|
26
28
|
} else {
|
27
|
-
this.currentRenderedElement.parentNode
|
29
|
+
this.currentRenderedElement.parentNode
|
30
|
+
.removeChild(this.currentRenderedElement);
|
28
31
|
}
|
29
32
|
}
|
30
33
|
this.currentExample = this.defined[this.currentIndex];
|
@@ -35,31 +38,31 @@ window.diffux = {
|
|
35
38
|
return this.currentExample;
|
36
39
|
},
|
37
40
|
|
38
|
-
setCurrent: function(
|
41
|
+
setCurrent: function(exampleDescription) {
|
39
42
|
this.defined.forEach(function(example, index) {
|
40
|
-
if (example.
|
43
|
+
if (example.description === exampleDescription) {
|
41
44
|
this.currentExample = example;
|
42
45
|
}
|
43
46
|
}.bind(this));
|
44
47
|
if (!this.currentExample) {
|
45
|
-
throw 'No example found with
|
48
|
+
throw 'No example found with description "' + exampleDescription + '"';
|
46
49
|
}
|
47
50
|
},
|
48
51
|
|
49
52
|
clearVisibleElements: function() {
|
50
|
-
var allElements =
|
51
|
-
|
53
|
+
var allElements = document.querySelectorAll('body > *');
|
54
|
+
for (var element of allElements) {
|
52
55
|
var style = window.getComputedStyle(element);
|
53
56
|
if (style.display !== 'none') {
|
54
57
|
element.parentNode.removeChild(element);
|
55
58
|
}
|
56
|
-
}
|
59
|
+
}
|
57
60
|
},
|
58
61
|
|
59
62
|
handleError: function(error) {
|
60
63
|
console.error(error);
|
61
64
|
return {
|
62
|
-
|
65
|
+
description: this.currentExample.description,
|
63
66
|
error: error.message
|
64
67
|
};
|
65
68
|
},
|
@@ -150,7 +153,7 @@ window.diffux = {
|
|
150
153
|
left = 0;
|
151
154
|
}
|
152
155
|
return {
|
153
|
-
|
156
|
+
description: this.currentExample.description,
|
154
157
|
width: width,
|
155
158
|
height: height,
|
156
159
|
top: top,
|
@@ -163,13 +166,13 @@ window.diffux = {
|
|
163
166
|
};
|
164
167
|
|
165
168
|
window.addEventListener('load', function() {
|
166
|
-
var matches = window.location.search.match(/
|
169
|
+
var matches = window.location.search.match(/description=([^&]*)/);
|
167
170
|
if (!matches) {
|
168
171
|
return;
|
169
172
|
}
|
170
173
|
var example = decodeURIComponent(matches[1]);
|
171
174
|
window.diffux.setCurrent(example);
|
172
|
-
window.diffux.renderCurrent();
|
175
|
+
window.diffux.renderCurrent(function() {});
|
173
176
|
});
|
174
177
|
|
175
178
|
// We need to redefine a few global functions that halt execution. Without this,
|
@@ -177,15 +180,21 @@ window.addEventListener('load', function() {
|
|
177
180
|
window.alert = function(message) {
|
178
181
|
console.log('`window.alert` called', message);
|
179
182
|
};
|
183
|
+
|
180
184
|
window.confirm = function(message) {
|
181
185
|
console.log('`window.confirm` called', message);
|
182
186
|
return true;
|
183
187
|
};
|
188
|
+
|
184
189
|
window.prompt = function(message, value) {
|
185
190
|
console.log('`window.prompt` called', message, value);
|
186
191
|
return null;
|
187
192
|
};
|
188
193
|
|
189
194
|
window.onerror = function(message, url, lineNumber) {
|
190
|
-
window.diffux.errors.push({
|
195
|
+
window.diffux.errors.push({
|
196
|
+
message: message,
|
197
|
+
url: url,
|
198
|
+
lineNumber: lineNumber
|
199
|
+
});
|
191
200
|
}
|
data/lib/views/debug.erb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<link rel="stylesheet" href="/diffux_ci-styles.css"></link>
|
5
|
+
<script src="/diffux_ci-runner.js"></script>
|
6
|
+
<% @config['source_files'].each do |source_file| %>
|
7
|
+
<script src="/resource?file=<%= ERB::Util.url_encode(source_file) %>"></script>
|
8
|
+
<% end %>
|
9
|
+
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
|
10
|
+
</head>
|
11
|
+
<body>
|
12
|
+
<h1>Diffux-CI Debug Tool</h1>
|
13
|
+
<p>Click on an item to render that example in isolation.</p>
|
14
|
+
<script>
|
15
|
+
(function() {
|
16
|
+
var ul = $('<ul>');
|
17
|
+
$('body').append(ul);
|
18
|
+
$.each(diffux.defined, function(_, example) {
|
19
|
+
ul.append($('<li>').append(
|
20
|
+
$('<a>', {
|
21
|
+
href: '/?description=' + encodeURIComponent(example.description)
|
22
|
+
}).text(example.description)
|
23
|
+
));
|
24
|
+
});
|
25
|
+
}());
|
26
|
+
</script>
|
27
|
+
</body>
|
28
|
+
</html>
|
data/lib/views/review.erb
CHANGED
@@ -1,31 +1,23 @@
|
|
1
1
|
<!DOCTYPE html>
|
2
2
|
<html>
|
3
3
|
<head>
|
4
|
-
<
|
5
|
-
body {
|
6
|
-
background-color: #f0f0f0;
|
7
|
-
font-family: helvetica, arial;
|
8
|
-
}
|
9
|
-
form {
|
10
|
-
display: inline-block;
|
11
|
-
}
|
12
|
-
</style>
|
4
|
+
<link rel="stylesheet" href="/diffux_ci-styles.css"></link>
|
13
5
|
</head>
|
14
6
|
<body>
|
15
7
|
<h1>Diffux-CI Review Tool</h1>
|
16
8
|
<h2>DIFFS</h2>
|
17
9
|
<% @snapshots[:diffs].each do |diff| %>
|
18
10
|
<h3>
|
19
|
-
<%= diff[:
|
11
|
+
<%= diff[:description] %> @ <%= diff[:viewport] %>
|
20
12
|
</h3>
|
21
13
|
<p><img src="/resource?file=<%= ERB::Util.url_encode(diff[:file]) %>"></p>
|
22
14
|
<form style="display: inline-block"
|
23
|
-
action="/approve?
|
15
|
+
action="/approve?description=<%= diff[:description] %>&viewport=<%= diff[:viewport] %>"
|
24
16
|
method="POST">
|
25
17
|
<button type="submit">Approve</button>
|
26
18
|
</form>
|
27
19
|
<form style="display: inline-block"
|
28
|
-
action="/reject?
|
20
|
+
action="/reject?description=<%= diff[:description] %>&viewport=<%= diff[:viewport] %>"
|
29
21
|
method="POST">
|
30
22
|
<button type="submit">Reject</button>
|
31
23
|
</form>
|
@@ -36,7 +28,7 @@
|
|
36
28
|
<h2>BASELINES</h2>
|
37
29
|
<% @snapshots[:baselines].each do |baseline| %>
|
38
30
|
<h3>
|
39
|
-
<%= baseline[:
|
31
|
+
<%= baseline[:description] %> @ <%= baseline[:viewport] %>
|
40
32
|
</h3>
|
41
33
|
<p><img src="/resource?file=<%= ERB::Util.url_encode(baseline[:file]) %>"></p>
|
42
34
|
<% end %>
|
metadata
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: diffux_ci
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Henric Trotzig
|
8
|
+
- Joe Lencioni
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
@@ -31,25 +32,19 @@ dependencies:
|
|
31
32
|
- !ruby/object:Gem::Version
|
32
33
|
version: 0.0.2
|
33
34
|
- !ruby/object:Gem::Dependency
|
34
|
-
name:
|
35
|
+
name: oily_png
|
35
36
|
requirement: !ruby/object:Gem::Requirement
|
36
37
|
requirements:
|
37
38
|
- - "~>"
|
38
39
|
- !ruby/object:Gem::Version
|
39
|
-
version: '1.
|
40
|
-
- - ">="
|
41
|
-
- !ruby/object:Gem::Version
|
42
|
-
version: 1.3.4
|
40
|
+
version: '1.1'
|
43
41
|
type: :runtime
|
44
42
|
prerelease: false
|
45
43
|
version_requirements: !ruby/object:Gem::Requirement
|
46
44
|
requirements:
|
47
45
|
- - "~>"
|
48
46
|
- !ruby/object:Gem::Version
|
49
|
-
version: '1.
|
50
|
-
- - ">="
|
51
|
-
- !ruby/object:Gem::Version
|
52
|
-
version: 1.3.4
|
47
|
+
version: '1.1'
|
53
48
|
- !ruby/object:Gem::Dependency
|
54
49
|
name: selenium-webdriver
|
55
50
|
requirement: !ruby/object:Gem::Requirement
|
@@ -144,7 +139,10 @@ files:
|
|
144
139
|
- lib/diffux_ci_server.rb
|
145
140
|
- lib/diffux_ci_uploader.rb
|
146
141
|
- lib/diffux_ci_utils.rb
|
142
|
+
- lib/diffux_ci_version.rb
|
147
143
|
- lib/public/diffux_ci-runner.js
|
144
|
+
- lib/public/diffux_ci-styles.css
|
145
|
+
- lib/views/debug.erb
|
148
146
|
- lib/views/index.erb
|
149
147
|
- lib/views/review.erb
|
150
148
|
homepage: http://rubygems.org/gems/diffux_ci
|