├── .gitignore ├── LICENSE.md ├── README.md ├── Rakefile ├── capybara-inline-screenshot.gemspec ├── lib ├── capybara-inline-screenshot.rb └── capybara-inline-screenshot │ ├── cucumber.rb │ ├── minitest.rb │ └── rspec.rb └── screenshots ├── buildkite.png └── iterm.png /.gitignore: -------------------------------------------------------------------------------- 1 | pkg/ -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 Buildkite Pty Ltd 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # capybara-inline-screenshot 2 | 3 | Extends [capybara-screenshot](https://github.com/mattheworiordan/capybara-screenshot) with inline image output. 4 | 5 | In [iTerm3 (beta)](https://www.iterm2.com/version3.html): 6 | 7 | ![Screenshot of iTerm2](screenshots/iterm.png) 8 | 9 | In [Buildkite](https://buildkite.com/): 10 | 11 | ![Screenshot of Buildkite](screenshots/buildkite.png) 12 | 13 | ## Usage 14 | 15 | In your Gemfile simply replace `capybara-screenshot` with `capybara-inline-screenshot`: 16 | 17 | ```ruby 18 | gem 'capybara-inline-screenshot' 19 | ``` 20 | 21 | ### RSpec 22 | 23 | For RSpec update your capabara-screenshot `require` statement from: 24 | 25 | ```ruby 26 | require 'capybara-screenshot/rspec' 27 | ``` 28 | 29 | to: 30 | 31 | ```ruby 32 | require 'capybara-inline-screenshot/rspec' 33 | ``` 34 | 35 | ### MiniTest 36 | 37 | For MiniTest update your capabara-screenshot `require` statement from: 38 | 39 | ```ruby 40 | require 'capybara-screenshot/rspec' 41 | ``` 42 | 43 | to: 44 | 45 | ```ruby 46 | require 'capybara-inline-screenshot/minitest' 47 | ``` 48 | 49 | and then include it in your tests as you need: 50 | 51 | ```ruby 52 | class SystemTest < Minitest::Test 53 | include CapybaraInlineScreenshot::Minitest 54 | end 55 | ``` 56 | 57 | ### Cucumber 58 | 59 | For Cucumber update your capabara-screenshot `require` statement from: 60 | 61 | ```ruby 62 | require 'capybara-screenshot/cucumber' 63 | ``` 64 | 65 | to: 66 | 67 | ```ruby 68 | require 'capybara-inline-screenshot/cucumber' 69 | ``` 70 | 71 | ### Artifact uploads 72 | 73 | The final step is to configure your build steps to upload the screenshot artifacts. The default path is your app’s `tmp` directory, so the artifact upload pattern would be `tmp/*.png` 74 | 75 | ## Fallback 76 | 77 | Thanks the wonder of ANSI escape codes if your terminal client doesn't understand the escape codes it'll simply ignore them—it'll just be be like using the standard capybara-screenshot gem. 78 | 79 | ## CI-mode 80 | 81 | If the `CI` environment variable is present screenshots will be output in the [Terminal artifact:// format](http://buildkite.github.io/terminal/inline-images/) with the expectation that the images are uploaded as build artifacts and inlined by your CI system. You can also force this mode by setting the environment variable `CAPYBARA_INLINE_SCREENSHOT=artifact`. 82 | 83 | If the `CI` environment variable is not present screenshots will be output in the base64 encoded [iTerm2 image format](http://iterm2.com/images.html) for viewing in a local terminal. You'll need the nightly release of iTerm to see the images. 84 | 85 | ## License 86 | 87 | See the [LICENSE](LICENSE.md) file for license rights and limitations (MIT). 88 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler' 2 | 3 | Bundler::GemHelper.install_tasks 4 | -------------------------------------------------------------------------------- /capybara-inline-screenshot.gemspec: -------------------------------------------------------------------------------- 1 | Gem::Specification.new do |gem| 2 | gem.name = "capybara-inline-screenshot" 3 | gem.version = "2.2.0" 4 | gem.author = "Tim Lucas" 5 | gem.email = "t@toolmantim.com" 6 | gem.homepage = "http://github.com/buildkite/capybara-inline-screenshot" 7 | gem.summary = "Extends capybara-screenshot with inline image output" 8 | gem.description = gem.summary 9 | gem.license = "MIT" 10 | 11 | gem.files = %x{ git ls-files }.split("\n").select { |d| d =~ %r{^(LICENSE.md|README.md|lib/)} } 12 | gem.require_paths = ["lib"] 13 | 14 | gem.add_dependency 'capybara-screenshot' 15 | end 16 | -------------------------------------------------------------------------------- /lib/capybara-inline-screenshot.rb: -------------------------------------------------------------------------------- 1 | require 'base64' 2 | require 'capybara-screenshot' 3 | 4 | module CapybaraInlineScreenshot 5 | # Sets the default base directory for artifacts (usually the root dir of the 6 | # project). Defaults to Rails.root but can be set to another value if you're 7 | # not using Rails. 8 | def self.base_artifact_dir=(path) 9 | @base_artifact_dir = path 10 | end 11 | 12 | def self.base_artifact_dir 13 | @base_artifact_dir || (Rails.root if defined? Rails) 14 | end 15 | 16 | def self.escape_code_for_image(path) 17 | if ENV['CI'] || ENV['CAPYBARA_INLINE_SCREENSHOT'] == 'artifact' 18 | artifact_escape_code_for_image(path) 19 | else 20 | base64_escape_code_for_image(path) 21 | end 22 | end 23 | 24 | def self.artifact_escape_code_for_image(path) 25 | relative_path = path.sub(/\A#{base_artifact_dir}\/?/, '') 26 | "\e]1338;url=artifact://#{relative_path}\a" 27 | end 28 | 29 | def self.base64_escape_code_for_image(path) 30 | name = inline_base64(File.basename(path)) 31 | image = inline_base64(File.read(path)) 32 | "\e]1337;File=name=#{name};inline=1:#{image}\a" 33 | end 34 | 35 | def self.inline_base64(string) 36 | Base64.encode64(string).gsub("\n",'') 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /lib/capybara-inline-screenshot/cucumber.rb: -------------------------------------------------------------------------------- 1 | require 'capybara-inline-screenshot' 2 | require 'capybara-screenshot' 3 | 4 | Before do |scenario| 5 | Capybara::Screenshot.final_session_name = nil 6 | end 7 | 8 | After do |scenario| 9 | if Capybara::Screenshot.autosave_on_failure && scenario.failed? 10 | Capybara.using_session(Capybara::Screenshot.final_session_name) do 11 | filename_prefix = Capybara::Screenshot.filename_prefix_for(:cucumber, scenario) 12 | 13 | saver = Capybara::Screenshot::Saver.new(Capybara, Capybara.page, true, filename_prefix) 14 | saver.save 15 | saver.output_screenshot_path 16 | 17 | if File.exist?(saver.screenshot_path) 18 | encoded_img = CapybaraInlineScreenshot.inline_base64(File.read(saver.screenshot_path)) 19 | method = respond_to?(:attach) ? :attach : :embed 20 | send(method, encoded_img, 'image/png;base64') 21 | 22 | STDOUT.puts CapybaraInlineScreenshot.escape_code_for_image(saver.screenshot_path) 23 | end 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /lib/capybara-inline-screenshot/minitest.rb: -------------------------------------------------------------------------------- 1 | require 'capybara-inline-screenshot' 2 | 3 | module CapybaraInlineScreenshot::Minitest 4 | def before_setup 5 | super 6 | Capybara::Screenshot.final_session_name = nil 7 | end 8 | 9 | def before_teardown 10 | super 11 | 12 | if Capybara::Screenshot.autosave_on_failure && !passed? 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::Saver.new(Capybara, Capybara.page, true, filename_prefix) 17 | saver.save 18 | saver.output_screenshot_path 19 | 20 | if File.exist?(saver.screenshot_path) 21 | puts CapybaraInlineScreenshot.escape_code_for_image(saver.screenshot_path) 22 | end 23 | end 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /lib/capybara-inline-screenshot/rspec.rb: -------------------------------------------------------------------------------- 1 | require 'capybara-inline-screenshot' 2 | require 'capybara-screenshot' 3 | require 'capybara-screenshot/rspec' 4 | 5 | module CapybaraInlineScreenshot::Rspec 6 | extend Capybara::Screenshot::RSpec::BaseReporter 7 | 8 | enhance_with_screenshot :example_failed 9 | 10 | def example_failed_with_screenshot(notification) 11 | example_failed_without_screenshot(notification) 12 | 13 | if screenshot = notification.example.metadata[:screenshot] 14 | output.puts CapybaraScreenshot::Helpers.yellow("HTML screenshot: file://#{screenshot[:html]}") if screenshot[:html] 15 | output.puts CapybaraScreenshot::Helpers.yellow("Image screenshot: file://#{screenshot[:image]}") if screenshot[:image] 16 | output.puts CapybaraInlineScreenshot.escape_code_for_image(screenshot[:image]) if screenshot[:image] 17 | end 18 | end 19 | end 20 | 21 | Capybara::Screenshot::RSpec::REPORTERS["RSpec::Core::Formatters::ProgressFormatter"] = CapybaraInlineScreenshot::Rspec 22 | Capybara::Screenshot::RSpec::REPORTERS["RSpec::Core::Formatters::DocumentationFormatter"] = CapybaraInlineScreenshot::Rspec 23 | -------------------------------------------------------------------------------- /screenshots/buildkite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buildkite/capybara-inline-screenshot/749982922beb6fc0d62294e1c7106f262b92bffa/screenshots/buildkite.png -------------------------------------------------------------------------------- /screenshots/iterm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buildkite/capybara-inline-screenshot/749982922beb6fc0d62294e1c7106f262b92bffa/screenshots/iterm.png --------------------------------------------------------------------------------