capybara-screenshot 0.1.10 → 0.2

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.
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
@@ -1,3 +1,8 @@
1
+ 15 Feb 2012
2
+ -----------
3
+
4
+ Merged pull request https://github.com/mattheworiordan/capybara-screenshot/pull/14 to limit when capybara-screenshot is fired for RSpec
5
+
1
6
  30 Jan 2012
2
7
  -----------
3
8
 
data/Gemfile CHANGED
@@ -2,3 +2,5 @@ source "http://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in capybara-screenshot.gemspec
4
4
  gemspec
5
+
6
+ gem 'rake'
data/README.md CHANGED
@@ -18,6 +18,28 @@ or update your Gemfile to include:
18
18
 
19
19
  That's it!
20
20
 
21
+ If you require more control, you can generate the screenshot on demand rather than on failure. This is useful
22
+ if the failure occurs at a point where the screen shot is not as useful for debugging a rendering problem.
23
+
24
+ In Cucumber,
25
+
26
+ screen_shot_and_save_page
27
+
28
+ Or for screenshot only, with image automatically opened
29
+
30
+ screen_shot_and_open_image
31
+
32
+ Or anywhere, including specs and tests
33
+
34
+ Capybara::Screenshot.screen_shot_and_save_page
35
+
36
+ Capybara::Screenshot.screen_shot_and_open_image
37
+
38
+ This can be more useful if you disable the auto-generate on failure feature with the following config
39
+
40
+ Capybara::Screenshot.autosave_on_failure = false
41
+
42
+
21
43
  Example application
22
44
  -------------------
23
45
 
@@ -16,6 +16,7 @@ Gem::Specification.new do |s|
16
16
 
17
17
  s.add_dependency 'capybara', '>= 1.0'
18
18
  s.add_development_dependency 'rspec', '~> 2.6'
19
+ s.add_development_dependency 'timecop'
19
20
 
20
21
  s.files = `git ls-files`.split("\n")
21
22
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
@@ -1,21 +1,69 @@
1
+ module Capybara
2
+ module Screenshot
3
+ class << self
4
+ attr_accessor :autosave_on_failure
5
+ attr_accessor :registered_drivers
6
+ end
7
+
8
+ self.autosave_on_failure = true
9
+ self.registered_drivers = {}
10
+
11
+ def self.screen_shot_and_save_page
12
+ saver = Saver.new(Capybara, Capybara.page)
13
+ saver.save
14
+ {:html => saver.html_path, :image => saver.screenshot_path}
15
+ end
16
+
17
+ def self.screen_shot_and_open_image
18
+ require "launchy"
19
+
20
+ saver = Saver.new(Capybara, Capybara.page, false)
21
+ saver.save
22
+ Launchy.open saver.screenshot_path
23
+ {:html => saver.html_path, :image => saver.screenshot_path}
24
+ end
25
+
26
+ def self.capybara_root
27
+ return @capybara_root if defined?(@capybara_root)
28
+
29
+ capybara_tmp_path = Capybara.save_and_open_page_path.to_s
30
+
31
+ @capybara = if defined?(Rails)
32
+ Rails.root.join capybara_tmp_path
33
+ elsif defined?(Padrino)
34
+ Padrino.root capybara_tmp_path
35
+ elsif defined?(Sinatra)
36
+ # Sinatra support, untested
37
+ File.join(settings.root, capybara_tmp_path)
38
+ else
39
+ capybara_tmp_path
40
+ end.to_s
41
+ end
42
+
43
+ def self.register_driver(driver, &block)
44
+ self.registered_drivers[driver] = block
45
+ end
46
+ end
47
+ end
48
+
49
+ Capybara::Screenshot.register_driver(:selenium) do |driver, path|
50
+ driver.browser.save_screenshot(path)
51
+ end
52
+
53
+ Capybara::Screenshot.register_driver(:poltergeist) do |driver, path|
54
+ driver.render(path, :full => true)
55
+ end
56
+
57
+ Capybara::Screenshot.register_driver(:webkit) do |driver, path|
58
+ driver.render(path)
59
+ end
60
+
61
+ require 'capybara-screenshot/saver'
62
+
1
63
  # do nothing if Cucumber is not being used
2
64
  if defined?(Cucumber::RbSupport::RbDsl)
3
65
  require 'capybara/cucumber'
4
66
  require 'capybara-screenshot/cucumber'
