simulacrum 0.0.3 → 0.1.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 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