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.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +13 -0
- data/Appraisals +19 -0
- data/CHANGELOG.md +256 -0
- data/Gemfile +9 -0
- data/LICENSE +19 -0
- data/README.md +315 -0
- data/Rakefile +40 -0
- data/capybara-screenshot.gemspec +39 -0
- data/gemfiles/cucumber.1.3.gemfile +11 -0
- data/gemfiles/cucumber.2.4.gemfile +11 -0
- data/gemfiles/latest.gemfile +10 -0
- data/gemfiles/rspec.3.0.gemfile +11 -0
- data/gemfiles/spinach.0.8.gemfile +11 -0
- data/lib/capybara-screenshot/callbacks.rb +44 -0
- data/lib/capybara-screenshot/capybara.rb +26 -0
- data/lib/capybara-screenshot/cucumber.rb +28 -0
- data/lib/capybara-screenshot/helpers.rb +28 -0
- data/lib/capybara-screenshot/minitest.rb +36 -0
- data/lib/capybara-screenshot/pruner.rb +48 -0
- data/lib/capybara-screenshot/rspec/base_reporter.rb +21 -0
- data/lib/capybara-screenshot/rspec/html_embed_reporter.rb +25 -0
- data/lib/capybara-screenshot/rspec/html_link_reporter.rb +37 -0
- data/lib/capybara-screenshot/rspec/json_reporter.rb +19 -0
- data/lib/capybara-screenshot/rspec/text_reporter.rb +39 -0
- data/lib/capybara-screenshot/rspec/textmate_link_reporter.rb +19 -0
- data/lib/capybara-screenshot/rspec.rb +95 -0
- data/lib/capybara-screenshot/s3_saver.rb +64 -0
- data/lib/capybara-screenshot/saver.rb +131 -0
- data/lib/capybara-screenshot/spinach.rb +26 -0
- data/lib/capybara-screenshot/testunit.rb +39 -0
- data/lib/capybara-screenshot/version.rb +5 -0
- data/lib/capybara-screenshot.rb +217 -0
- data/spec/cucumber/cucumber_spec.rb +89 -0
- data/spec/cucumber/step_definitions/step_definitions.rb +18 -0
- data/spec/cucumber/support/env.rb +17 -0
- data/spec/feature/minitest_spec.rb +79 -0
- data/spec/feature/testunit_spec.rb +77 -0
- data/spec/rspec/rspec_spec.rb +158 -0
- data/spec/spec_helper.rb +34 -0
- data/spec/spinach/spinach_spec.rb +60 -0
- data/spec/spinach/support/spinach_failure.rb +41 -0
- data/spec/support/aruba.rb +2 -0
- data/spec/support/common_setup.rb +67 -0
- data/spec/support/html_reporter_context.rb +28 -0
- data/spec/support/test_app.rb +13 -0
- data/spec/unit/base_reporter_spec.rb +25 -0
- data/spec/unit/capybara-screenshot_rspec_spec.rb +48 -0
- data/spec/unit/capybara-screenshot_spec.rb +121 -0
- data/spec/unit/capybara_spec.rb +50 -0
- data/spec/unit/pruner_spec.rb +108 -0
- data/spec/unit/rspec_reporters/html_embed_reporter_spec.rb +18 -0
- data/spec/unit/rspec_reporters/html_link_reporter_spec.rb +27 -0
- data/spec/unit/rspec_reporters/text_reporter_spec.rb +98 -0
- data/spec/unit/rspec_reporters/textmate_link_reporter_spec.rb +39 -0
- data/spec/unit/s3_saver_spec.rb +132 -0
- data/spec/unit/saver_spec.rb +366 -0
- metadata +264 -0
data/Rakefile
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
|
4
|
+
Bundler::GemHelper.install_tasks
|
5
|
+
|
6
|
+
require 'rspec/core/rake_task'
|
7
|
+
|
8
|
+
rspec_rake_task = RSpec::Core::RakeTask.new(:spec)
|
9
|
+
|
10
|
+
task default: [:spec]
|
11
|
+
|
12
|
+
def target_gem
|
13
|
+
gem_file = ENV['BUNDLE_GEMFILE'] || ''
|
14
|
+
targets = %w(cucumber spinach rspec)
|
15
|
+
|
16
|
+
target = gem_file.match(/(#{targets.join('|')})/)
|
17
|
+
if target && targets.include?(target[1])
|
18
|
+
target[1].to_sym
|
19
|
+
else
|
20
|
+
[]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
namespace :travis do
|
25
|
+
task :ci => target_gem do
|
26
|
+
Rake::Task['spec'].invoke
|
27
|
+
end
|
28
|
+
|
29
|
+
task :cucumber do
|
30
|
+
rspec_rake_task.pattern = 'spec/cucumber'
|
31
|
+
end
|
32
|
+
|
33
|
+
task :spinach do
|
34
|
+
rspec_rake_task.pattern = 'spec/spinach'
|
35
|
+
end
|
36
|
+
|
37
|
+
task :rspec do
|
38
|
+
rspec_rake_task.pattern = 'spec/rspec'
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "capybara-screenshot/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "leifcr-capybara-screenshot"
|
7
|
+
s.version = Capybara::Screenshot::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Matthew O'Riordan"]
|
10
|
+
s.email = ["matthew.oriordan@gmail.com"]
|
11
|
+
s.homepage = "http://github.com/mattheworiordan/capybara-screenshot"
|
12
|
+
s.summary = %q{Automatically create snapshots when Cucumber steps fail with Capybara and Rails}
|
13
|
+
s.description = %q{When a Cucumber step fails, it is useful to create a screenshot image and HTML file of the current page}
|
14
|
+
s.license = 'MIT'
|
15
|
+
|
16
|
+
s.rubyforge_project = "capybara-screenshot"
|
17
|
+
|
18
|
+
if RUBY_VERSION < "1.9"
|
19
|
+
s.add_dependency 'capybara', ['>= 1.0', '< 2']
|
20
|
+
else
|
21
|
+
s.add_dependency 'capybara', ['>= 1.0', '< 3']
|
22
|
+
end
|
23
|
+
s.add_dependency 'launchy'
|
24
|
+
|
25
|
+
s.add_development_dependency 'rspec'
|
26
|
+
s.add_development_dependency 'timecop'
|
27
|
+
s.add_development_dependency 'cucumber'
|
28
|
+
s.add_development_dependency 'aruba'
|
29
|
+
s.add_development_dependency 'sinatra'
|
30
|
+
s.add_development_dependency 'test-unit'
|
31
|
+
s.add_development_dependency 'spinach'
|
32
|
+
s.add_development_dependency 'minitest'
|
33
|
+
s.add_development_dependency 'aws-sdk'
|
34
|
+
|
35
|
+
s.files = `git ls-files`.split("\n")
|
36
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
37
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
38
|
+
s.require_paths = ["lib"]
|
39
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Capybara
|
2
|
+
module Screenshot
|
3
|
+
module Callbacks
|
4
|
+
class CallbackSet < Array
|
5
|
+
def call *args
|
6
|
+
each do |callback|
|
7
|
+
callback.call *args
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
def callbacks
|
14
|
+
@callbacks ||= {}
|
15
|
+
end
|
16
|
+
|
17
|
+
def define_callback name
|
18
|
+
callbacks[name] ||= CallbackSet.new
|
19
|
+
|
20
|
+
define_singleton_method name do |&block|
|
21
|
+
callbacks[name] << block
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def run_callbacks name, *args
|
26
|
+
if cb_set = callbacks[name]
|
27
|
+
cb_set.call *args
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
module InstanceMethods
|
33
|
+
def run_callbacks name, *args
|
34
|
+
self.class.run_callbacks name, *args
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.included receiver
|
39
|
+
receiver.extend ClassMethods
|
40
|
+
receiver.send :include, InstanceMethods
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "capybara-screenshot"
|
2
|
+
|
3
|
+
module Capybara
|
4
|
+
module DSL
|
5
|
+
# Adds class methods to Capybara module and gets mixed into
|
6
|
+
# the current scope during Cucumber and RSpec tests
|
7
|
+
|
8
|
+
def screenshot_and_save_page
|
9
|
+
Capybara::Screenshot.screenshot_and_save_page
|
10
|
+
end
|
11
|
+
|
12
|
+
def screenshot_and_open_image
|
13
|
+
Capybara::Screenshot.screenshot_and_open_image
|
14
|
+
end
|
15
|
+
|
16
|
+
def using_session_with_screenshot(name,&blk)
|
17
|
+
original_session_name = Capybara.session_name
|
18
|
+
Capybara::Screenshot.final_session_name = name
|
19
|
+
using_session_without_screenshot(name,&blk)
|
20
|
+
Capybara::Screenshot.final_session_name = original_session_name
|
21
|
+
end
|
22
|
+
|
23
|
+
alias_method :using_session_without_screenshot, :using_session
|
24
|
+
alias_method :using_session, :using_session_with_screenshot
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require "capybara-screenshot"
|
2
|
+
|
3
|
+
Before do |scenario|
|
4
|
+
Capybara::Screenshot.final_session_name = nil
|
5
|
+
end
|
6
|
+
|
7
|
+
After do |scenario|
|
8
|
+
if Capybara::Screenshot.autosave_on_failure && scenario.failed?
|
9
|
+
Capybara.using_session(Capybara::Screenshot.final_session_name) do
|
10
|
+
filename_prefix = Capybara::Screenshot.filename_prefix_for(:cucumber, scenario)
|
11
|
+
|
12
|
+
saver = Capybara::Screenshot.new_saver(Capybara, Capybara.page, true, filename_prefix)
|
13
|
+
saver.save
|
14
|
+
saver.output_screenshot_path
|
15
|
+
|
16
|
+
# Trying to embed the screenshot into our output."
|
17
|
+
if File.exist?(saver.screenshot_path)
|
18
|
+
require "base64"
|
19
|
+
#encode the image into it's base64 representation
|
20
|
+
image = open(saver.screenshot_path, 'rb') {|io|io.read}
|
21
|
+
saver.display_image
|
22
|
+
#this will embed the image in the HTML report, embed() is defined in cucumber
|
23
|
+
encoded_img = Base64.encode64(image)
|
24
|
+
embed(encoded_img, 'image/png;base64', "Screenshot of the error")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class CapybaraScreenshot
|
2
|
+
module Helpers
|
3
|
+
extend self
|
4
|
+
|
5
|
+
COLORS =
|
6
|
+
{
|
7
|
+
"black" => 0,
|
8
|
+
"red" => 1,
|
9
|
+
"green" => 2,
|
10
|
+
"yellow" => 3,
|
11
|
+
"blue" => 4,
|
12
|
+
"purple" => 5,
|
13
|
+
"magenta" => 5,
|
14
|
+
"cyan" => 6,
|
15
|
+
"white" => 7
|
16
|
+
}
|
17
|
+
|
18
|
+
COLORS.each_pair do |color, value|
|
19
|
+
define_method color do |text|
|
20
|
+
"\033[0;#{30+value}m#{text}\033[0m"
|
21
|
+
end
|
22
|
+
|
23
|
+
define_method "bright_#{color}" do |text|
|
24
|
+
"\033[1;#{30+value}m#{text}\033[0m"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require "capybara-screenshot"
|
2
|
+
|
3
|
+
module Capybara::Screenshot::MiniTestPlugin
|
4
|
+
def before_setup
|
5
|
+
super
|
6
|
+
Capybara::Screenshot.final_session_name = nil
|
7
|
+
end
|
8
|
+
|
9
|
+
def before_teardown
|
10
|
+
super
|
11
|
+
if self.class.ancestors.map(&:to_s).include?('Capybara::DSL')
|
12
|
+
if Capybara::Screenshot.autosave_on_failure && !passed? && !skipped?
|
13
|
+
Capybara.using_session(Capybara::Screenshot.final_session_name) do
|
14
|
+
filename_prefix = Capybara::Screenshot.filename_prefix_for(:minitest, self)
|
15
|
+
|
16
|
+
saver = Capybara::Screenshot.new_saver(Capybara, Capybara.page, true, filename_prefix)
|
17
|
+
saver.save
|
18
|
+
saver.output_screenshot_path
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
begin
|
26
|
+
Minitest.const_get('Test')
|
27
|
+
class Minitest::Test
|
28
|
+
include Capybara::Screenshot::MiniTestPlugin
|
29
|
+
end
|
30
|
+
rescue NameError => e
|
31
|
+
class MiniTest::Unit::TestCase
|
32
|
+
include Capybara::Screenshot::MiniTestPlugin
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Capybara
|
2
|
+
module Screenshot
|
3
|
+
class Pruner
|
4
|
+
attr_reader :strategy
|
5
|
+
|
6
|
+
def initialize(strategy)
|
7
|
+
@strategy = strategy
|
8
|
+
|
9
|
+
@strategy_proc = case strategy
|
10
|
+
when :keep_all
|
11
|
+
lambda { }
|
12
|
+
when :keep_last_run
|
13
|
+
lambda { prune_with_last_run_strategy }
|
14
|
+
when Hash
|
15
|
+
raise ArgumentError, ":keep key is required" unless strategy[:keep]
|
16
|
+
raise ArgumentError, ":keep must be a Integer" unless strategy[:keep].kind_of?(Integer)
|
17
|
+
raise ArgumentError, ":keep value must be number greater than zero" unless strategy[:keep].to_i > 0
|
18
|
+
lambda { prune_with_numeric_strategy(strategy[:keep].to_i) }
|
19
|
+
else
|
20
|
+
fail "Invalid prune strategy #{strategy}. `:keep_all`or `{ keep: 10 }` are valid examples."
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def prune_old_screenshots
|
25
|
+
strategy_proc.call
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
attr_reader :strategy_proc
|
30
|
+
|
31
|
+
def wildcard_path
|
32
|
+
File.expand_path('*.{html,png}', Screenshot.capybara_root)
|
33
|
+
end
|
34
|
+
|
35
|
+
def prune_with_last_run_strategy
|
36
|
+
FileUtils.rm_rf(Dir.glob(wildcard_path))
|
37
|
+
end
|
38
|
+
|
39
|
+
def prune_with_numeric_strategy(count)
|
40
|
+
files = Dir.glob(wildcard_path).sort_by do |file_name|
|
41
|
+
File.mtime(File.expand_path(file_name, Screenshot.capybara_root))
|
42
|
+
end
|
43
|
+
|
44
|
+
FileUtils.rm_rf(files[0...-count])
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
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
|