5
-
6
- After do |scenario|
7
- if scenario.failed?
8
- screenshot_path = Capybara::Screenshot::Cucumber.screen_shot_and_save_page[:image]
9
- # Trying to embed the screenshot into our output."
10
- if File.exist?(screenshot_path)
11
- require "base64"
12
- #encode the image into it's base64 representation
13
- encoded_img = Base64.encode64(IO.read(screenshot_path))
14
- #this will embed the image in the HTML report, embed() is defined in cucumber
15
- embed("data:image/png;base64,#{encoded_img}", 'image/png', "Screenshot of the error")
16
- end
17
- end
18
- end
19
67
  end
20
68
 
21
69
  if defined?(RSpec)
@@ -23,11 +71,6 @@ if defined?(RSpec)
23
71
  # RSpec hooks afterwards, and thus executed first
24
72
  require 'capybara/rspec'
25
73
  require 'capybara-screenshot/rspec'
26
- RSpec.configure do |config|
27
- config.after do
28
- Capybara::Screenshot::RSpec.screen_shot_and_save_page if example.exception
29
- end
30
- end
31
74
  end
32
75
 
33
76
  begin
@@ -35,4 +78,4 @@ begin
35
78
  require 'capybara-screenshot/minitest'
36
79
  rescue LoadError
37
80
  # mini test not available
38
- end
81
+ end
@@ -1,11 +1,32 @@
1
- require 'capybara-screenshot/saver'
2
-
3
1
  module Capybara
4
2
  module Screenshot
5
3
  module Cucumber
6
- def self.screen_shot_and_save_page
7
- Capybara::Screenshot::Saver.screen_shot_and_save_page Capybara, Capybara.body
4
+
5
+ def screen_shot_and_save_page
6
+ Capybara::Screenshot.screen_shot_and_save_page
7
+ end
8
+
9
+ def screen_shot_and_open_image
10
+ Capybara::Screenshot.screen_shot_and_open_image
8
11
  end
12
+
13
+ end
14
+ end
15
+ end
16
+ World(Capybara::Screenshot::Cucumber)
17
+
18
+ After do |scenario|
19
+ if Capybara::Screenshot.autosave_on_failure && scenario.failed?
20
+ saver = Capybara::Screenshot::Saver.new(Capybara, Capybara.page)
21
+ saver.save
22
+
23
+ # Trying to embed the screenshot into our output."
24
+ if File.exist?(saver.screenshot_path)
25
+ require "base64"
26
+ #encode the image into it's base64 representation
27
+ encoded_img = Base64.encode64(IO.read(saver.screenshot_path))
28
+ #this will embed the image in the HTML report, embed() is defined in cucumber
29
+ embed("data:image/png;base64,#{encoded_img}", 'image/png', "Screenshot of the error")
9
30
  end
10
31
  end
11
32
  end
@@ -1,5 +1,3 @@
1
- require 'capybara-screenshot/saver'
2
-
3
1
  if defined?(ActionDispatch::IntegrationTest)
4
2
  method = if ActionDispatch::IntegrationTest.respond_to? :teardown
5
3
  :teardown
@@ -13,8 +11,8 @@ if defined?(ActionDispatch::IntegrationTest)
13
11
  # by adding the argument context, MiniTest passes the context of the test
14
12
  # which has an instance variable @passed indicating success / failure
15
13
  context.instance_eval do
16
- if @passed.blank?
17
- Capybara::Screenshot::Saver.screen_shot_and_save_page Capybara, Capybara.body
14
+ if Capybara::Screenshot.autosave_on_failure && @passed.blank?
15
+ Capybara::Screenshot.screen_shot_and_save_page
18
16
  end
19
17
  end
20
18
  end
@@ -1,11 +1,10 @@
1
- require 'capybara-screenshot/saver'
1
+ RSpec.configure do |config|
2
+ config.after(:type => :request) do
3
+ if Capybara::Screenshot.autosave_on_failure && example.exception
4
+ saver = Capybara::Screenshot::Saver.new(Capybara, Capybara.page)
5
+ saver.save
2
6
 
3
- module Capybara
4
- module Screenshot
5
- class RSpec
6
- def self.screen_shot_and_save_page
7
- Capybara::Screenshot::Saver.screen_shot_and_save_page Capybara, Capybara.body
8
- end
7
+ example.metadata[:full_description] += "\n Screenshot: #{saver.screenshot_path}"
9
8
  end
10
9
  end
11
10
  end
@@ -1,49 +1,47 @@
1
1
  module Capybara
2
2
  module Screenshot
