looks_good 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,340 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE html
3
+ PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
4
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
5
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
6
+ <head>
7
+ <title>RSpec results</title>
8
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
9
+ <meta http-equiv="Expires" content="-1" />
10
+ <meta http-equiv="Pragma" content="no-cache" />
11
+ <style type="text/css">
12
+ body {
13
+ margin: 0;
14
+ padding: 0;
15
+ background: #fff;
16
+ font-size: 80%;
17
+ }
18
+ </style>
19
+ <script type="text/javascript">
20
+ // <![CDATA[
21
+
22
+ function addClass(element_id, classname) {
23
+ document.getElementById(element_id).className += (" " + classname);
24
+ }
25
+
26
+ function removeClass(element_id, classname) {
27
+ var elem = document.getElementById(element_id);
28
+ var classlist = elem.className.replace(classname,'');
29
+ elem.className = classlist;
30
+ }
31
+
32
+ function moveProgressBar(percentDone) {
33
+ document.getElementById("rspec-header").style.width = percentDone +"%";
34
+ }
35
+
36
+ function makeRed(element_id) {
37
+ removeClass(element_id, 'passed');
38
+ removeClass(element_id, 'not_implemented');
39
+ addClass(element_id,'failed');
40
+ }
41
+
42
+ function makeYellow(element_id) {
43
+ var elem = document.getElementById(element_id);
44
+ if (elem.className.indexOf("failed") == -1) { // class doesn't includes failed
45
+ if (elem.className.indexOf("not_implemented") == -1) { // class doesn't include not_implemented
46
+ removeClass(element_id, 'passed');
47
+ addClass(element_id,'not_implemented');
48
+ }
49
+ }
50
+ }
51
+
52
+ function apply_filters() {
53
+ var passed_filter = document.getElementById('passed_checkbox').checked;
54
+ var failed_filter = document.getElementById('failed_checkbox').checked;
55
+ var pending_filter = document.getElementById('pending_checkbox').checked;
56
+
57
+ assign_display_style("example passed", passed_filter);
58
+ assign_display_style("example failed", failed_filter);
59
+ assign_display_style("example not_implemented", pending_filter);
60
+
61
+ assign_display_style_for_group("example_group passed", passed_filter);
62
+ assign_display_style_for_group("example_group not_implemented", pending_filter, pending_filter || passed_filter);
63
+ assign_display_style_for_group("example_group failed", failed_filter, failed_filter || pending_filter || passed_filter);
64
+ }
65
+
66
+ function get_display_style(display_flag) {
67
+ var style_mode = 'none';
68
+ if (display_flag == true) {
69
+ style_mode = 'block';
70
+ }
71
+ return style_mode;
72
+ }
73
+
74
+ function assign_display_style(classname, display_flag) {
75
+ var style_mode = get_display_style(display_flag);
76
+ var elems = document.getElementsByClassName(classname)
77
+ for (var i=0; i<elems.length;i++) {
78
+ elems[i].style.display = style_mode;
79
+ }
80
+ }
81
+
82
+ function assign_display_style_for_group(classname, display_flag, subgroup_flag) {
83
+ var display_style_mode = get_display_style(display_flag);
84
+ var subgroup_style_mode = get_display_style(subgroup_flag);
85
+ var elems = document.getElementsByClassName(classname)
86
+ for (var i=0; i<elems.length;i++) {
87
+ var style_mode = display_style_mode;
88
+ if ((display_flag != subgroup_flag) && (elems[i].getElementsByTagName('dt')[0].innerHTML.indexOf(", ") != -1)) {
89
+ elems[i].style.display = subgroup_style_mode;
90
+ } else {
91
+ elems[i].style.display = display_style_mode;
92
+ }
93
+ }
94
+ }
95
+
96
+ // ]]>
97
+ </script>
98
+ <style type="text/css">
99
+ #rspec-header {
100
+ background: #65C400; color: #fff; height: 4em;
101
+ }
102
+
103
+ .rspec-report h1 {
104
+ margin: 0px 10px 0px 10px;
105
+ padding: 10px;
106
+ font-family: "Lucida Grande", Helvetica, sans-serif;
107
+ font-size: 1.8em;
108
+ position: absolute;
109
+ }
110
+
111
+ #label {
112
+ float:left;
113
+ }
114
+
115
+ #display-filters {
116
+ float:left;
117
+ padding: 28px 0 0 40%;
118
+ font-family: "Lucida Grande", Helvetica, sans-serif;
119
+ }
120
+
121
+ #summary {
122
+ float:right;
123
+ padding: 5px 10px;
124
+ font-family: "Lucida Grande", Helvetica, sans-serif;
125
+ text-align: right;
126
+ }
127
+
128
+ #summary p {
129
+ margin: 0 0 0 2px;
130
+ }
131
+
132
+ #summary #totals {
133
+ font-size: 1.2em;
134
+ }
135
+
136
+ .example_group {
137
+ margin: 0 10px 5px;
138
+ background: #fff;
139
+ }
140
+
141
+ dl {
142
+ margin: 0; padding: 0 0 5px;
143
+ font: normal 11px "Lucida Grande", Helvetica, sans-serif;
144
+ }
145
+
146
+ dt {
147
+ padding: 3px;
148
+ background: #65C400;
149
+ color: #fff;
150
+ font-weight: bold;
151
+ }
152
+
153
+ dd {
154
+ margin: 5px 0 5px 5px;
155
+ padding: 3px 3px 3px 18px;
156
+ }
157
+
158
+
159
+ dd.example.passed {
160
+ border-left: 5px solid #65C400;
161
+ border-bottom: 1px solid #65C400;
162
+ background: #DBFFB4; color: #3D7700;
163
+ }
164
+
165
+ dd.example.not_implemented {
166
+ border-left: 5px solid #FAF834;
167
+ border-bottom: 1px solid #FAF834;
168
+ background: #FCFB98; color: #131313;
169
+ }
170
+
171
+ dd.example.pending_fixed {
172
+ border-left: 5px solid #0000C2;
173
+ border-bottom: 1px solid #0000C2;
174
+ color: #0000C2; background: #D3FBFF;
175
+ }
176
+
177
+ dd.example.failed {
178
+ border-left: 5px solid #C20000;
179
+ border-bottom: 1px solid #C20000;
180
+ color: #C20000; background: #FFFBD3;
181
+ }
182
+
183
+
184
+ dt.not_implemented {
185
+ color: #000000; background: #FAF834;
186
+ }
187
+
188
+ dt.pending_fixed {
189
+ color: #FFFFFF; background: #C40D0D;
190
+ }
191
+
192
+ dt.failed {
193
+ color: #FFFFFF; background: #C40D0D;
194
+ }
195
+
196
+
197
+ #rspec-header.not_implemented {
198
+ color: #000000; background: #FAF834;
199
+ }
200
+
201
+ #rspec-header.pending_fixed {
202
+ color: #FFFFFF; background: #C40D0D;
203
+ }
204
+
205
+ #rspec-header.failed {
206
+ color: #FFFFFF; background: #C40D0D;
207
+ }
208
+
209
+
210
+ .backtrace {
211
+ color: #000;
212
+ font-size: 12px;
213
+ }
214
+
215
+ a {
216
+ color: #BE5C00;
217
+ }
218
+
219
+ /* Ruby code, style similar to vibrant ink */
220
+ .ruby {
221
+ font-size: 12px;
222
+ font-family: monospace;
223
+ color: white;
224
+ background-color: black;
225
+ padding: 0.1em 0 0.2em 0;
226
+ }
227
+
228
+ .ruby .keyword { color: #FF6600; }
229
+ .ruby .constant { color: #339999; }
230
+ .ruby .attribute { color: white; }
231
+ .ruby .global { color: white; }
232
+ .ruby .module { color: white; }
233
+ .ruby .class { color: white; }
234
+ .ruby .string { color: #66FF00; }
235
+ .ruby .ident { color: white; }
236
+ .ruby .method { color: #FFCC00; }
237
+ .ruby .number { color: white; }
238
+ .ruby .char { color: white; }
239
+ .ruby .comment { color: #9933CC; }
240
+ .ruby .symbol { color: white; }
241
+ .ruby .regex { color: #44B4CC; }
242
+ .ruby .punct { color: white; }
243
+ .ruby .escape { color: white; }
244
+ .ruby .interp { color: white; }
245
+ .ruby .expr { color: white; }
246
+
247
+ .ruby .offending { background-color: gray; }
248
+ .ruby .linenum {
249
+ width: 75px;
250
+ padding: 0.1em 1em 0.2em 0;
251
+ color: #000000;
252
+ background-color: #FFFBD3;
253
+ }
254
+
255
+ </style>
256
+ </head>
257
+ <body>
258
+ <div class="rspec-report">
259
+
260
+ <div id="rspec-header">
261
+ <div id="label">
262
+ <h1>RSpec Code Examples</h1>
263
+ </div>
264
+
265
+ <div id="display-filters">
266
+ <input id="passed_checkbox" name="passed_checkbox" type="checkbox" checked onchange="apply_filters()" value="1"> <label for="passed_checkbox">Passed</label>
267
+ <input id="failed_checkbox" name="failed_checkbox" type="checkbox" checked onchange="apply_filters()" value="2"> <label for="failed_checkbox">Failed</label>
268
+ <input id="pending_checkbox" name="pending_checkbox" type="checkbox" checked onchange="apply_filters()" value="3"> <label for="pending_checkbox">Pending</label>
269
+ </div>
270
+
271
+ <div id="summary">
272
+ <p id="totals">&nbsp;</p>
273
+ <p id="duration">&nbsp;</p>
274
+ </div>
275
+ </div>
276
+
277
+
278
+ <div class="results">
279
+ <div id="div_group_1" class="example_group passed">
280
+ <dl style="margin-left: 0px;">
281
+ <dt id="example_group_1" class="passed">LooksGood::Configuration</dt>
282
+ </dl>
283
+ </div>
284
+ <div id="div_group_2" class="example_group passed">
285
+ <dl style="margin-left: 15px;">
286
+ <dt id="example_group_2" class="passed">#reference_image_path</dt>
287
+ <script type="text/javascript">moveProgressBar('20.0');</script>
288
+ <dd class="example passed"><span class="passed_spec_name">should default to &lt;Rails.root&gt;/spec/reference_images</span></dd>
289
+ <script type="text/javascript">moveProgressBar('40.0');</script>
290
+ <dd class="example passed"><span class="passed_spec_name">should be overrideable</span></dd>
291
+ </dl>
292
+ </div>
293
+ <div id="div_group_3" class="example_group passed">
294
+ <dl style="margin-left: 0px;">
295
+ <dt id="example_group_3" class="passed">looks_good</dt>
296
+ </dl>
297
+ </div>
298
+ <div id="div_group_4" class="example_group passed">
299
+ <dl style="margin-left: 15px;">
300
+ <dt id="example_group_4" class="passed">creating an initial reference (expected) image</dt>
301
+ <script type="text/javascript">moveProgressBar('60.0');</script>
302
+ <dd class="example passed"><span class="passed_spec_name">should notify that no reference exists for image and create a candidate</span></dd>
303
+ </dl>
304
+ </div>
305
+ <div id="div_group_5" class="example_group passed">
306
+ <dl style="margin-left: 15px;">
307
+ <dt id="example_group_5" class="passed">image comparison</dt>
308
+ <script type="text/javascript">moveProgressBar('80.0');</script>
309
+ <dd class="example passed"><span class="passed_spec_name">captured and referenced images match</span></dd>
310
+ </dl>
311
+ </div>
312
+ <div id="div_group_6" class="example_group passed">
313
+ <dl style="margin-left: 15px;">
314
+ <dt id="example_group_6" class="passed">training mode populates a candidate reference</dt>
315
+ <script type="text/javascript">makeRed('rspec-header');</script>
316
+ <script type="text/javascript">makeRed('div_group_6');</script>
317
+ <script type="text/javascript">makeRed('example_group_6');</script>
318
+ <script type="text/javascript">moveProgressBar('100.0');</script>
319
+ <dd class="example failed">
320
+ <span class="failed_spec_name">should create a reference from a candidate</span>
321
+ <div class="failure" id="failure_1">
322
+ <div class="message"><pre>can't convert nil into String</pre></div>
323
+ <div class="backtrace"><pre>./lib/looks_good.rb:104:in `+'
324
+ ./lib/looks_good.rb:104:in `run'
325
+ ./spec/looks_good_spec.rb:76:in `block (3 levels) in <top (required)>'</pre></div>
326
+ <pre class="ruby"><code><span class="linenum">102</span>
327
+ <span class="linenum">103</span> <span class="keyword">def </span><span class="method">run</span>
328
+ <span class="offending"><span class="linenum">104</span> <span class="ident">puts</span> <span class="punct">&quot;</span><span class="string">-------------</span><span class="punct">&quot;</span> <span class="punct">+</span> <span class="attribute">@reference_image_path</span></span>
329
+ <span class="linenum">105</span> <span class="constant">self</span><span class="punct">.</span><span class="ident">crop_element</span>
330
+ <span class="linenum">106</span> <span class="keyword">end</span></code></pre>
331
+ </div>
332
+ </dd>
333
+ </dl>
334
+ </div>
335
+ <script type="text/javascript">document.getElementById('duration').innerHTML = "Finished in <strong>14.828533 seconds</strong>";</script>
336
+ <script type="text/javascript">document.getElementById('totals').innerHTML = "5 examples, 1 failure";</script>
337
+ </div>
338
+ </div>
339
+ </body>
340
+ </html>
@@ -0,0 +1,83 @@
1
+ require 'spec_helper'
2
+ include Capybara::DSL
3
+
4
+ describe 'LooksGood' do
5
+
6
+ before(:all) do
7
+ @spec_support_root = spec_support_root
8
+ end
9
+
10
+ before(:each) do
11
+ @ref_path = LooksGood::Configuration.reference_image_path = File.join(spec_support_root, 'ref_path')
12
+ end
13
+
14
+ after(:each) do
15
+ remove_refs(@ref_path)
16
+ config_clean_up
17
+ end
18
+
19
+ describe 'LooksGood, when no reference image exists' do
20
+
21
+ it "will create a reference image" do
22
+ black_element = element_for_spec
23
+ $stdout.should_receive(:puts).with "Saved #{@ref_path}/#{"black.png"} as reference"
24
+
25
+ LooksGood.matches?("black.png", black_element).should be_true
26
+
27
+ File.exists?(File.join(@ref_path, "black.png")).should be_true
28
+ end
29
+ end
30
+
31
+ describe 'LooksGood image comparison' do
32
+
33
+ before(:each) do
34
+ create_square_image(@ref_path, 'black')
35
+ end
36
+
37
+ after(:each) do
38
+ remove_refs(@ref_path)
39
+ config_clean_up
40
+ end
41
+
42
+ it 'will return true if the images are identical' do
43
+ black_element = element_for_spec('#black')
44
+
45
+ LooksGood.matches?("black.png", black_element).should be_true
46
+ end
47
+
48
+ describe 'between different images of the same size' do
49
+
50
+ it 'will return false, creates new diff and candidate images' do
51
+ red_element = element_for_spec('#red')
52
+ expected_error = "element did not match #{"black.png"}. " +
53
+ "A diff image: #{"black.png"} was created in #{@ref_path}/diff/#{"black.png"} " +
54
+ "A new reference #{@ref_path}/candidate/#{"black.png"} can be used to fix the test"
55
+
56
+ expect {LooksGood.matches?("black.png", red_element)}.to raise_error(RuntimeError, expected_error)
57
+
58
+ File.exists?(File.join(@ref_path,'diff', "black.png")).should be_true
59
+ File.exists?(File.join(@ref_path,'candidate', "black.png")).should be_true
60
+ end
61
+
62
+ end
63
+
64
+ describe 'between images of the different size' do
65
+
66
+ it 'will return false, creates new diff and candidate images' do
67
+ red_element = element_for_spec('#different-size')
68
+ expected_error = "element did not match #{"black.png"}. " +
69
+ "A diff image: #{"black.png"} was created in #{@ref_path}/diff/#{"black.png"} " +
70
+ "A new reference #{@ref_path}/candidate/#{"black.png"} can be used to fix the test"
71
+
72
+ expect {LooksGood.matches?("black.png", red_element)}.to raise_error(RuntimeError, expected_error)
73
+
74
+ File.exists?(File.join(@ref_path,'diff', "black.png")).should be_true
75
+ File.exists?(File.join(@ref_path,'candidate', "black.png")).should be_true
76
+ end
77
+
78
+ end
79
+ end
80
+
81
+
82
+
83
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+ include Capybara::DSL
3
+
4
+ describe 'rspec matcher' do
5
+
6
+ before(:each) do
7
+ @black_box = 'black.png'
8
+ @ref_path = LooksGood::Configuration.reference_image_path = File.join(spec_support_root, 'ref_path')
9
+ create_images_for_web_page
10
+ end
11
+
12
+ after(:each) do
13
+ config_clean_up
14
+ remove_refs(@ref_path)
15
+ end
16
+
17
+ describe 'initializing and runnin looks_good' do
18
+
19
+ it 'will pass if images matches reference' do
20
+ create_square_image(@ref_path, 'black')
21
+ black_element = element_for_spec("#black")
22
+ black_element.should look_like("black.png")
23
+ end
24
+
25
+ it "will fail if images doesn't matches reference" do
26
+ create_square_image(@ref_path, 'black')
27
+ red_element = element_for_spec("#red")
28
+ expect{red_element.should look_like(@black_box)}.to raise_error
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe LooksGood::CaptureElement do
4
+
5
+ # creating a dummy class to test a module
6
+ class SomeClass
7
+ end
8
+
9
+ before :each do
10
+ subject = SomeClass.new
11
+ subject.extend(LooksGood::CaptureElement)
12
+ end
13
+
14
+ after :each do
15
+ config_clean_up
16
+ end
17
+
18
+ it '.capture should return a cropped image' do
19
+ capybara_element = mock(Capybara::Node::Element)
20
+ position = {:x => 1, :y => 2, :width => 100, :height => 200}
21
+ magick_image = Magick::Image.new(position[:width],position[:height])
22
+
23
+
24
+ subject.should_receive(:get_element_position).with(capybara_element).and_return(position)
25
+ subject.should_receive(:take_screenshot).and_return(magick_image)
26
+ subject.should_receive(:crop_element).and_return(magick_image)
27
+
28
+ image = subject.capture(capybara_element)
29
+ image.class.should == Magick::Image
30
+ end
31
+
32
+ end
33
+
@@ -0,0 +1,66 @@
1
+ require 'spec_helper'
2
+
3
+ describe LooksGood::Comparison do
4
+
5
+ before do
6
+ apple = Magick::Image.new(100,100) { self.background_color = "green" }
7
+ orange = Magick::Image.new(100,100) { self.background_color = "orange" }
8
+ @apple = LooksGood::Image.new(apple, "apple.png")
9
+ @orange = LooksGood::Image.new(orange, "orange.png")
10
+ end
11
+
12
+ describe 'will compare two images' do
13
+
14
+ it 'will return true if the images are identical' do
15
+ LooksGood::Comparison.new(@apple, @apple).matches?.should == true
16
+ end
17
+
18
+ it 'will return false if the images are different' do
19
+ LooksGood::Comparison.new(@orange, @apple).matches?.should == false
20
+ end
21
+ end
22
+
23
+ describe 'Diff images' do
24
+ describe 'for two images with the same size' do
25
+ it 'will be generated' do
26
+ LooksGood::Comparison.new(@apple, @orange).diff_image.class.should == LooksGood::Image
27
+ end
28
+ end
29
+
30
+ describe 'for two images with different sizes' do
31
+ before do
32
+ @apple_image = Magick::Image.new(30,300) { self.background_color = "green" }
33
+ @orange_image = Magick::Image.new(80,100) { self.background_color = "orange" }
34
+
35
+ @apple = LooksGood::Image.new(@apple_image, "apple.png")
36
+ @orange = LooksGood::Image.new(@orange_image, "orange.png")
37
+
38
+ @diff_image = LooksGood::Comparison.new(@apple, @orange).diff_image
39
+ end
40
+
41
+ it 'will be generated' do
42
+ @diff_image.class.should == LooksGood::Image
43
+ end
44
+
45
+ it 'will be extended to cover the difference in both images' do
46
+ @diff_image.image.columns.should eql 80
47
+ @diff_image.image.rows.should eql 300
48
+ end
49
+
50
+ describe 'with two different offset' do
51
+ before do
52
+ @apple_image.offset = 50
53
+ @orange_image.offset = 2
54
+
55
+ @diff_image = LooksGood::Comparison.new(@apple, @orange).diff_image
56
+ end
57
+
58
+ it 'will remove image offset from the diff image' do
59
+ @diff_image.image.offset.should eql 0
60
+ end
61
+
62
+ end
63
+
64
+ end
65
+ end
66
+ end