File: base_matcher_spec.rb

package info (click to toggle)
ruby-rspec 3.13.0c0e0m0s1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 6,856 kB
  • sloc: ruby: 70,868; sh: 1,423; makefile: 99
file content (137 lines) | stat: -rw-r--r-- 4,834 bytes parent folder | download
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
module RSpec::Matchers::BuiltIn
  RSpec.describe BaseMatcher do
    describe "#match_unless_raises" do
      let(:matcher) do
        Class.new(BaseMatcher).new
      end

      it "returns true if there are no errors" do
        expect(matcher.match_unless_raises {}).to be_truthy
      end

      it "returns false if there is an error" do
        expect(matcher.match_unless_raises { raise }).to be_falsey
      end

      it "returns false if the only submitted error is raised" do
        expect(matcher.match_unless_raises(RuntimeError) { raise "foo" }).to be_falsey
      end

      it "returns false if any of several errors submitted is raised" do
        expect(matcher.match_unless_raises(RuntimeError, ArgumentError, NameError) { raise "foo" }).to be_falsey
        expect(matcher.match_unless_raises(RuntimeError, ArgumentError, NameError) { raise ArgumentError.new('') }).to be_falsey
        expect(matcher.match_unless_raises(RuntimeError, ArgumentError, NameError) { raise NameError.new('') }).to be_falsey
      end

      it "re-raises any error other than one of those specified" do
        expect do
          matcher.match_unless_raises(ArgumentError) { raise "foo" }
        end.to raise_error "foo"
      end

      it "stores the rescued exception for use in messages" do
        matcher.match_unless_raises(RuntimeError) { raise "foo" }
        expect(matcher.rescued_exception).to be_a(RuntimeError)
        expect(matcher.rescued_exception.message).to eq("foo")
      end

    end

    describe "#failure_message" do
      context "when the parameter to .new is omitted" do
        it "describes what was expected" do
          matcher_class = Class.new(BaseMatcher) do
            def match(_expected, _actual)
              false
            end
          end

          stub_const("Foo::Bar::BeSomething", matcher_class)

          matcher = matcher_class.new
          matcher.matches?("foo")
          expect(matcher.failure_message).to eq('expected "foo" to be something')
        end
      end
    end

    describe "#===" do
      it "responds the same way as matches?" do
        matcher = Class.new(BaseMatcher) do
          def initialize(expected)
            @expected = expected
          end

          def matches?(actual)
            (@actual = actual) == @expected
          end
        end

        expect(matcher.new(3).matches?(3)).to be_truthy
        expect(matcher.new(3)).to be === 3

        expect(matcher.new(3).matches?(4)).to be_falsey
        expect(matcher.new(3)).not_to be === 4
      end
    end

    describe "default failure message detection" do
      def has_default_failure_messages?(matcher)
        BaseMatcher::DefaultFailureMessages.has_default_failure_messages?(matcher)
      end

      shared_examples_for "detecting default failure message" do
        context "that has no failure message overrides" do
          it "indicates that it has default failure messages" do
            matcher = build_matcher
            expect(has_default_failure_messages?(matcher)).to be true
          end
        end

        context "that overrides `failure_message`" do
          it "indicates that it lacks default failure messages" do
            matcher = build_matcher { def failure_message; end }
            expect(has_default_failure_messages?(matcher)).to be false
          end
        end

        context "that overrides `failure_message_when_negated`" do
          it "indicates that it lacks default failure messages" do
            matcher = build_matcher { def failure_message_when_negated; end }
            expect(has_default_failure_messages?(matcher)).to be false
          end
        end
      end

      context "for a DSL-defined custom matcher" do
        include_examples "detecting default failure message" do
          def build_matcher(&block)
            definition = Proc.new do
              match {}
              module_exec(&block) if block
            end

            RSpec::Matchers::DSL::Matcher.new(:matcher_name, definition, self)
          end
        end
      end

      context "for a matcher that subclasses `BaseMatcher`" do
        include_examples "detecting default failure message" do
          def build_matcher(&block)
            Class.new(RSpec::Matchers::BuiltIn::BaseMatcher, &block).new
          end
        end
      end

      context "for a custom matcher that lacks `failure_message_when_negated` (documented as an optional part of the matcher protocol" do
        it "indicates that it lacks default failure messages" do
          matcher = Class.new(RSpec::Matchers::BuiltIn::BaseMatcher) { undef failure_message_when_negated }.new

          expect(RSpec::Support.is_a_matcher?(matcher)).to be true
          expect(has_default_failure_messages?(matcher)).to be false
        end
      end
    end
  end
end