# Make the code below work with cucumber >= 2.0. Once we stop # supporting <2.0 we should probably do this differently, but this way # we can easily support both at the same time. begin if not(Cucumber::Core::Ast::Feature.instance_methods.include?(:accept_hook?)) require 'gherkin/tag_expression' class Cucumber::Core::Ast::Feature # Code inspired by Cucumber::Core::Test::Case.match_tags?() in # cucumber-ruby-core 1.1.3, lib/cucumber/core/test/case.rb:~59. def accept_hook?(hook) tag_expr = Gherkin::TagExpression.new(hook.tag_expressions.flatten) tags = @tags.map do |t| Gherkin::Formatter::Model::Tag.new(t.name, t.line) end tag_expr.evaluate(tags) end end end rescue NameError => e raise e if e.to_s != "uninitialized constant Cucumber::Core" end # Sort of inspired by Cucumber::RbSupport::RbHook (from cucumber # < 2.0) but really we just want an object with a 'tag_expressions' # attribute to make accept_hook?() (used below) happy. class SimpleHook attr_reader :tag_expressions def initialize(tag_expressions, proc) @tag_expressions = tag_expressions @proc = proc end def invoke(arg) @proc.call(arg) end end def BeforeFeature(*tag_expressions, &block) $before_feature_hooks ||= [] $before_feature_hooks << SimpleHook.new(tag_expressions, block) end def AfterFeature(*tag_expressions, &block) $after_feature_hooks ||= [] $after_feature_hooks << SimpleHook.new(tag_expressions, block) end require 'cucumber/formatter/console' if not($at_exit_print_artifacts_dir_patching_done) module Cucumber::Formatter::Console if method_defined?(:print_stats) alias old_print_stats print_stats end def print_stats(*args) if Dir.exists?(ARTIFACTS_DIR) and Dir.entries(ARTIFACTS_DIR).size > 2 @io.puts "Artifacts directory: #{ARTIFACTS_DIR}" @io.puts end if self.class.method_defined?(:old_print_stats) old_print_stats(*args) end end end $at_exit_print_artifacts_dir_patching_done = true end def info_log(message = "", options = {}) options[:color] = :clear # This trick allows us to use a module's (~private) method on a # one-off basis. cucumber_console = Class.new.extend(Cucumber::Formatter::Console) puts cucumber_console.format_string(message, options[:color]) end def debug_log(message, options = {}) $debug_log_fns.each { |fn| fn.call(message, options) } if $debug_log_fns end require 'cucumber/formatter/pretty' # Backport part of commit af940a8 from the cucumber-ruby repo. This # fixes the "out hook output" for the Pretty formatter so stuff # written via `puts` after a Scenario has run its last step will be # written, instead of delayed to the next Feature/Scenario (if any) or # dropped completely (if not). # XXX: This can be removed once we stop supporting Debian Jessie # around when Debian Stretch is released. if Gem::Version.new(Cucumber::VERSION) < Gem::Version.new('2.0.0.beta.4') module Cucumber module Formatter class Pretty def after_feature_element(feature_element) print_messages @io.puts @io.flush end end end end end module ExtraFormatters # This is a null formatter in the sense that it doesn't ever output # anything. We only use it do hook into the correct events so we can # add our extra hooks. class ExtraHooks def initialize(*args) # We do not care about any of the arguments. end def before_feature(feature) if $before_feature_hooks $before_feature_hooks.each do |hook| hook.invoke(feature) if feature.accept_hook?(hook) end end end def after_feature(feature) if $after_feature_hooks $after_feature_hooks.reverse.each do |hook| hook.invoke(feature) if feature.accept_hook?(hook) end end end end # The pretty formatter with debug logging mixed into its output. class PrettyDebug < Cucumber::Formatter::Pretty def initialize(*args) super(*args) $debug_log_fns ||= [] $debug_log_fns << self.method(:debug_log) end def debug_log(message, options) options[:color] ||= :blue @io.puts(format_string(message, options[:color])) @io.flush end end end module Cucumber module Cli class Options BUILTIN_FORMATS['pretty_debug'] = [ 'ExtraFormatters::PrettyDebug', 'Prints the feature with debugging information - in colours.' ] BUILTIN_FORMATS['debug'] = BUILTIN_FORMATS['pretty_debug'] end end end AfterConfiguration do |config| # Cucumber may read this file multiple times, and hence run this # AfterConfiguration hook multiple times. We only want our # ExtraHooks formatter to be loaded once, otherwise the hooks would # be run miltiple times. extra_hooks = ['ExtraFormatters::ExtraHooks', '/dev/null'] config.formats << extra_hooks if not(config.formats.include?(extra_hooks)) end