simulacrum 0.0.3 → 0.1.0

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: 7687eec5b004b38792cf95b1c4dc725c060f9a00
4
- data.tar.gz: 794e8cd0f33574cc2290cfcdb407b21a99c5d27e
3
+ metadata.gz: 6ac13e91d6381485d3876e060ce5b106a7f08b17
4
+ data.tar.gz: b080c8f22ff2d7269d8103976a77da6d5d61dcc4
5
5
  SHA512:
6
- metadata.gz: 7e570746996c898fdaba924b2f885637640dae8c1734b433942ba1da5fcec94b1860daaa54b2df3aec0138c34be784fae34635d54d44b13994333460415a1a62
7
- data.tar.gz: 1e356ca93bd87a2483f7e13855ac7eb561520d7e927f06619229fa4e1da97d70b29a37964d7c79d42b2509c05ff81f5d523c5b93eaf5dc94ee6898da6fab1605
6
+ metadata.gz: 636c3df6a29a58103c9d32930de147b845eb712b489b2f0c1cedfca2b35094e22d387722468a8ccfdafa2801a52144c3ea4ad89aa2c5aa79f016c3f70f8e71c8
7
+ data.tar.gz: bafe2f7328c674a8c4ede41babb0f8bacdc8b3a72bd3f92195fb646c8f0cd2890b26f4e740e1eeccaf42528de57c4e7adab81284f4920d6d969fae387346f09d
data/README.md CHANGED
@@ -11,16 +11,21 @@ An opinionated UI component regression testing tool built to be tightly integrat
11
11
 
12
12
  ```ruby
13
13
  RSpec.configure do |config|
14
- config.include Simulacrum
14
+ include Simulacrum
15
15
  end
16
16
  ```
17
17
 
18
18
  Simulacrum can also be configured once included;
19
19
 
20
20
  ```ruby
21
- Simulacrum.configure do |config|
22
- config.images_path = 'somewhere/example/spec/ui_specs'
23
- config.acceptable_delta = 2 # allow a maximum of 2% difference
21
+ RSpec.configure do |config|
22
+ include Simulacrum
23
+
24
+ Simulacrum.configure do |simulacrum|
25
+ simulacrum.images_path = 'somewhere/example/spec/ui_specs'
26
+ simulacrum.acceptable_delta = 0.1 # allow a maximum of 0.1% difference
27
+ config.defaults.capture_selector = '.kayessess__examples'
28
+ end
24
29
  end
25
30
  ```
26
31
 
data/lib/simulacrum.rb CHANGED
@@ -6,37 +6,21 @@ require_relative './simulacrum/configuration'
6
6
 
7
7
  # Gem module
8
8
  module Simulacrum
9
- @current_browser = nil
10
9
  @browsers = {}
11
10
  @components = {}
11
+ @current_browser = nil
12
12
  @configuration = Simulacrum::Configuration.new
13
13
 
14
- Capybara.configure do |config|
15
- config.default_driver = :selenium
16
- end
17
-
18
14
  def self.components
19
15
  @components
20
16
  end
21
17
 
22
- def self.browsers
23
- @browsers
24
- end
25
-
26
- def self.current_browser
27
- @current_browser
28
- end
29
-
30
- def self.current_browser=(browser)
31
- @current_browser = browser
32
- end
33
-
34
18
  def self.configuration
35
19
  @configuration
36
20
  end
37
21
 
38
22
  def self.configure(&block)
39
- options = OpenStruct.new
23
+ options = OpenStruct.new(defaults: OpenStruct.new)
40
24
  yield options
41
25
  @configuration.configure(options.to_h)
42
26
  end
@@ -44,5 +28,10 @@ module Simulacrum
44
28
  def self.included(receiver, &block)
45
29
  receiver.extend Simulacrum::Methods
46
30
  receiver.send :include, Simulacrum::Matchers
31
+
32
+ if defined?(Rails)
33
+ receiver.send :include, Rails.application.routes.url_helpers
34
+ receiver.send :include, Rails.application.routes.mounted_helpers
35
+ end
47
36
  end
48
37
  end
