leifcr-capybara-screenshot 1.0.14

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 (60) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +13 -0
  5. data/Appraisals +19 -0
  6. data/CHANGELOG.md +256 -0
  7. data/Gemfile +9 -0
  8. data/LICENSE +19 -0
  9. data/README.md +315 -0
  10. data/Rakefile +40 -0
  11. data/capybara-screenshot.gemspec +39 -0
  12. data/gemfiles/cucumber.1.3.gemfile +11 -0
  13. data/gemfiles/cucumber.2.4.gemfile +11 -0
  14. data/gemfiles/latest.gemfile +10 -0
  15. data/gemfiles/rspec.3.0.gemfile +11 -0
  16. data/gemfiles/spinach.0.8.gemfile +11 -0
  17. data/lib/capybara-screenshot/callbacks.rb +44 -0
  18. data/lib/capybara-screenshot/capybara.rb +26 -0
  19. data/lib/capybara-screenshot/cucumber.rb +28 -0
  20. data/lib/capybara-screenshot/helpers.rb +28 -0
  21. data/lib/capybara-screenshot/minitest.rb +36 -0
  22. data/lib/capybara-screenshot/pruner.rb +48 -0
  23. data/lib/capybara-screenshot/rspec/base_reporter.rb +21 -0
  24. data/lib/capybara-screenshot/rspec/html_embed_reporter.rb +25 -0
  25. data/lib/capybara-screenshot/rspec/html_link_reporter.rb +37 -0
  26. data/lib/capybara-screenshot/rspec/json_reporter.rb +19 -0
  27. data/lib/capybara-screenshot/rspec/text_reporter.rb +39 -0
  28. data/lib/capybara-screenshot/rspec/textmate_link_reporter.rb +19 -0
  29. data/lib/capybara-screenshot/rspec.rb +95 -0
  30. data/lib/capybara-screenshot/s3_saver.rb +64 -0
  31. data/lib/capybara-screenshot/saver.rb +131 -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/lib/capybara-screenshot.rb +217 -0
  36. data/spec/cucumber/cucumber_spec.rb +89 -0
  37. data/spec/cucumber/step_definitions/step_definitions.rb +18 -0
  38. data/spec/cucumber/support/env.rb +17 -0
  39. data/spec/feature/minitest_spec.rb +79 -0
  40. data/spec/feature/testunit_spec.rb +77 -0
  41. data/spec/rspec/rspec_spec.rb +158 -0
  42. data/spec/spec_helper.rb +34 -0
  43. data/spec/spinach/spinach_spec.rb +60 -0
  44. data/spec/spinach/support/spinach_failure.rb +41 -0
  45. data/spec/support/aruba.rb +2 -0
  46. data/spec/support/common_setup.rb +67 -0
  47. data/spec/support/html_reporter_context.rb +28 -0
  48. data/spec/support/test_app.rb +13 -0
  49. data/spec/unit/base_reporter_spec.rb +25 -0
  50. data/spec/unit/capybara-screenshot_rspec_spec.rb +48 -0
  51. data/spec/unit/capybara-screenshot_spec.rb +121 -0
  52. data/spec/unit/capybara_spec.rb +50 -0
  53. data/spec/unit/pruner_spec.rb +108 -0
  54. data/spec/unit/rspec_reporters/html_embed_reporter_spec.rb +18 -0
  55. data/spec/unit/rspec_reporters/html_link_reporter_spec.rb +27 -0
  56. data/spec/unit/rspec_reporters/text_reporter_spec.rb +98 -0
  57. data/spec/unit/rspec_reporters/textmate_link_reporter_spec.rb +39 -0
  58. data/spec/unit/s3_saver_spec.rb +132 -0
  59. data/spec/unit/saver_spec.rb +366 -0
  60. metadata +264 -0