3
- module Saver
4
- def self.screen_shot_and_save_page(capybara, body)
5
- #Our default return values
6
- html_path = nil
7
- image_path = nil
3
+ class Saver
4
+ attr_reader :capybara, :page, :file_base_name
8
5
 
6
+ def initialize(capybara, page, html_save=true)
7
+ @capybara, @page, @html_save = capybara, page, html_save
8
+ @file_base_name = "screenshot-#{Time.now.strftime('%Y-%m-%d-%H-%M-%S')}"
9
+ end
10
+
11
+ def save
9
12
  # if current_path empty then nothing to screen shot as browser has not loaded any URL
10
- unless capybara.current_path.to_s.empty?
11
- require 'capybara/util/save_and_open_page'
12
- file_base_name = "#{Time.now.strftime('%Y-%m-%d-%H-%M-%S')}"
13
- #will save to the capybara.save_and_open_page_path
14
- html_path = "{capybara.save_and_open_page_path}#{file_base_name}.html"
15
- capybara.save_page(body, "#{file_base_name}.html")
16
-
17
- #where should we save the screenshot to
18
- if defined?(Rails)
19
- screenshot_path = Rails.root.join "#{capybara.save_and_open_page_path}/#{file_base_name}.png"
20
- elsif defined?(Padrino)
21
- screenshot_path = Padrino.root "#{capybara.save_and_open_page_path}/#{file_base_name}.png"
22
- elsif defined?(Sinatra)
23
- # Sinatra support, untested
24
- screenshot_path = File.join(settings.root, "#{capybara.save_and_open_page_path}/#{file_base_name}.png")
25
- else
26
- screenshot_path = File.join(capybara.save_and_open_page_path.to_s, "#{file_base_name}.png")
27
- end
28
-
29
- #We try to figure out how to call the screenshot method on the current driver
30
- case capybara.current_driver
31
- when :poltergeist
32
- capybara.page.driver.render(screenshot_path, :full => true)
33
- when :selenium
34
- capybara.page.driver.browser.save_screenshot(screenshot_path)
35
- else
36
- #For other drivers that support a plain .render call and only expect the path as a parameter
37
- #This includes e.g. capybara-webkit
38
- if capybara.page.driver.respond_to?(:render)
39
- capybara.page.driver.render(screenshot_path)
40
- end
41
- end
13
+ return if capybara.current_path.to_s.empty?
14
+
15
+ save_html if @html_save
16
+ save_screenshot
17
+ end
18
+
19
+ def save_html
20
+ require 'capybara/util/save_and_open_page'
21
+ capybara.save_page(page.body, "#{file_base_name}.html")
22
+ end
23
+
24
+ def save_screenshot
25
+ if Capybara::Screenshot.registered_drivers.has_key?(capybara.current_driver)
26
+ Capybara::Screenshot.registered_drivers[capybara.current_driver].call(page.driver, screenshot_path)
27
+ else
28
+ warn "capybara-screenshot could not detect a screenshot driver for '#{capybara.current_driver}'. Saving with default with unknown results."
29
+ save_with_default
42
30
  end
43
- #we return the path to the html and the screenshot
44
- {:html => html_path, :image => screenshot_path}
45
31
  end
32
+
33
+ def save_with_default
34
+ page.driver.render(screenshot_path)
35
+ end
36
+
37
+ def html_path
38
+ File.join(Capybara::Screenshot.capybara_root, "#{file_base_name}.html")
39
+ end
40
+
41
+ def screenshot_path
42
+ File.join(Capybara::Screenshot.capybara_root, "#{file_base_name}.png")
43
+ end
44
+
46
45
  end
47
46
  end
48
47
  end
49
-
@@ -1,5 +1,5 @@
1
1
  module Capybara
2
2
  module Screenshot
3
- VERSION = "0.1.10"
3
+ VERSION = "0.2"
4
4
  end
5
5
  end