@@ -1,3 +1,4 @@
1
+ require 'rspec'
1
2
  require_relative './diff/rmagick'
2
3
 
3
4
  module Simulacrum
@@ -46,7 +47,7 @@ module Simulacrum
46
47
  nil
47
48
  end
48
49
 
49
- def perform_diff()
50
+ def perform_diff
50
51
  @diff = Simulacrum::RmagicDiff.new(@component.reference_path,
51
52
  @component.candidate_path)
52
53
  diff_delta_percent_is_acceptable
@@ -1,90 +1,93 @@
1
1
  require 'capybara/dsl'
2
+ require 'fileutils'
3
+ require 'rmagick'
4
+ require_relative 'renderer'
2
5
 
3
6
  module Simulacrum
4
7
  class Component
5
- include Capybara::DSL
6
-
7
8
  attr_reader :name, :browser
8
9
  attr_accessor :options
9
10
 
10
- def initialize(name, browser = nil, options = {})
11
+ def initialize(name, options = {})
11
12
  @name = name
12
13
  @options = options
13
- @browser = browser
14
+ @renderer = Simulacrum::Renderer.new(options.url)
14
15
  end
15
16
 
16
17
  # Load up the component url and capture an image, returns a File object
17
18
  def render
18
- use_browser
19
19
  ensure_example_path
20
- visit(@options.url)
21
- page.driver.save_screenshot(candidate_path, options)
22
- kill_driver
20
+ save_candidate(@renderer.render)
21
+ crop_candidate_to_selector
22
+ ensure
23
+ cleanup
23
24
  end
24
25
 
25
- def render_with(browser)
26
- self.class.new(name, browser, @options)
26
+ def reference?
27
+ File.exists?(reference_path)
27
28
  end
28
29
 
29
- def remove_candidate
30
- FileUtils.rm(candidate_path) if candidate?
30
+ def candidate?
31
+ File.exists?(candidate_path)
31
32
  end
32
33
 
33
- def remove_diff
34
- FileUtils.rm(diff_path) if diff?
34
+ def diff?
35
+ File.exists?(diff_path)
35
36
  end
36
37
 
37
- def root_path
38
- File.join(Simulacrum.configuration.images_path, render_path)
38
+ def acceptable_delta
39
+ options.acceptable_delta || Simulacrum.configuration.acceptable_delta
39
40
  end
40
41
 
41
42
  def reference_path
42
- File.join(root_path, Simulacrum.configuration.reference_filename)
43
+ filename = Simulacrum.configuration.reference_filename
44
+ File.join(root_path, "#{filename}.png")
43
45
  end
44
46
 
45
47
  def candidate_path
46
- File.join(root_path, Simulacrum.configuration.candidate_filename)
48
+ filename = Simulacrum.configuration.candidate_filename
49
+ File.join(root_path, "#{filename}.png")
47
50
  end
48
51
 
49
52
  def diff_path
50
- File.join(root_path, Simulacrum.configuration.diff_filename)
53
+ filename = Simulacrum.configuration.diff_filename
54
+ File.join(root_path, "#{filename}.png")
51
55
  end
52
56
 
53
- def reference?
54
- File.exists?(reference_path)
57
+ def remove_candidate
58
+ FileUtils.rm(candidate_path) if candidate?
55
59
  end
56
60
 
57
- def candidate?
58
- File.exists?(candidate_path)
61
+ def remove_diff
62
+ FileUtils.rm(diff_path) if diff?
59
63
  end
60
64
 
61
- def diff?
62
- File.exists?(diff_path)
63
- end
65
+ private
64
66
 
65
- def acceptable_delta
66
- @options.acceptable_delta || Simulacrum.configuration.acceptable_delta
67
+ def cleanup
68
+ @renderer.cleanup
69
+ # FileUtils.remove_entry(root_path) unless reference? || candidate? || diff?
67
70
  end
68
71
 
69
- private
72
+ def save_candidate(tmp_image_path)
73
+ FileUtils.mv(tmp_image_path, candidate_path)
74
+ end
70
75
 
