require 'mspec/runner/mspec' require 'mspec/runner/actions/tally' class SpecGuard def self.report @report ||= Hash.new { |h,k| h[k] = [] } end def self.clear @report = nil end def self.finish report.keys.sort.each do |key| desc = report[key] size = desc.size spec = size == 1 ? "spec" : "specs" print "\n\n#{size} #{spec} omitted by guard: #{key}:\n" desc.each { |description| print "\n", description; } end print "\n\n" end def self.guards @guards ||= [] end def self.clear_guards @guards = [] end # Returns a partial Ruby version string based on +which+. # For example, if RUBY_VERSION = 8.2.3: # # :major => "8" # :minor => "8.2" # :tiny => "8.2.3" # :teeny => "8.2.3" # :full => "8.2.3" def self.ruby_version(which = :minor) case which when :major n = 1 when :minor n = 2 when :tiny, :teeny, :full n = 3 end RUBY_VERSION.split('.')[0,n].join('.') end attr_accessor :name def initialize(*args) @parameters = args end def yield?(invert = false) return true if MSpec.mode? :unguarded allow = match? ^ invert if !allow and reporting? MSpec.guard MSpec.register :finish, SpecGuard MSpec.register :add, self return true elsif MSpec.mode? :verify return true end allow end def run_if(name, &block) @name = name if block yield if yield?(false) else yield?(false) end ensure unregister end def run_unless(name, &block) @name = name if block yield if yield?(true) else yield?(true) end ensure unregister end def reporting? MSpec.mode?(:report) or (MSpec.mode?(:report_on) and SpecGuard.guards.include?(name)) end def report_key "#{name} #{@parameters.join(", ")}" end def record(description) SpecGuard.report[report_key] << description end def add(example) record example.description MSpec.retrieve(:formatter).tally.counter.guards! end def unregister MSpec.unguard MSpec.unregister :add, self end def match? raise "must be implemented by the subclass" end end # Combined guards def guard(condition, &block) raise "condition must be a Proc" unless condition.is_a?(Proc) raise LocalJumpError, "no block given" unless block return yield if MSpec.mode? :unguarded or MSpec.mode? :verify or MSpec.mode? :report yield if condition.call end def guard_not(condition, &block) raise "condition must be a Proc" unless condition.is_a?(Proc) raise LocalJumpError, "no block given" unless block return yield if MSpec.mode? :unguarded or MSpec.mode? :verify or MSpec.mode? :report yield unless condition.call end