capybara-screenshot-nocolor 1.0.5

Sign up to get free protection for your applications and to get access to all the features.
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