71
- def kill_driver
72
- if not @browser.nil? and @browser.remote?
73
- page.driver.quit
76
+ def crop_candidate_to_selector
77
+ unless capture_selector.nil?
78
+ candidate_image = Magick::Image::read(candidate_path).first
79
+ bounds = @renderer.get_bounds_for_selector(capture_selector)
80
+ candidate_image.crop!(*bounds)
81
+ candidate_image.write(candidate_path)
74
82
  end
75
83
  end
76
84
 
77
- def render_path
78
- path = [name.to_s]
79
- path << @browser.name unless @browser.nil?
80
- File.join(path.map(&:to_s))
85
+ def root_path
86
+ File.join(Simulacrum.configuration.references_path, name.to_s, driver_path)
81
87
  end
82
88
 
83
- def use_browser
84
- unless @browser.nil?
85
- @browser.use
86
- sleep @browser.capture_delay.to_i
87
- end
89
+ def driver_path
90
+ Capybara.current_driver == :default ? '' : Capybara.current_driver.to_s
88
91
  end
89
92
 
90
93
  def ensure_example_path
@@ -92,7 +95,7 @@ module Simulacrum
92
95
  end
93
96
 
94
97
  def capture_selector
95
- @options.capture_selector || Simulacrum.configuration.capture_selector
98
+ options.capture_selector || Simulacrum.configuration.capture_selector
96
99
  end
97
100
  end
98
101
  end
@@ -2,43 +2,56 @@ require 'ostruct'
2
2
 
3
3
  module Simulacrum
4
4
  class Configuration
5
- attr_reader :images_path, :reference_filename, :candidate_filename,
6
- :diff_filename, :capture_selector, :acceptable_delta, :capture_delay
5
+
6
+ COMPONENT_DEFAULTS = {
7
+ acceptable_delta: 1,
8
+ window_size: [1024, 768],
9
+ capture_delay: nil,
10
+ capture_selector: :html,
11
+ }
12
+
13
+ attr_reader :references_path, :reference_filename, :candidate_filename,
14
+ :diff_filename, :acceptable_delta, :capture_delay, :window_size,
15
+ :capture_selector, :default_browser
7
16
 
8
17
  def initialize
9
- @config = OpenStruct.new
18
+ @config = OpenStruct.new(defaults: OpenStruct.new(COMPONENT_DEFAULTS))
10
19
  end
11
20
 
12
21
  def configure(config)
13
22
  @config = OpenStruct.new(@config.to_h.merge!(config))
14
23
  end
15
24
 
16
- def images_path
17
- @config.images_path
25
+ def default_browser
26
+ @config.default_browser || :selenium
27
+ end
28
+
29
+ def references_path
30
+ if @config.references_path
31
+ @config.references_path
32
+ elsif defined?(Rails)
33
+ File.join(Rails.root, 'spec/ui/references')
34
+ end
18
35
  end
19
36
 
20
37
  def reference_filename
21
- @config.reference_filename || 'reference.png'
38
+ @config.reference_filename || 'reference'
22
39
  end
23
40
 
24
41
  def candidate_filename
25
- @config.candidate_filename || 'candidate.png'
42
+ @config.candidate_filename || 'candidate'
26
43
  end
27
44
 
28
45
  def diff_filename
29
- @config.diff_filename || 'diff.png'
30
- end
31
-
32
- def capture_delay
33
- @config.capture_delay || 0
46
+ @config.diff_filename || 'diff'
34
47
  end
35
48
 
36
49
  def acceptable_delta
37
- @config.acceptable_delta || 0.0
50
+ @config.defaults.acceptable_delta || 0.0
38
51
  end
39
52
 
40
- def remote_url
41
- @config.remote_url
53
+ def capture_selector
54
+ @config.defaults.capture_selector || nil
42
55
  end
43
56
  end
44
57
  end
@@ -1,3 +1,4 @@
1
+ require 'rspec'
1
2
  require_relative './comparator'
2
3
 
3
4
  module Simulacrum
@@ -5,9 +6,6 @@ module Simulacrum
5
6
  extend RSpec::Matchers::DSL
6
7
 
7
8
  matcher :look_the_same do