@@ -0,0 +1,117 @@
1
+ require 'spec_helper'
2
+
3
+ describe Capybara::Screenshot::Saver do
4
+ before(:all) do
5
+ @original_drivers = Capybara::Screenshot.registered_drivers
6
+ Capybara::Screenshot.registered_drivers[:default] = lambda {|driver, path| driver.render(path) }
7
+ end
8
+
9
+ after(:all) do
10
+ Capybara::Screenshot.registered_drivers = @original_drivers
11
+ end
12
+
13
+ before do
14
+ Capybara::Screenshot.stub(:capybara_root).and_return(capybara_root)
15
+ Timecop.freeze(Time.local(2012, 6, 7, 8, 9, 10))
16
+ end
17
+
18
+ let(:capybara_root) { '/tmp' }
19
+ let(:file_basename) { "screenshot-2012-06-07-08-09-10" }
20
+ let(:screenshot_path) { "#{capybara_root}/#{file_basename}.png" }
21
+
22
+ let(:driver_mock) { mock('Capybara driver').as_null_object }
23
+ let(:page_mock) { mock('Capybara session page', :body => 'body', :driver => driver_mock).as_null_object }
24
+ let(:capybara_mock) {
25
+ mock(Capybara).as_null_object.tap do |m|
26
+ m.stub(:current_driver).and_return(:default)
27
+ m.stub(:current_path).and_return('/')
28
+ end
29
+ }
30
+
31
+ let(:saver) { Capybara::Screenshot::Saver.new(capybara_mock, page_mock) }
32
+
33
+ it 'should save html file with "screenshot-Y-M-D-H-M-S.html" format' do
34
+ capybara_mock.should_receive(:save_page).with('body', "#{file_basename}.html")
35
+
36
+ saver.save
37
+ end
38
+
39
+ it 'should save screenshot file in capybara root output directory with format "screenshot-Y-M-D-H-M-S.png"' do
40
+ driver_mock.should_receive(:render).with(screenshot_path)
41
+
42
+ saver.save
43
+ end
44
+
45
+ it 'should not save html if false passed as html argument' do
46
+ saver = Capybara::Screenshot::Saver.new(capybara_mock, page_mock, false)
47
+ capybara_mock.should_not_receive(:save_page)
48
+
49
+ saver.save
50
+ end
51
+
52
+ it 'should save if current_path is empty' do
53
+ capybara_mock.stub(:current_path).and_return(nil)
54
+ capybara_mock.should_not_receive(:save_page)
55
+ driver_mock.should_not_receive(:render)
56
+
57
+ saver.save
58
+ end
59
+
60
+ describe "with selenium driver" do
61
+ before do
62
+ capybara_mock.stub(:current_driver).and_return(:selenium)
63
+ end
64
+
65
+ it 'should save via browser' do
66
+ browser_mock = mock('browser')
67
+ driver_mock.should_receive(:browser).and_return(browser_mock)
68
+ browser_mock.should_receive(:save_screenshot).with(screenshot_path)
69
+
70
+ saver.save
71
+ end
72
+ end
73
+
74
+ describe "with poltergeist driver" do
75
+ before do
76
+ capybara_mock.stub(:current_driver).and_return(:poltergeist)
77
+ end
78
+
79
+ it 'should save driver render with :full => true' do
80
+ driver_mock.should_receive(:render).with(screenshot_path, {:full => true})
81
+
82
+ saver.save
83
+ end
84
+ end
85
+
86
+ describe "with webkit driver" do
87
+ before do
88
+ capybara_mock.stub(:current_driver).and_return(:webkit)
89
+ end
90
+
91
+ it 'should save driver render' do
92
+ driver_mock.should_receive(:render).with(screenshot_path)
93
+
94
+ saver.save
95
+ end
96
+ end
97
+
98
+ describe "with unknown driver" do
99
+ before do
100
+ capybara_mock.stub(:current_driver).and_return(:unknown)
101
+ saver.stub(:warn).and_return(nil)
102
+ end
103
+
104
+ it 'should save driver render' do
105
+ driver_mock.should_receive(:render).with(screenshot_path)
106
+
107
+ saver.save
108
+ end
109
+
110
+ it 'should output warning about unknown results' do
111
+ # Not pure mock testing
112
+ saver.should_receive(:warn).with(/screenshot driver for 'unknown'.*unknown results/).and_return(nil)
113
+
114
+ saver.save
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe Capybara::Screenshot do
4
+ before(:all) do
5
+ @original_drivers = Capybara::Screenshot.registered_drivers
6
+ end
7
+
8
+ after(:all) do
9
+ Capybara::Screenshot.registered_drivers = @original_drivers
10
+ end
11
+
12
+ describe ".register_driver" do
13
+ it 'should store driver with block' do
14
+ block = lambda {}
15
+ Capybara::Screenshot.register_driver :foo, &block
16
+
17
+ Capybara::Screenshot.registered_drivers[:foo].should eq block
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,16 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper.rb"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+
8
+ $: << '../lib'
9
+ require 'capybara-screenshot'
10
+ require 'timecop'
11
+
12
+ RSpec.configure do |config|
13
+ config.treat_symbols_as_metadata_keys_with_true_values = true
14
+ config.run_all_when_everything_filtered = true
15
+ config.filter_run :focus
16
+ end
metadata CHANGED
@@ -1,64 +1,74 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: capybara-screenshot
3
- version: !ruby/object:Gem::Version
4
- hash: 15
5
- prerelease: false
6
- segments:
7
- - 0
8
- - 1
9
- - 10
10
- version: 0.1.10
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.2'
5
+ prerelease:
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Matthew O'Riordan
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2012-01-30 00:00:00 +00:00
19
- default_executable:
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
12
+ date: 2012-06-20 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
22
15
  name: capybara
