diffux_ci 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0434bae3bc243b30200763f7503dec75c2f884c1
4
- data.tar.gz: fab849f9e3bad3c2286f689beca20ab2bcee7957
3
+ metadata.gz: e5143ca3e39e34a1ea00043f6f20814a72971b16
4
+ data.tar.gz: 6fced8ad6eccd338a886769b2ca755768ab9c0f9
5
5
  SHA512:
6
- metadata.gz: 3cd2f4c3c22a01247ad075259954c2c8815a412b7f77fb20c201210877f826b515a6e9fdf62e660492dba84bf02ceb410c28526781485460680046306f9145ea
7
- data.tar.gz: 5c516aff788a20ad96cf7e9992647940b7d481f5edc70de3dd3cf32956e708cbe57d896492144bdb5883bfae6b0b20320eb004d74cb4c55e4472b20872a4c414
6
+ metadata.gz: 758fe05b11a9edcc343acc0cd9988615e2035432675e88de8b2837941f2c1704de1b9d6cd2a31102df05fd1b5276dc0a7b439b83a987a7e421e0b0177e7a8679
7
+ data.tar.gz: feb1f5d30adea55fc3fc0f467f1079eb629d09b15a6b0248ebfe60a91d2f2679a9e086a789c5822fbac5cf7611831358090be701aaa4ea7378e97859df8fe114
@@ -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 <<-EOS
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
@@ -50,30 +50,43 @@ begin
50
50
  fail "JavaScript errors found during initialization: \n#{errors.inspect}"
51
51
  end
52
52
 
53
- # We use the description of the example to store the snapshot. If a
54
- # description is duplicated with different code, it can cause seemingly random
55
- # and confusing differences. To avoid this issue, we want to keep track of the
56
- # descriptions that we've seen and fail if we come across the same description
57
- # twice.
58
- seen_descriptions = {}
59
-
60
- while current = driver.execute_script('return window.diffux.next()') do
61
- description = current['description']
62
-
63
- resolve_viewports(current).each do |viewport|
64
- # Make sure we don't have a duplicate description
65
- seen_descriptions[description] ||= {}
66
- if seen_descriptions[description][viewport['name']]
67
- fail <<-EOS
68
- Error while rendering "#{description}" @#{viewport['name']}:
69
- Duplicate description detected
70
- EOS
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
- seen_descriptions[description][viewport['name']] = true
84
+ print '├─ '
73
85
  end
86
+ description = example['description']
87
+ print " #{description} "
74
88
 
75
- # Resize window to the right size before rendering
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 `renderCurrent()` which calls it
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.renderCurrent(doneFunc);
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
- puts "First snapshot created (#{baseline_path})"
184
+ print '.'
185
+ puts " First snapshot created (#{baseline_path})"
168
186
  end
169
187
  end
170
188
  end
@@ -1,4 +1,4 @@
1
1
  # Defines the gem version.
2
2
  module DiffuxCI
3
- VERSION = '0.3.1'
3
+ VERSION = '0.3.2'
4
4
  end
@@ -1,52 +1,52 @@
1
1
  'use strict';
2
2
 
3
3
  window.diffux = {
4
- defined: [],
5
- currentIndex: 0,
6
- currentExample: undefined,
4
+ defined: {},
5
+ fdefined: [],
7
6
  currentRenderedElement: undefined,
8
7
  errors: [],
9
8
 
10
9
  define: function(description, func, options) {
11
- this.defined.push({
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.defined = []; // clear out all previously added examples
20
- this.define.apply(this, arguments); // add the example
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
- next: function() {
25
- if (this.currentRenderedElement) {
26
- if (window.React) {
27
- window.React.unmountComponentAtNode(document.body.lastChild);
28
- } else {
29
- this.currentRenderedElement.parentNode
30
- .removeChild(this.currentRenderedElement);
31
- }
32
- }
33
- this.currentExample = this.defined[this.currentIndex];
34
- if (!this.currentExample) {
35
- return;
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
- setCurrent: function(exampleDescription) {
42
- this.defined.forEach(function(example, index) {
43
- if (example.description === exampleDescription) {
44
- this.currentExample = example;
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: this.currentExample.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
- renderCurrent: function(doneFunc) {
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 = this.currentExample.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 (this.currentExample.options.snapshotEntireScreen) {
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: this.currentExample.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.setCurrent(example);
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.1
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
- - diffux_ci
133
+ - diffux
134
134
  extensions: []
135
135
  extra_rdoc_files: []
136
136
  files:
137
- - bin/diffux_ci
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