selfie 0.0.1.pre → 0.0.1
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/README.md +93 -1
- data/lib/selfie/dsl.rb +139 -0
- data/lib/selfie/version.rb +1 -1
- data/lib/selfie.rb +2 -1
- metadata +34 -7
- data/Gemfile +0 -2
- data/selfie.gemspec +0 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6bc05951c6292fdc8b8a6b66d19de4ef2e264058
|
4
|
+
data.tar.gz: 9766f95411f54e665e4b0b50646adb3949482f5a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dbbbb0e68288151ec1c2ec21d9cb60e1eaa8facc7fa5dad01f0cd2823356c42e828d27bbab95a80c6357286cc853ad70c92b8833003a2b461e16dd7a42abe21a
|
7
|
+
data.tar.gz: c4ddced49ff082facdf39aafa3ca4918fe58d39a50ae102e12c128a629bae102b644636eb77449895a92f97bc5af89b12042f0c893b8cf8e86d34c6b1a86f280
|
data/README.md
CHANGED
@@ -1 +1,93 @@
|
|
1
|
-
# Selfie
|
1
|
+
# Selfie
|
2
|
+
|
3
|
+
Visual UI regression tests using PhantomJS, Poltergeist and Imagemagick for Capybara.
|
4
|
+
|
5
|
+
## To get started
|
6
|
+
|
7
|
+
For rails it's easy! Just add ``selfie`` to your ``Gemfile``
|
8
|
+
|
9
|
+
```
|
10
|
+
gem 'selfie'
|
11
|
+
```
|
12
|
+
|
13
|
+
Then create an integration test and include the `Selfie::DSL` and use `snap!` to capture a screenshot.
|
14
|
+
|
15
|
+
```
|
16
|
+
class CompletePurchaseTest < ActiveSupport::TestCase
|
17
|
+
include Capybara::DSL
|
18
|
+
include Selfie::DSL
|
19
|
+
|
20
|
+
test "should do a complete purchase" do
|
21
|
+
visit '/'
|
22
|
+
assert has_content? 'Welcome to Shopping!'
|
23
|
+
|
24
|
+
snap! 'home'
|
25
|
+
|
26
|
+
# do more stuff here.
|
27
|
+
|
28
|
+
make_report
|
29
|
+
open_report
|
30
|
+
end
|
31
|
+
end
|
32
|
+
```
|
33
|
+
### Creating reference image sets
|
34
|
+
|
35
|
+
Easy huh, except there is at this moment nothing to diff with. You need to run
|
36
|
+
the script once to create your reference images.
|
37
|
+
|
38
|
+
Selfie saves the images of the current run into `tmp/snap/current`. You can simply copy
|
39
|
+
that directory to create your reference images. It will look for the reference images in th `test/assets` directory. The name of the directory is the underscored variant with ``Test`` removed so in this case ``complete_purchase``
|
40
|
+
|
41
|
+
```
|
42
|
+
cp -R tmp/snap/current test/assets/complete_purchase
|
43
|
+
```
|
44
|
+
|
45
|
+
|
46
|
+
## Being forgiving
|
47
|
+
|
48
|
+
Sometimes you don't want a single pixel to fail your test. For instance, when you work
|
49
|
+
with generated dates. You can provide a threshold that allows for changes:
|
50
|
+
|
51
|
+
```
|
52
|
+
snap! 'home', threshold: 0.01
|
53
|
+
```
|
54
|
+
|
55
|
+
You can see the threshold next to the image result in the make report.
|
56
|
+
|
57
|
+
## Capturing page on failed asserts
|
58
|
+
|
59
|
+
If you want to capture an image on a failed assert you can use the following 'freedom-patch' to override `assert`.
|
60
|
+
|
61
|
+
Like this:
|
62
|
+
|
63
|
+
```
|
64
|
+
class PurchaseTest < ActiveSupport::TestCase
|
65
|
+
def assert(*args)
|
66
|
+
passed = super(*args)
|
67
|
+
ensure
|
68
|
+
snap 'ERROR!' unless passed
|
69
|
+
end
|
70
|
+
end
|
71
|
+
```
|
72
|
+
|
73
|
+
## Being async
|
74
|
+
|
75
|
+
`snap!` doesn't wait for a page load, it just snaps te current page. Normally, you might want to use one of the Capybara ``finders``, such as
|
76
|
+
|
77
|
+
```
|
78
|
+
assert has_content? 'Welcome to Shopping!'
|
79
|
+
```
|
80
|
+
to verify that specific page has loaded before you snap a shot!
|
81
|
+
|
82
|
+
## Under the hood
|
83
|
+
|
84
|
+
It basically relies on a couple of components. PhantomJS, and ImageMagick. It uses PhantomJS's, `save_screenshot` method to capture a screenshot. And ImageMagic's ``compare`` and ``convert`` to make a diff and measure the difference.
|
85
|
+
|
86
|
+
## Contribute!
|
87
|
+
|
88
|
+
Awesome please help me out! This is cool, but it can be much cooler, friendlier. More awesome. A couple of things on my wishlist!
|
89
|
+
|
90
|
+
- A assert `snap_and_compare! 'home', threshold: 0.05`
|
91
|
+
- snap! with a given element
|
92
|
+
- Add some tests if you like
|
93
|
+
|
data/lib/selfie/dsl.rb
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
module Selfie
|
2
|
+
module DSL
|
3
|
+
def snap_reference_dir
|
4
|
+
asset = self.class.name.gsub(/Test$/,'').underscore
|
5
|
+
asset_dir = File.join 'test','assets', asset
|
6
|
+
end
|
7
|
+
|
8
|
+
def make_report
|
9
|
+
process_images
|
10
|
+
File.write("snap.html", ERB.new(template).result(binding))
|
11
|
+
end
|
12
|
+
|
13
|
+
def open_report
|
14
|
+
`open snap.html`
|
15
|
+
end
|
16
|
+
|
17
|
+
def process_images
|
18
|
+
@diff = []
|
19
|
+
@has_diff = Dir.exist? snap_reference_dir
|
20
|
+
|
21
|
+
for snap in @snaps
|
22
|
+
name = snap[:name]
|
23
|
+
snap[:src] = src = "tmp/snap/current/#{name}.png"
|
24
|
+
|
25
|
+
next unless @has_diff
|
26
|
+
|
27
|
+
snap[:diff] = diff = "tmp/snap/current/#{name}_diff.png"
|
28
|
+
snap[:ref] = ref = "#{snap_reference_dir}/#{name}.png"
|
29
|
+
|
30
|
+
`compare #{ref} #{src} #{diff}`
|
31
|
+
cmd = "convert #{ref} #{src} -compose Difference -composite -colorspace gray -format '%[fx:mean*100]' info:"
|
32
|
+
|
33
|
+
snap[:psr] = (`#{cmd}`).strip.to_f
|
34
|
+
snap[:changed] = snap[:psr] > snap[:threshold]
|
35
|
+
|
36
|
+
@diff << snap if snap[:changed]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def snap!(name, options={})
|
41
|
+
|
42
|
+
name = ("%03d" % @film += 1) + "_#{name}"
|
43
|
+
path = "tmp/snap/current/#{name}.png"
|
44
|
+
|
45
|
+
snap = {name: name, url: current_url}
|
46
|
+
snap[:threshold] = 0
|
47
|
+
|
48
|
+
snap.merge!(options)
|
49
|
+
|
50
|
+
@snaps << snap
|
51
|
+
save_screenshot(path, :full => true)
|
52
|
+
end
|
53
|
+
|
54
|
+
def setup_selfie
|
55
|
+
@snaps = []
|
56
|
+
@film = 0
|
57
|
+
`rm -rf tmp/snap/current`
|
58
|
+
`mkdir -p tmp/snap/current`
|
59
|
+
end
|
60
|
+
|
61
|
+
def template
|
62
|
+
<<-ERB
|
63
|
+
|
64
|
+
<style>
|
65
|
+
body {
|
66
|
+
color:#4a4a4a;
|
67
|
+
background-color:#efefef;
|
68
|
+
}
|
69
|
+
.paper {
|
70
|
+
border:1px solid #d0d0d0;
|
71
|
+
font-family:helvetica;
|
72
|
+
padding:20px;
|
73
|
+
width:1500px;
|
74
|
+
margin:50px auto; border:1px solid #efefef;
|
75
|
+
border-radius:10px;
|
76
|
+
background-color:white;
|
77
|
+
}
|
78
|
+
.no-ref {
|
79
|
+
background-color:#efeeef;padding:10px; border-radius:5px;
|
80
|
+
}
|
81
|
+
p {
|
82
|
+
word-wrap: break-word;
|
83
|
+
}
|
84
|
+
hr {
|
85
|
+
border-color:#d0d0d0
|
86
|
+
}
|
87
|
+
.results img { border:10px solid #efefef; width:720px; }
|
88
|
+
.failed { color:#FF9999; }
|
89
|
+
.img-failed img { border-color:#FF9999;}
|
90
|
+
.logo {float:right;width:80px; border-radius:5px;width:60px;height:60px}
|
91
|
+
</style>
|
92
|
+
|
93
|
+
<title>Selfie results</title>
|
94
|
+
<body>
|
95
|
+
<div class='paper'>
|
96
|
+
<img class='logo' title='Emile <3 you!' src='https://0.gravatar.com/avatar/aca8aad5245e144c9222102decb1776e&s=440'/>
|
97
|
+
|
98
|
+
<h1 class='<%=(@diff.empty? ? "success" : "failed") %>'>Selfie - <%=(@diff.empty? ? "Lookin' good :)" : "Things changed") %></h1>
|
99
|
+
|
100
|
+
<hr size=1/>
|
101
|
+
|
102
|
+
<% unless @has_diff %>
|
103
|
+
<div class='no-ref'>No reference images path defined in '<%=snap_reference_dir%>' -
|
104
|
+
You can copy this: 'cp -R tmp/snap/current <%=snap_reference_dir%>'
|
105
|
+
</div>
|
106
|
+
<% end %>
|
107
|
+
|
108
|
+
<div class='results'>
|
109
|
+
<% unless @diff.empty? %>
|
110
|
+
<h2>These <%=@diff.length%> snaps are different</h2>
|
111
|
+
<% for snap in @diff %>
|
112
|
+
<div class='<%=(snap[:changed] ? "img-failed" : "img-success")%>'>
|
113
|
+
<h3><%=snap[:name]%> (<%=snap[:psr]%>)</h3>
|
114
|
+
<p><%=snap[:url]%></p>
|
115
|
+
<p><%=snap[:note]%></p>
|
116
|
+
<a href='<%=snap[:src]%>'><img src='<%=snap[:src]%>'/ ></a>
|
117
|
+
<a href='<%=snap[:diff]%>'><img src='<%=snap[:diff]%>'/ ></a>
|
118
|
+
</div>
|
119
|
+
<% end %>
|
120
|
+
<hr size=1/>
|
121
|
+
<% end %>
|
122
|
+
|
123
|
+
<h2>All snaps</h2>
|
124
|
+
<% for snap in @snaps %>
|
125
|
+
<div class='<%=(snap[:changed] ? "img-failed" : "img-success")%>'>
|
126
|
+
<h3><%=snap[:name]%> (<%=snap[:psr]%>)</h3>
|
127
|
+
<p><%=snap[:url]%></p>
|
128
|
+
<p><%=snap[:note]%></p>
|
129
|
+
<a href='<%=snap[:src]%>'><img src='<%=snap[:src]%>'/ ></a>
|
130
|
+
<a href='<%=snap[:diff]%>'><img src='<%=snap[:diff]%>'/ ></a>
|
131
|
+
</div>
|
132
|
+
<% end %>
|
133
|
+
</div>
|
134
|
+
</div>
|
135
|
+
</body>
|
136
|
+
ERB
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
data/lib/selfie/version.rb
CHANGED
data/lib/selfie.rb
CHANGED
@@ -1 +1,2 @@
|
|
1
|
-
require 'selfie/version'
|
1
|
+
require 'selfie/version'
|
2
|
+
require 'selfie/dsl'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: selfie
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.1
|
4
|
+
version: 0.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Emile Bosch
|
@@ -9,7 +9,35 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
date: 2013-10-24 00:00:00.000000000 Z
|
12
|
-
dependencies:
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: simplecov
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: poltergeist
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
13
41
|
description: Selfie takes screenshots of itself, when running your poltergeist tests,
|
14
42
|
little egotistical bastard.
|
15
43
|
email: emilebosch@me.com
|
@@ -17,11 +45,10 @@ executables: []
|
|
17
45
|
extensions: []
|
18
46
|
extra_rdoc_files: []
|
19
47
|
files:
|
48
|
+
- lib/selfie/dsl.rb
|
20
49
|
- lib/selfie/version.rb
|
21
50
|
- lib/selfie.rb
|
22
51
|
- README.md
|
23
|
-
- selfie.gemspec
|
24
|
-
- Gemfile
|
25
52
|
homepage: https://github.com/emilebosch/selfie
|
26
53
|
licenses:
|
27
54
|
- MIT
|
@@ -37,14 +64,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
37
64
|
version: '0'
|
38
65
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
39
66
|
requirements:
|
40
|
-
- - '
|
67
|
+
- - '>='
|
41
68
|
- !ruby/object:Gem::Version
|
42
|
-
version:
|
69
|
+
version: '0'
|
43
70
|
requirements: []
|
44
71
|
rubyforge_project:
|
45
72
|
rubygems_version: 2.0.2
|
46
73
|
signing_key:
|
47
74
|
specification_version: 4
|
48
|
-
summary: Screenshots for your
|
75
|
+
summary: Screenshots for your poltergeist tests
|
49
76
|
test_files: []
|
50
77
|
has_rdoc:
|
data/Gemfile
DELETED
data/selfie.gemspec
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
require './lib/selfie/version'
|
2
|
-
|
3
|
-
Gem::Specification.new do |s|
|
4
|
-
s.name = 'selfie'
|
5
|
-
s.version = Selfie::VERSION
|
6
|
-
s.date = '2013-10-24'
|
7
|
-
s.summary = "Screenshots for your poltegergeist tests"
|
8
|
-
s.description = "Selfie takes screenshots of itself, when running your poltergeist tests, little egotistical bastard."
|
9
|
-
s.authors = ["Emile Bosch"]
|
10
|
-
s.email = 'emilebosch@me.com'
|
11
|
-
s.files = Dir.glob('{lib}/**/*') + %w(README.md selfie.gemspec Gemfile)
|
12
|
-
s.homepage = 'https://github.com/emilebosch/selfie'
|
13
|
-
s.license = 'MIT'
|
14
|
-
end
|