23
- prerelease: false
24
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
25
17
  none: false
26
- requirements:
27
- - - ">="
28
- - !ruby/object:Gem::Version
29
- hash: 15
30
- segments:
31
- - 1
32
- - 0
33
- version: "1.0"
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '1.0'
34
22
  type: :runtime
35
- version_requirements: *id001
36
- - !ruby/object:Gem::Dependency
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '1.0'
30
+ - !ruby/object:Gem::Dependency
37
31
  name: rspec
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '2.6'
38
+ type: :development
38
39
  prerelease: false
39
- requirement: &id002 !ruby/object:Gem::Requirement
40
+ version_requirements: !ruby/object:Gem::Requirement
40
41
  none: false
41
- requirements:
42
+ requirements:
42
43
  - - ~>
43
- - !ruby/object:Gem::Version
44
- hash: 15
45
- segments:
46
- - 2
47
- - 6
48
- version: "2.6"
44
+ - !ruby/object:Gem::Version
45
+ version: '2.6'
46
+ - !ruby/object:Gem::Dependency
47
+ name: timecop
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
49
54
  type: :development
50
- version_requirements: *id002
51
- description: When a Cucumber step fails, it is useful to create a screenshot image and HTML file of the current page
52
- email:
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: When a Cucumber step fails, it is useful to create a screenshot image
63
+ and HTML file of the current page
64
+ email:
53
65
  - matthew.oriordan@gmail.com
54
66
  executables: []
55
-
56
67
  extensions: []
57
-
58
68
  extra_rdoc_files: []
59
-
60
- files:
69
+ files:
61
70
  - .gitignore
71
+ - .rspec
62
72
  - CHANGELOG.md
63
73
  - Gemfile
64
74
  - LICENSE
@@ -71,39 +81,41 @@ files:
71
81
  - lib/capybara-screenshot/rspec.rb
72
82
  - lib/capybara-screenshot/saver.rb
73
83
  - lib/capybara-screenshot/version.rb
74
- has_rdoc: true
84
+ - spec/capybara-screenshot/saver_spec.rb
85
+ - spec/capybara-screenshot_spec.rb
86
+ - spec/spec_helper.rb
75
87
  homepage: http://github.com/mattheworiordan/capybara-screenshot
76
88
  licenses: []
77
-
78
89
  post_install_message:
79
90
  rdoc_options: []
80
-
81
- require_paths:
91
+ require_paths:
82
92
  - lib
83
- required_ruby_version: !ruby/object:Gem::Requirement
93
+ required_ruby_version: !ruby/object:Gem::Requirement
84
94
  none: false
85
- requirements:
86
- - - ">="
87
- - !ruby/object:Gem::Version
88
- hash: 3
89
- segments:
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ segments:
90
100
  - 0
91
- version: "0"
92
- required_rubygems_version: !ruby/object:Gem::Requirement
101
+ hash: 1087741615674543132
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
93
103
  none: false
94
- requirements:
95
- - - ">="
96
- - !ruby/object:Gem::Version
97
- hash: 3
98
- segments:
104
+ requirements:
105
+ - - ! '>='
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ segments:
99
109
  - 0
100
- version: "0"
110
+ hash: 1087741615674543132
101
111
  requirements: []
102
-
103
112
  rubyforge_project: capybara-screenshot
104
- rubygems_version: 1.3.7
113
+ rubygems_version: 1.8.24
105
114
  signing_key:
106
115
  specification_version: 3
107
- summary: Automatically create snapshots when Cucumber steps fail with Capybara and Rails
108
- test_files: []
109
-
116
+ summary: Automatically create snapshots when Cucumber steps fail with Capybara and
117
+ Rails
118
+ test_files:
119
+ - spec/capybara-screenshot/saver_spec.rb
120
+ - spec/capybara-screenshot_spec.rb
121
+ - spec/spec_helper.rb