capybara-screenshot-nocolor 1.0.5

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.
Files changed (57) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +7 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +17 -0
  5. data/Appraisals +31 -0
  6. data/CHANGELOG.md +198 -0
  7. data/Gemfile +7 -0
  8. data/LICENSE +19 -0
  9. data/README.md +240 -0
  10. data/Rakefile +40 -0
  11. data/capybara-screenshot.gemspec +38 -0
  12. data/gemfiles/cucumber.1.2.gemfile +9 -0
  13. data/gemfiles/cucumber.1.3.0.gemfile +9 -0
  14. data/gemfiles/latest.gemfile +8 -0
  15. data/gemfiles/rspec.2.14.gemfile +9 -0
  16. data/gemfiles/rspec.2.99.gemfile +9 -0
  17. data/gemfiles/rspec.3.0.gemfile +9 -0
  18. data/gemfiles/spinach.0.7.gemfile +9 -0
  19. data/gemfiles/spinach.0.8.0.gemfile +9 -0
  20. data/lib/capybara-screenshot.rb +157 -0
  21. data/lib/capybara-screenshot/capybara.rb +28 -0
  22. data/lib/capybara-screenshot/cucumber.rb +27 -0
  23. data/lib/capybara-screenshot/minitest.rb +27 -0
  24. data/lib/capybara-screenshot/pruner.rb +47 -0
  25. data/lib/capybara-screenshot/rspec.rb +92 -0
  26. data/lib/capybara-screenshot/rspec/base_reporter.rb +21 -0
  27. data/lib/capybara-screenshot/rspec/html_embed_reporter.rb +25 -0
  28. data/lib/capybara-screenshot/rspec/html_link_reporter.rb +37 -0
  29. data/lib/capybara-screenshot/rspec/text_reporter.rb +38 -0
  30. data/lib/capybara-screenshot/rspec/textmate_link_reporter.rb +19 -0
  31. data/lib/capybara-screenshot/saver.rb +87 -0
  32. data/lib/capybara-screenshot/spinach.rb +26 -0
  33. data/lib/capybara-screenshot/testunit.rb +39 -0
  34. data/lib/capybara-screenshot/version.rb +5 -0
  35. data/spec/cucumber/cucumber_spec.rb +93 -0
  36. data/spec/cucumber/step_definitions/step_definitions.rb +18 -0
  37. data/spec/cucumber/support/env.rb +17 -0
  38. data/spec/feature/minitest_spec.rb +110 -0
  39. data/spec/feature/testunit_spec.rb +81 -0
  40. data/spec/rspec/rspec_spec.rb +159 -0
  41. data/spec/spec_helper.rb +29 -0
  42. data/spec/spinach/spinach_spec.rb +64 -0
  43. data/spec/spinach/support/spinach_failure.rb +41 -0
  44. data/spec/support/common_setup.rb +59 -0
  45. data/spec/support/html_reporter_context.rb +28 -0
  46. data/spec/support/test_app.rb +13 -0
  47. data/spec/unit/base_reporter_spec.rb +25 -0
  48. data/spec/unit/capybara-screenshot_rspec_spec.rb +48 -0
  49. data/spec/unit/capybara-screenshot_spec.rb +88 -0
  50. data/spec/unit/capybara_spec.rb +50 -0
  51. data/spec/unit/pruner_spec.rb +108 -0
  52. data/spec/unit/rspec_reporters/html_embed_reporter_spec.rb +18 -0
  53. data/spec/unit/rspec_reporters/html_link_reporter_spec.rb +27 -0
  54. data/spec/unit/rspec_reporters/text_reporter_spec.rb +97 -0
  55. data/spec/unit/rspec_reporters/textmate_link_reporter_spec.rb +39 -0
  56. data/spec/unit/saver_spec.rb +282 -0
  57. metadata +247 -0