@@ -0,0 +1,121 @@
1
+ require 'spec_helper'
2
+
3
+ describe Capybara::Screenshot do
4
+ describe '.register_driver' do
5
+ before(:all) do
6
+ @original_drivers = Capybara::Screenshot.registered_drivers.dup
7
+ end
8
+
9
+ after(:all) do
10
+ Capybara::Screenshot.registered_drivers = @original_drivers
11
+ end
12
+
13
+ it 'stores driver with block' do
14
+ block = lambda {}
15
+ Capybara::Screenshot.register_driver :foo, &block
16
+
17
+ expect(Capybara::Screenshot.registered_drivers[:foo]).to eql(block)
18
+ end
19
+ end
20
+
21
+ describe '.register_filename_prefix_formatter' do
22
+ before(:all) do
23
+ @original_formatters = Capybara::Screenshot.filename_prefix_formatters.dup
24
+ end
25
+
26
+ after(:all) do
27
+ Capybara::Screenshot.filename_prefix_formatters = @original_formatters
28
+ end
29
+
30
+ it 'stores test type with block' do
31
+ block = lambda { |arg| }
32
+ Capybara::Screenshot.register_filename_prefix_formatter :foo, &block
33
+
34
+ expect(Capybara::Screenshot.filename_prefix_formatters[:foo]).to eql(block)
35
+ end
36
+
37
+ describe '.filename_prefix_for' do
38
+ it 'returns "configured formatter" for specified formatter' do
39
+ Capybara::Screenshot.register_filename_prefix_formatter(:foo) { |arg| 'custom_path' }
40
+ expect(Capybara::Screenshot.filename_prefix_for(:foo, double('test'))).to eql('custom_path')
41
+ end
42
+ end
43
+ end
44
+
45
+ describe '.filename_prefix_for' do
46
+ it 'returns "screenshot" for undefined formatter' do
47
+ expect(Capybara::Screenshot.filename_prefix_for(:foo, double('test'))).to eql('screenshot')
48
+ end
49
+ end
50
+
51
+ describe '.append_screenshot_path' do
52
+ it 'prints a deprecation message and delegates to RSpec.add_link_to_screenshot_for_failed_examples' do
53
+ begin
54
+ original_stderr = $stderr
55
+ $stderr = StringIO.new
56
+ expect {
57
+ Capybara::Screenshot.append_screenshot_path = false
58
+ }.to change {
59
+ Capybara::Screenshot::RSpec.add_link_to_screenshot_for_failed_examples
60
+ }.from(true).to(false)
61
+ expect($stderr.string).to include("append_screenshot_path is deprecated")
62
+ ensure
63
+ $stderr = original_stderr
64
+ end
65
+ end
66
+ end
67
+
68
+ describe '.new_saver' do
69
+ it 'passes through to get a new Saver if the user has not configured s3' do
70
+ saver_double = double('saver')
71
+ args = double('args')
72
+ expect(Capybara::Screenshot::Saver).to receive(:new).with(args).and_return(saver_double)
73
+
74
+ expect(Capybara::Screenshot.new_saver(args)).to eq(saver_double)
75
+ end
76
+
77
+ it 'wraps the returned saver in an S3 saver if it has been configured' do
78
+ require 'capybara-screenshot/s3_saver'
79
+
80
+ saver_double = double('saver')
81
+ args = double('args')
82
+ s3_saver_double = double('s3_saver')
83
+ s3_configuration = { hello: 'world' }
84
+
85
+ Capybara::Screenshot.s3_configuration = s3_configuration
86
+
87
+ expect(Capybara::Screenshot::Saver).to receive(:new).with(args).and_return(saver_double)
88
+ expect(Capybara::Screenshot::S3Saver).to receive(:new_with_configuration).with(saver_double, s3_configuration).and_return(s3_saver_double)
89
+
90
+ expect(Capybara::Screenshot.new_saver(args)).to eq(s3_saver_double)
91
+ end
92
+ end
93
+
94
+ describe '#prune' do
95
+ before do
96
+ Capybara::Screenshot.reset_prune_history
97
+ end
98
+
99
+ it 'prunes once by default' do
100
+ expect(Capybara::Screenshot::Pruner).to receive(:new).and_call_original.once
101
+ 3.times { Capybara::Screenshot.prune }
102
+ end
103
+
104
+ it 'prunes every time if option force: true' do
105
+ expect(Capybara::Screenshot::Pruner).to receive(:new).and_call_original.exactly(3).times
106
+ 3.times { Capybara::Screenshot.prune(force: true) }
107
+ end
108
+
109
+ context 'prune strategy' do
110
+ let(:prune_strategy) { { keep: 100 } }
111
+ before do
112
+ Capybara::Screenshot.prune_strategy = prune_strategy
113
+ end
114
+
115
+ it 'is passed to initializer' do
116
+ expect(Capybara::Screenshot::Pruner).to receive(:new).with(prune_strategy).and_call_original
117
+ Capybara::Screenshot.prune
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,50 @@
1
+ require 'capybara-screenshot'
2
+ require 'capybara/dsl'
3
+
4
+ describe Capybara do
5
+ it 'adds screen shot methods to the Capybara module' do
6
+ expect(::Capybara).to respond_to(:screenshot_and_save_page)
7
+ expect(::Capybara).to respond_to(:screenshot_and_open_image)
8
+ end
9
+
10
+ context 'request type example', :type => :request do
11
+ it 'has access to screen shot instance methods' do
12
+ expect(subject).to respond_to(:screenshot_and_save_page)
13
+ expect(subject).to respond_to(:screenshot_and_open_image)
14
+ end
15
+ end
16
+
17
+ describe 'using_session' do
18
+ include Capybara::DSL
19
+
20
+ it 'saves the name of the final session' do
21
+ expect(Capybara::Screenshot).to receive(:final_session_name=).with(:different_session)
22
+ expect {
23
+ using_session :different_session do
24
+ expect(0).to eq 1
25
+ end
26
+ }.to raise_exception ::RSpec::Expectations::ExpectationNotMetError
27
+ end
28
+ end
29
+ end
30
+
31
+ describe 'final_session_name' do
32
+ subject { Capybara::Screenshot.clone }
33
+
34
+ describe 'when the final session name has been set' do
35
+ before do
36
+ subject.final_session_name = 'my-failing-session'
37
+ end
38
+
39
+ it 'returns the name' do
40
+ expect(subject.final_session_name).to eq 'my-failing-session'
41
+ end
42
+ end
43
+
44
+ describe 'when the final session name has not been set' do
45
+ it 'returns the current session name' do
46
+ allow(Capybara).to receive(:session_name).and_return('my-current-session')
47
+ expect(subject.final_session_name).to eq 'my-current-session'
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,108 @@
1
+ require 'spec_helper'
2
+
3
+ describe Capybara::Screenshot::Pruner do
4
+ describe '#initialize' do
5
+ let(:pruner) { Capybara::Screenshot::Pruner.new(strategy) }
6
+
7
+ context 'accepts generic strategies:' do
8
+ [:keep_all, :keep_last_run].each do |strategy_sym|
9
+ let(:strategy) { strategy_sym }
10
+
11
+ it ":#{strategy_sym}" do
12
+ expect(pruner.strategy).to eq(strategy)
13
+ end
14
+ end
15
+ end
16
+
17
+ context 'keep:int' do
18
+ let(:strategy) { { keep: 50 } }
19
+
20
+ it 'is a suitable strategy' do
21
+ expect(pruner.strategy).to eq(strategy)
22
+ end
23
+ end
24
+
25
+ context 'invalid strategy' do
26
+ context 'symbol' do
27
+ let(:strategy) { :invalid_strategy }
28
+
29
+ it 'raises an error' do
30
+ expect { pruner }.to raise_error(/Invalid prune strategy/)
31
+ end
32
+ end
33
+
34
+ context 'keep:sym' do
35
+ let(:strategy) { { keep: :symbol } }
36
+
37
+ it 'raises an error' do
38
+ expect { pruner }.to raise_error(/must be a Integer/)
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ describe '#prune_old_screenshots' do
45
+ let(:capybara_root) { Capybara::Screenshot.capybara_root }
46
+ let(:remaining_files) { Dir.glob(File.expand_path('*', capybara_root)).sort }
47
+ let(:files_created) { [] }
48
+ let(:files_count) { 8 }
49
+ let(:pruner) { Capybara::Screenshot::Pruner.new(strategy) }
50
+
51
+ before do
52
+ allow(Capybara::Screenshot).to receive(:capybara_root).and_return(Dir.mktmpdir.to_s)
53
+
54
+ files_count.times do |i|
55
+ files_created << FileUtils.touch("#{capybara_root}/#{i}.#{i % 2 == 0 ? 'png' : 'html'}").first.tap do |file_name|
56
+ File.utime(Time.now, Time.now - files_count + i, file_name)
57
+ end
58
+ end
59
+
60
+ pruner.prune_old_screenshots
61
+ end
62
+
63
+ after do
64
+ FileUtils.rm_rf capybara_root
65
+ end
66
+
67
+ context 'with :keep_all strategy' do
68
+ let(:strategy) { :keep_all }
69
+
70
+ it 'should not remove screens' do
71
+ expect(remaining_files).to eq(files_created)
72
+ end
73
+ end
74
+
75
+ context 'with :keep_last_run strategy' do
76
+ let(:strategy) { :keep_last_run }
77
+
78
+ it 'should remove all screens' do
79
+ expect(remaining_files).to be_empty
80
+ end
81
+
82
+ context 'when dir is missing' do
83
+ before { FileUtils.rm_rf(Capybara::Screenshot.capybara_root) }
84
+
85
+ it 'should not raise error' do
86
+ expect { pruner.prune_old_screenshots }.to_not raise_error
87
+ end
88
+ end
89
+ end
90
+
91
+ context 'with :keep strategy' do
92
+ let(:keep_count) { 3 }
93
+ let(:strategy) { { keep: keep_count } }
94
+
95
+ it 'should keep specified number of screens' do
96
+ expect(remaining_files).to eq(files_created.last(keep_count))
97
+ end
98
+
99
+ context 'when dir is missing' do
100
+ before { FileUtils.rm_rf(Capybara::Screenshot.capybara_root) }
101
+
102
+ it 'should not raise error when dir is missing' do
103
+ expect { pruner.prune_old_screenshots }.to_not raise_error
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe Capybara::Screenshot::RSpec::HtmlEmbedReporter do
4
+ include_context 'html reporter'
5
+
6
+ context 'when an image was saved' do
7
+ before do
8
+ set_example double("example", metadata: {screenshot: {image: "path/to/image"}})
9
+ end
10
+
11
+ it 'embeds the image base64 encoded into the content' do
12
+ expect(File).to receive(:binread).with("path/to/image").and_return("image data")
13
+ encoded_image_data = Base64.encode64('image data')
14
+ content_without_styles = @reporter.extra_failure_content(nil).gsub(/ ?style='.*?' ?/, "")
15
+ expect(content_without_styles).to eql("original content<img src='data:image/png;base64,#{encoded_image_data}'>")
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ describe Capybara::Screenshot::RSpec::HtmlLinkReporter do
4
+ include_context 'html reporter'
5
+
6
+ context 'when a html file was saved' do
7
+ before do
8
+ set_example double("example", metadata: {screenshot: {html: "path/to/a html file"}})
9
+ end
10
+
11
+ it 'appends a link to the html to the original content' do
12
+ content_without_styles = @reporter.extra_failure_content(nil).gsub(/ ?style=".*?" ?/, "")
13
+ expect(content_without_styles).to eql(%{original content<p>Saved files: <a href="file://path/to/a%20html%20file">HTML page</a></p>})
14
+ end
15
+ end
16
+
17
+ context 'when a html file and an image were saved' do
18
+ before do
19
+ set_example double("example", metadata: {screenshot: {html: "path/to/html", image: "path/to/an image"}})
20
+ end
21
+
22
+ it 'appends links to both files to the original content' do
23
+ content_without_styles = @reporter.extra_failure_content(nil).gsub(/ ?style=".*?" ?/, "")
24
+ expect(content_without_styles).to eql(%{original content<p>Saved files: <a href="file://path/to/html">HTML page</a><a href="file://path/to/an%20image">Screenshot</a></p>})
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,98 @@
1
+ require 'spec_helper'
2
+ require 'capybara-screenshot/helpers'
3
+
4
+ describe Capybara::Screenshot::RSpec::TextReporter do
5
+ before do
6
+ # Mocking `RSpec::Core::Formatters::ProgressFormatter`, but only implementing the methods that
7
+ # are actually used in `TextReporter#dump_failure_info_with_screenshot`.
8
+ @reporter_class = Class.new do
9
+ attr_reader :output
10
+
11
+ def initialize
12
+ @output = StringIO.new
13
+ end
14
+
15
+ protected
16
+
17
+ def long_padding
18
+ " "
19
+ end
20
+
21
+ def failure_color(str)
22
+ "colorized(#{str})"
23
+ end
24
+
25
+ private
26
+
27
+ def dump_failure_info(example)
28
+ output.puts "original failure info"
29
+ end
30
+ alias_method :example_failed, :dump_failure_info
31
+ end
32
+
33
+ @reporter = @reporter_class.new
34
+ @reporter.singleton_class.send :include, described_class
35
+ end
36
+
37
+ let(:example_failed_method) do
38
+ if ::RSpec::Core::Version::STRING.to_i <= 2
39
+ :dump_failure_info
40
+ else
41
+ :example_failed
42
+ end
43
+ end
44
+
45
+ def example_failed_method_argument_double(metadata = {})
46
+ example_group = Module.new.send(:include, Capybara::DSL)
47
+ example = double("example", metadata: metadata, example_group: example_group)
48
+ if ::RSpec::Core::Version::STRING.to_i <= 2
49
+ example
50
+ else
51
+ double("notification").tap do |notification|
52
+ allow(notification).to receive(:example).and_return(example)
53
+ end
54
+ end
55
+ end
56
+
57
+ context 'when there is no screenshot' do
58
+ let(:example) { example_failed_method_argument_double }
59
+
60
+ it 'doesnt change the original output of the reporter' do
61
+ @reporter.send(example_failed_method, example)
62
+ expect(@reporter.output.string).to eql("original failure info\n")
63
+ end
64
+ end
65
+
66
+ context 'when a html file was saved' do
67
+ let(:example) { example_failed_method_argument_double(screenshot: { html: "path/to/html" }) }
68
+
69
+ it 'appends the html file path to the original output' do
70
+ @reporter.send(example_failed_method, example)
71
+ expect(@reporter.output.string).to eql("original failure info\n #{CapybaraScreenshot::Helpers.yellow("HTML screenshot: file://path/to/html")}\n")
72
+ end
73
+ end
74
+
75
+ context 'when a html file and an image were saved' do
76
+ let(:example) { example_failed_method_argument_double(screenshot: { html: "path/to/html", image: "path/to/image" }) }
77
+
78
+ it 'appends the image path to the original output' do
79
+ @reporter.send(example_failed_method, example)
80
+ expect(@reporter.output.string).to eql("original failure info\n #{CapybaraScreenshot::Helpers.yellow("HTML screenshot: file://path/to/html")}\n #{CapybaraScreenshot::Helpers.yellow("Image screenshot: file://path/to/image")}\n")
81
+ end
82
+ end
83
+
84
+
85
+ it 'works with older RSpec formatters where `#red` is used instead of `#failure_color`' do
86
+ old_reporter_class = Class.new(@reporter_class) do
87
+ undef_method :failure_color
88
+ def red(str)
89
+ "red(#{str})"
90
+ end
91
+ end
92
+ old_reporter = old_reporter_class.new
93
+ old_reporter.singleton_class.send :include, described_class
94
+ example = example_failed_method_argument_double(screenshot: { html: "path/to/html" })
95
+ old_reporter.send(example_failed_method, example)
96
+ expect(old_reporter.output.string).to eql("original failure info\n #{CapybaraScreenshot::Helpers.yellow("HTML screenshot: file://path/to/html")}\n")
97
+ end
98
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ describe Capybara::Screenshot::RSpec::TextMateLinkReporter do
4
+ include_context 'html reporter'
5
+
6
+ context 'when a html file was saved' do
7
+ before do
8
+ set_example double("example", metadata: {screenshot: {html: "path/to/a html file"}})
9
+ end
10
+
11
+ it 'appends a link to the html to the original content' do
12
+ content_without_styles = @reporter.extra_failure_content(nil).gsub(/ ?style=".*?"/, "")
13
+ # Single quotes are handled differently by CGI.escape_html in Ruby 1.9 / Ruby 2, so to be
14
+ # compatible with both versions we can't hard code the final escaped string.
15
+ expected_onclick_handler = CGI.escape_html("TextMate.system('open file://path/to/a\\%20html\\%20file'); return false;")
16
+ expect(content_without_styles).to eql(%{original content<p>} +
17
+ %{Saved files: <a href="file://path/to/a%20html%20file" onclick="#{expected_onclick_handler}">HTML page</a></p>}
18
+ )
19
+ end
20
+ end
21
+
22
+ context 'when a html file and an image were saved' do
23
+ before do
24
+ set_example double("example", metadata: {screenshot: {html: "path/to/html", image: "path/to/an image"}})
25
+ end
26
+
27
+ it 'appends links to both files to the original content' do
28
+ content_without_styles = @reporter.extra_failure_content(nil).gsub(/ ?style=".*?"/, "")
29
+ # Single quotes are handled differently by CGI.escape_html in Ruby 1.9 / Ruby 2, so to be
30
+ # compatible with both versions we can't hard code the final escaped string.
31
+ expected_onclick_handler_1 = CGI.escape_html("TextMate.system('open file://path/to/html'); return false;")
32
+ expected_onclick_handler_2 = CGI.escape_html("TextMate.system('open file://path/to/an\\%20image'); return false;")
33
+ expect(content_without_styles).to eql(%{original content<p>} +
34
+ %{Saved files: <a href="file://path/to/html" onclick="#{expected_onclick_handler_1}">HTML page</a>} +
35
+ %{<a href="file://path/to/an%20image" onclick="#{expected_onclick_handler_2}">Screenshot</a></p>}
36
+ )
37
+ end
38
+ end
39
+ end