8
- # browser = options[:in_browser]
9
- # browser.use unless browser.nil?
10
-
11
9
  match do |component|
12
10
  component = component
13
11
  comparator = Simulacrum::Comparator.new(component)
@@ -27,7 +25,7 @@ module Simulacrum
27
25
  <<-eos
28
26
  The pixel change percentage exceeded the maximum threshold of #{component.acceptable_delta}%.
29
27
 
30
- There was a #{comparator.diff.percent_change}% pixel difference found between \
28
+ There was a #{comparator.diff.delta_percent}% pixel difference found between \
31
29
  the reference and the candidate.
32
30
 
33
31
  Reference: #{component.reference_path}
@@ -1,5 +1,4 @@
1
1
  require 'ostruct'
2
- require_relative './browser'
3
2
  require_relative './component'
4
3
 
5
4
  module Simulacrum
@@ -8,30 +7,26 @@ module Simulacrum
8
7
  def component(name, &block)
9
8
  options = OpenStruct.new
10
9
  yield options
11
- component = Simulacrum::Component.new(name, nil, options)
10
+ component = Simulacrum::Component.new(name, options)
12
11
  Simulacrum.components[name] = component
13
- subject { component }
14
- let(:component) { component }
15
- end
16
12
 
17
- def browser(name, &block)
18
- options = OpenStruct.new
19
- options.caps = {}
20
- yield options
21
- Simulacrum.browsers[name] = Simulacrum::Browser.new(name, options)
22
- let(name.to_sym) { browser }
13
+ subject do
14
+ component
15
+ end
16
+
17
+ let(:component) do
18
+ component
19
+ end
23
20
  end
24
21
 
25
- def use_browser(name, extra_config = {})
26
- previous_browser = Simulacrum.current_browser
27
- current_browser = Simulacrum.browsers[name]
28
- current_browser.configure(extra_config)
29
- Simulacrum.current_browser = current_browser
30
- subject { component.render_with(current_browser) }
31
- after(:each) {
32
- Simulacrum.current_browser = previous_browser
33
- component.render_with(previous_browser)
34
- }
22
+ def use_window_size(dimensions)
23
+ subject do
24
+ component.set_window_size(dimensions)
25
+ end
26
+
27
+ after(:each) do
28
+ subject.reset_window_size
29
+ end
35
30
  end
36
31
  end
37
32
  end
@@ -0,0 +1,49 @@
1
+ require 'capybara'
2
+ require 'tmpdir'
3
+
4
+ module Simulacrum
5
+ class Renderer
6
+ include Capybara::DSL
7
+
8
+ attr_reader :url, :tmp_path
9
+
10
+ def initialize(url)
11
+ @url = url
12
+ @tmp_dir = Dir.mktmpdir
13
+ end
14
+
15
+ def render
16
+ page.visit(url)
17
+ resize_window!
18
+ save_screenshot!
19
+ end
20
+
21
+ def cleanup
22
+ FileUtils.remove_entry(@tmp_dir)
23
+ end
24
+
25
+ def get_bounds_for_selector(selector)
26
+ element = page.find(selector)
27
+ location = element.native.location
28
+ size = element.native.size
29
+ [location.x, location.y, size.width, size.height]
30
+ end
31
+
32
+ private
33
+
34
+ def resize_window!
35
+ begin
36
+ page.driver.browser.manage.window.resize_to(1024, 768)
37
+ rescue Selenium::WebDriver::Error::UnknownError => e
38
+ end
39
+ end
40
+
41
+ def save_screenshot!
42
+ page.driver.save_screenshot(tmp_path)
43
+ end
44
+
45
+ def tmp_path
46
+ @tmp_path ||= File.join(@tmp_dir, Simulacrum.configuration.candidate_filename)
47
+ end
48
+ end
49
+ end
@@ -1,5 +1,5 @@
1
1
  # Package information
2
2
  module Simulacrum
3
3
  PACKAGE = 'simulacrum'
4
- VERSION = '0.0.3'
4
+ VERSION = '0.1.0'
5
5
  end