@@ -0,0 +1,92 @@
1
+ require "capybara-screenshot"
2
+
3
+ require "capybara-screenshot/rspec/text_reporter"
4
+ require "capybara-screenshot/rspec/html_link_reporter"
5
+ require "capybara-screenshot/rspec/html_embed_reporter"
6
+ require "capybara-screenshot/rspec/textmate_link_reporter"
7
+
8
+ module Capybara
9
+ module Screenshot
10
+ module RSpec
11
+
12
+ # Reporters extend RSpec formatters to display information about screenshots for failed
13
+ # examples.
14
+ #
15
+ # Technically, a reporter is a module that gets injected into a RSpec formatter class.
16
+ # It uses method aliasing to extend some (usually just one) of the formatter's methods.
17
+ #
18
+ # Implementing a custom reporter is as simple as creating a module and setting up the
19
+ # appropriate aliases. Use `BaseReporter.enhance_with_screenshot` if you don't want
20
+ # to set up the aliases manually:
21
+ #
22
+ # module MyReporter
23
+ # extend Capybara::Screenshot::RSpec::BaseReporter
24
+ #
25
+ # # Will replace the formatter's original `dump_failure_info` method with
26
+ # # `dump_failure_info_with_screenshot` from this module:
27
+ # enhance_with_screenshot :dump_failure_info
28
+ #
29
+ # def dump_failure_info_with_screenshot(example)
30
+ # dump_failure_info_without_screenshot(example) # call original implementation
31
+ # ... # your additions here
32
+ # end
33
+ # end
34
+ #
35
+ # Finally customize `Capybara::Screenshot::RSpec::FORMATTERS` to make sure your reporter
36
+ # gets injected into the appropriate formatter.
37
+
38
+ REPORTERS = {
39
+ "RSpec::Core::Formatters::ProgressFormatter" => Capybara::Screenshot::RSpec::TextReporter,
40
+ "RSpec::Core::Formatters::DocumentationFormatter" => Capybara::Screenshot::RSpec::TextReporter,
41
+ "RSpec::Core::Formatters::HtmlFormatter" => Capybara::Screenshot::RSpec::HtmlLinkReporter,
42
+ "RSpec::Core::Formatters::TextMateFormatter" => Capybara::Screenshot::RSpec::TextMateLinkReporter, # RSpec 2
43
+ "RSpec::Mate::Formatters::TextMateFormatter" => Capybara::Screenshot::RSpec::TextMateLinkReporter # RSpec 3
44
+ }
45
+
46
+ class << self
47
+ attr_accessor :add_link_to_screenshot_for_failed_examples
48
+
49
+ def after_failed_example(example)
50
+ if example.example_group.include?(Capybara::DSL) # Capybara DSL method has been included for a feature we can snapshot
51
+ Capybara.using_session(Capybara::Screenshot.final_session_name) do
52
+ if Capybara.page.current_url != '' && Capybara::Screenshot.autosave_on_failure && example.exception
53
+ filename_prefix = Capybara::Screenshot.filename_prefix_for(:rspec, example)
54
+
55
+ saver = Capybara::Screenshot::Saver.new(Capybara, Capybara.page, true, filename_prefix)
56
+ saver.save
57
+
58
+ example.metadata[:screenshot] = {}
59
+ example.metadata[:screenshot][:html] = saver.html_path if saver.html_saved?
60
+ example.metadata[:screenshot][:image] = saver.screenshot_path if saver.screenshot_saved?
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+
67
+ self.add_link_to_screenshot_for_failed_examples = true
68
+ end
69
+ end
70
+ end
71
+
72
+ RSpec.configure do |config|
73
+ config.before do
74
+ Capybara::Screenshot.final_session_name = nil
75
+ end
76
+
77
+ config.after do |example_from_block_arg|
78
+ # RSpec 3 no longer defines `example`, but passes the example as block argument instead
79
+ example = config.respond_to?(:expose_current_running_example_as) ? example_from_block_arg : self.example
80
+
81
+ Capybara::Screenshot::RSpec.after_failed_example(example)
82
+ end
83
+
84
+ config.before(:suite) do
85
+ if Capybara::Screenshot::RSpec.add_link_to_screenshot_for_failed_examples
86
+ RSpec.configuration.formatters.each do |formatter|
87
+ next unless (reporter_module = Capybara::Screenshot::RSpec::REPORTERS[formatter.class.to_s])
88
+ formatter.singleton_class.send :include, reporter_module
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,21 @@
1
+ module Capybara
2
+ module Screenshot
3
+ module RSpec
4
+ module BaseReporter
5
+
6
+ # Automatically set up method aliases (very much like ActiveSupport's `alias_method_chain`)
7
+ # when the module gets included.
8
+ def enhance_with_screenshot(method)
9
+ with_method, without_method = "#{method}_with_screenshot", "#{method}_without_screenshot"
10
+ define_singleton_method :included do |mod|
11
+ if mod.method_defined?(method) || mod.private_method_defined?(method)
12
+ mod.send :alias_method, without_method, method
13
+ mod.send :alias_method, method, with_method
14
+ end
15
+ end
16
+ end
17
+
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,25 @@
1
+ require 'capybara-screenshot/rspec/base_reporter'
2
+ require 'base64'
3
+
4
+ module Capybara
5
+ module Screenshot
6
+ module RSpec
7
+ module HtmlEmbedReporter
8
+ extend BaseReporter
9
+ enhance_with_screenshot :extra_failure_content
10
+
11
+ def extra_failure_content_with_screenshot(exception)
12
+ result = extra_failure_content_without_screenshot(exception)
13
+ example = @failed_examples.last
14
+ # Ignores saved html file, only saved image will be embedded (if present)
15
+ if (screenshot = example.metadata[:screenshot]) && screenshot[:image]
16
+ image = File.binread(screenshot[:image])
17
+ encoded_img = Base64.encode64(image)
18
+ result += "<img src='data:image/png;base64,#{encoded_img}' style='display: block'>"
19
+ end
20
+ result
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,37 @@
1
+ require 'capybara-screenshot/rspec/base_reporter'
2
+ require 'cgi'
3
+ require 'uri'
4
+
5
+ module Capybara
6
+ module Screenshot
7
+ module RSpec
8
+ module HtmlLinkReporter
9
+ extend BaseReporter
10
+ enhance_with_screenshot :extra_failure_content
11
+
12
+ def extra_failure_content_with_screenshot(exception)
13
+ result = extra_failure_content_without_screenshot(exception)
14
+ example = @failed_examples.last
15
+ if (screenshot = example.metadata[:screenshot])
16
+ result << "<p>Saved files: "
17
+ result << link_to_screenshot("HTML page", screenshot[:html]) if screenshot[:html]
18
+ result << link_to_screenshot("Screenshot", screenshot[:image]) if screenshot[:image]
19
+ result << "</p>"
20
+ end
21
+ result
22
+ end
23
+
24
+ def link_to_screenshot(title, path)
25
+ url = URI.escape("file://#{path}")
26
+ title = CGI.escape_html(title)
27
+ attributes = attributes_for_screenshot_link(url).map { |name, val| %{#{name}="#{CGI.escape_html(val)}"} }.join(" ")
28
+ "<a #{attributes}>#{title}</a>"
29
+ end
30
+
31
+ def attributes_for_screenshot_link(url)
32
+ {"href" => url, "style" => "margin-right: 10px; font-weight: bold"}
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,38 @@
1
+ require 'capybara-screenshot/rspec/base_reporter'
2
+
3
+ module Capybara
4
+ module Screenshot
5
+ module RSpec
6
+ module TextReporter
7
+ extend BaseReporter
8
+
9
+ if ::RSpec::Core::Version::STRING.to_i <= 2
10
+ enhance_with_screenshot :dump_failure_info
11
+ else
12
+ enhance_with_screenshot :example_failed
13
+ end
14
+
15
+ def dump_failure_info_with_screenshot(example)
16
+ dump_failure_info_without_screenshot example
17
+ output_screenshot_info(example)
18
+ end
19
+
20
+ def example_failed_with_screenshot(notification)
21
+ example_failed_without_screenshot notification
22
+ output_screenshot_info(notification.example)
23
+ end
24
+
25
+ private
26
+ def output_screenshot_info(example)
27
+ return unless (screenshot = example.metadata[:screenshot])
28
+ output.puts(long_padding + "HTML screenshot: #{screenshot[:html]}") if screenshot[:html]
29
+ output.puts(long_padding + "Image screenshot: #{screenshot[:image]}") if screenshot[:image]
30
+ end
31
+
32
+ def long_padding
33
+ " "
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,19 @@
1
+ require 'capybara-screenshot/rspec/base_reporter'
2
+ require 'capybara-screenshot/rspec/html_link_reporter'
3
+ require 'shellwords'
4
+
5
+ module Capybara
6
+ module Screenshot
7
+ module RSpec
8
+ module TextMateLinkReporter
9
+ extend BaseReporter
10
+ include HtmlLinkReporter
11
+ enhance_with_screenshot :extra_failure_content
12
+
13
+ def attributes_for_screenshot_link(url)
14
+ super.merge("onclick" => "TextMate.system('open #{Shellwords.escape(url)}'); return false;")
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,87 @@
1
+ module Capybara
2
+ module Screenshot
3
+ class Saver
4
+ attr_reader :capybara, :page, :file_base_name
5
+ def initialize(capybara, page, html_save=true, filename_prefix='screenshot')
6
+ @capybara, @page, @html_save = capybara, page, html_save
7
+ time_now = Time.now
8
+ timestamp = "#{time_now.strftime('%Y-%m-%d-%H-%M-%S.')}#{'%03d' % (time_now.usec/1000).to_i}"
9
+
10
+ filename = [filename_prefix]
11
+ filename << timestamp if Capybara::Screenshot.append_timestamp
12
+ filename << SecureRandom.hex if Capybara::Screenshot.append_random
13
+
14
+ @file_base_name = filename.join('_')
15
+
16
+ Capybara::Screenshot.prune
17
+ end
18
+
19
+ def save
20
+ # if current_path empty then nothing to screen shot as browser has not loaded any URL
21
+ return if capybara.current_path.to_s.empty?
22
+
23
+ save_html if @html_save
24
+ save_screenshot
25
+ end
26
+
27
+ def save_html
28
+ path = html_path
29
+ clear_save_and_open_page_path do
30
+ if Capybara::VERSION.match(/^\d+/)[0] == '1'
31
+ capybara.save_page(page.body, "#{path}")
32
+ else
33
+ capybara.save_page("#{path}")
34
+ end
35
+ end
36
+ @html_saved = true
37
+ end
38
+
39
+ def save_screenshot
40
+ path = screenshot_path
41
+ clear_save_and_open_page_path do
42
+ result = Capybara::Screenshot.registered_drivers.fetch(capybara.current_driver) { |driver_name|
43
+ warn "capybara-screenshot could not detect a screenshot driver for '#{capybara.current_driver}'. Saving with default with unknown results."
44
+ Capybara::Screenshot.registered_drivers[:default]
45
+ }.call(page.driver, path)
46
+ @screenshot_saved = result != :not_supported
47
+ end
48
+ end
49
+
50
+ def html_path
51
+ File.join(Capybara::Screenshot.capybara_root, "#{file_base_name}.html")
52
+ end
53
+
54
+ def screenshot_path
55
+ File.join(Capybara::Screenshot.capybara_root, "#{file_base_name}.png")
56
+ end
57
+
58
+ def html_saved?
59
+ @html_saved
60
+ end
61
+
62
+ def screenshot_saved?
63
+ @screenshot_saved
64
+ end
65
+
66
+ # If Capybara.save_and_open_page_path is set then
67
+ # the html_path or screenshot_path can be appended to this path in
68
+ # some versions of Capybara instead of using it as an absolute path
69
+ def clear_save_and_open_page_path
70
+ old_path = Capybara.save_and_open_page_path
71
+ Capybara.save_and_open_page_path = nil
72
+ yield
73
+ Capybara.save_and_open_page_path = old_path
74
+ end
75
+
76
+ def output_screenshot_path
77
+ output "HTML screenshot: #{html_path}" if html_saved?
78
+ output "Image screenshot: #{screenshot_path}" if screenshot_saved?
79
+ end
80
+
81
+ private
82
+ def output(message)
83
+ puts " #{message}"
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,26 @@
1
+ require "capybara-screenshot"
2
+
3
+ Spinach.hooks.before_scenario do |scenario|
4
+ Capybara::Screenshot.final_session_name = nil
5
+ end
6
+
7
+ module Capybara::Screenshot::Spinach
8
+ def self.fail_with_screenshot(step_data, exception, location, step_definitions)
9
+ if Capybara::Screenshot.autosave_on_failure
10
+ Capybara.using_session(Capybara::Screenshot.final_session_name) do
11
+ filename_prefix = Capybara::Screenshot.filename_prefix_for(:spinach, step_data)
12
+ saver = Capybara::Screenshot::Saver.new(Capybara, Capybara.page, true, filename_prefix)
13
+ saver.save
14
+ saver.output_screenshot_path
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ Spinach.hooks.on_failed_step do |*args|
21
+ Capybara::Screenshot::Spinach.fail_with_screenshot(*args)
22
+ end
23
+
24
+ Spinach.hooks.on_error_step do |*args|
25
+ Capybara::Screenshot::Spinach.fail_with_screenshot(*args)
26
+ end
@@ -0,0 +1,39 @@
1
+ require 'test/unit/testresult'
2
+
3
+ module Capybara::Screenshot
4
+ class << self
5
+ attr_accessor :testunit_paths
6
+ end
7
+
8
+ self.testunit_paths = [%r{test/integration}]
9
+ end
10
+
11
+ Test::Unit::TestCase.class_eval do
12
+ setup do
13
+ Capybara::Screenshot.final_session_name = nil
14
+ end
15
+ end
16
+
17
+ Test::Unit::TestResult.class_eval do
18
+ private
19
+
20
+ def notify_fault_with_screenshot(fault, *args)
21
+ notify_fault_without_screenshot fault, *args
22
+ is_integration_test = fault.location.any? do |location|
23
+ Capybara::Screenshot.testunit_paths.any? { |path| location.match(path) }
24
+ end
25
+ if is_integration_test
26
+ if Capybara::Screenshot.autosave_on_failure
27
+ Capybara.using_session(Capybara::Screenshot.final_session_name) do
28
+ filename_prefix = Capybara::Screenshot.filename_prefix_for(:testunit, fault)
29
+
30
+ saver = Capybara::Screenshot::Saver.new(Capybara, Capybara.page, true, filename_prefix)
31
+ saver.save
32
+ saver.output_screenshot_path
33
+ end
34
+ end
35
+ end
36
+ end
37
+ alias notify_fault_without_screenshot notify_fault
38
+ alias notify_fault notify_fault_with_screenshot
39
+ end
@@ -0,0 +1,5 @@
1
+ module Capybara
2
+ module Screenshot
3
+ VERSION = '1.0.5'
4
+ end
5
+ end
@@ -0,0 +1,93 @@
1
+ require "spec_helper"
2
+
3
+ describe "Using Capybara::Screenshot with Cucumber" do
4
+ include CommonSetup
5
+
6
+ before do
7
+ clean_current_dir
8
+ end
9
+
10
+ let(:cmd) { 'bundle exec cucumber' }
11
+
12
+ def run_failing_case(failure_message, code)
13
+ run_case code
14
+ expect(output_from(cmd)).to match(failure_message)
15
+ end
16
+
17
+ def run_case(code, options = {})
18
+ write_file('features/support/env.rb', <<-RUBY)
19
+ #{ensure_load_paths_valid}
20
+ require 'cucumber/support/env.rb'
21
+ #{setup_test_app}
22
+ RUBY
23
+
24
+ write_file('features/step_definitions/step_definitions.rb', <<-RUBY)
25
+ %w(lib spec).each do |include_folder|
26
+ $LOAD_PATH.unshift(File.join('#{gem_root}', include_folder))
27
+ end
28
+ require 'cucumber/step_definitions/step_definitions.rb'
29
+ RUBY
30
+
31
+ write_file('features/cucumber.feature', code)
32
+
33
+ run_simple_with_retry cmd, false
34
+
35
+ expect(output_from(cmd)).to_not include('failed)') if options[:assert_all_passed]
36
+ end
37
+
38
+ it 'saves a screenshot on failure' do
39
+ run_failing_case %q{Unable to find link or button "you'll never find me"}, <<-CUCUMBER
40
+ Feature: Failure
41
+ Scenario: Failure
42
+ Given I visit "/"
43
+ And I click on a missing link
44
+ CUCUMBER
45
+ check_file_content 'tmp/my_screenshot.html', 'This is the root page', true
46
+ end
47
+
48
+ it 'saves a screenshot on an error' do
49
+ run_failing_case %q{you can't handle me}, <<-CUCUMBER
50
+ Feature: Failure
51
+ Scenario: Failure
52
+ Given I visit "/"
53
+ And I trigger an unhandled exception
54
+ CUCUMBER
55
+ check_file_content 'tmp/my_screenshot.html', 'This is the root page', true
56
+ end
57
+
58
+ it 'saves a screenshot for the correct session for failures using_session' do
59
+ run_failing_case(%q{Unable to find link or button "you'll never find me"}, <<-CUCUMBER)
60
+ Feature: Failure
61
+ Scenario: Failure in different session
62
+ Given I visit "/"
63
+ And I click on a missing link on a different page in a different session
64
+ CUCUMBER
65
+ check_file_content 'tmp/my_screenshot.html', 'This is a different page', true
66
+ end
67
+
68
+ context 'pruning' do
69
+ before do
70
+ create_screenshot_for_pruning
71
+ configure_prune_strategy :last_run
72
+ end
73
+
74
+ it 'on failure it prunes previous screenshots when strategy is set' do
75
+ run_failing_case %q{Unable to find link or button "you'll never find me"}, <<-CUCUMBER
76
+ Feature: Prune
77
+ Scenario: Screenshots are pruned if strategy is set
78
+ Given I visit "/"
79
+ And I click on a missing link
80
+ CUCUMBER
81
+ assert_screenshot_pruned
82
+ end
83
+
84
+ it 'on success it never prunes' do
85
+ run_case <<-CUCUMBER, assert_all_passed: true
86
+ Feature: Prune
87
+ Scenario: Screenshots are pruned if strategy is set
88
+ Given I visit "/"
89
+ CUCUMBER
90
+ assert_screenshot_not_pruned
91
+ end
92
+ end
93
+ end