summaryrefslogtreecommitdiff
path: root/spec/mspec/lib/mspec/guards/guard.rb
blob: 88adbba2602cb127c299629051f5c0a80a96717b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
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
    yield if yield?(false)
  ensure
    unregister
  end

  def run_unless(name, &block)
    @name = name
    yield if yield?(true)
  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