metadata CHANGED
@@ -1,71 +1,71 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simulacrum
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Morris
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-07 00:00:00.000000000 Z
11
+ date: 2014-03-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: capybara
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ~>
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: 2.2.1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ~>
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: 2.2.1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rspec
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '>='
31
+ - - ~>
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: 2.14.1
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '>='
38
+ - - ~>
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: 2.14.1
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rmagick
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - '>='
45
+ - - ~>
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
47
+ version: 2.13.2
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - '>='
52
+ - - ~>
53
53
  - !ruby/object:Gem::Version
54
- version: '0'
54
+ version: 2.13.2
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: selenium-webdriver
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - '>='
59
+ - - ~>
60
60
  - !ruby/object:Gem::Version
61
- version: '0'
61
+ version: 2.40.0
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - '>='
66
+ - - ~>
67
67
  - !ruby/object:Gem::Version
68
- version: '0'
68
+ version: 2.40.0
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: coveralls
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -108,20 +108,6 @@ dependencies:
108
108
  - - '>='
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
- - !ruby/object:Gem::Dependency
112
- name: rspec
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - '>='
116
- - !ruby/object:Gem::Version
117
- version: '0'
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - '>='
123
- - !ruby/object:Gem::Version
124
- version: '0'
125
111
  - !ruby/object:Gem::Dependency
126
112
  name: rspec-nc
127
113
  requirement: !ruby/object:Gem::Requirement
@@ -186,20 +172,19 @@ executables: []
186
172
  extensions: []
187
173
  extra_rdoc_files: []
188
174
  files:
189
- - lib/simulacrum/browser.rb
190
- - lib/simulacrum/browser_options.rb
175
+ - LICENSE
176
+ - README.md
177
+ - lib/simulacrum.rb
191
178
  - lib/simulacrum/comparator.rb
192
179
  - lib/simulacrum/component.rb
193
180
  - lib/simulacrum/configuration.rb
181
+ - lib/simulacrum/diff.rb
194
182
  - lib/simulacrum/diff/pdiff.rb
195
183
  - lib/simulacrum/diff/rmagick.rb
196
- - lib/simulacrum/diff.rb
197
184
  - lib/simulacrum/matchers.rb
198
185
  - lib/simulacrum/methods.rb
186
+ - lib/simulacrum/renderer.rb
199
187
  - lib/simulacrum/version.rb
200
- - lib/simulacrum.rb
201
- - README.md
202
- - LICENSE
203
188
  - spec/fixtures/a.png
204
189
  - spec/fixtures/a2.png
205
190
  - spec/spec_helper.rb
@@ -225,7 +210,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
225
210
  version: '0'
226
211
  requirements: []
227
212
  rubyforge_project:
228
- rubygems_version: 2.1.11
213
+ rubygems_version: 2.2.2
229
214
  signing_key:
230
215
  specification_version: 4
231
216
  summary: A gem for visually testing and inspecting user interface components.
@@ -1,44 +0,0 @@
1
- require 'capybara'
2
-
3
- module Simulacrum
4
- class Browser
5
- attr_reader :name, :options
6
-
7
- def initialize(name, options)
8
- @name = name
9
- @options = options
10
- end
11
-
12
- def use
13
- register_driver
14
- Capybara.default_driver = name.to_sym
15
- end
16
-
17
- def configure(config)
18
- puts config.inspect
19
- end
20
-
21
- def capture_delay
22
- @options.capture_delay || Simulacrum.configuration.capture_delay
23
- end
24
-
25
- def remote?
26
- @options.remote.nil? ? false : @options.remote
27
- end
28
-
29
- private
30
-
31
- def driver_options
32
- options = { desired_capabilities: @options.caps }
33
- options[:browser] = :remote if remote?
34
- options[:url] = Simulacrum.configuration.remote_url if remote?
35
- options
36
- end
37
-
38
- def register_driver
39
- Capybara.register_driver name.to_sym do |app|
40
- Capybara::Selenium::Driver.new(app, driver_options)
41
- end
42
- end
43
- end
44
- end
@@ -1,5 +0,0 @@
1
- module Simulacrum
2
- class BrowserOptions < OpenStruct
3
-
4
- end
5
- end