File: expectation_target_spec.rb

package info (click to toggle)
ruby-rspec 3.5.0c3e0m0s0-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 6,312 kB
  • ctags: 4,788
  • sloc: ruby: 62,572; sh: 785; makefile: 100
file content (152 lines) | stat: -rw-r--r-- 4,852 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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
module RSpec
  module Expectations
    RSpec.describe ExpectationTarget do
      context 'when constructed via #expect' do
        it 'constructs a new instance targetting the given argument' do
          expect(expect(7).target).to eq(7)
        end

        it 'constructs a new instance targetting the given block' do
          block = lambda {}
          expect(expect(&block).target).to be(block)
        end

        it 'raises an ArgumentError when given an argument and a block' do
          expect {
            expect(7) { }
          }.to raise_error(ArgumentError)
        end

        it 'raises a wrong number of args ArgumentError when given two args' do
          expect {
            expect(1, 2)
          }.to raise_error(ArgumentError, /wrong number of arg/)
        end

        it 'raises an ArgumentError when given neither an argument nor a block' do
          expect {
            expect
          }.to raise_error(ArgumentError)
        end

        it 'can be passed nil' do
          expect(expect(nil).target).to be_nil
        end

        it 'passes a valid positive expectation' do
          expect(5).to eq(5)
        end

        it 'passes a valid negative expectation' do
          expect(5).not_to eq(4)
        end

        it 'passes a valid negative expectation with a split infinitive' do
          expect(5).to_not eq(4)
        end

        it 'fails an invalid positive expectation' do
          expect {
            expect(5).to eq(4)
          }.to fail_with(/expected: 4.*got: 5/m)
        end

        it 'fails an invalid negative expectation' do
          message = /expected 5 not to be a kind of Fixnum/
          expect {
            expect(5).not_to be_a(Fixnum)
          }.to fail_with(message)
        end

        it 'fails an invalid negative expectation with a split infinitive' do
          message = /expected 5 not to be a kind of Fixnum/
          expect {
            expect(5).to_not be_a(Fixnum)
          }.to fail_with(message)
        end

        it 'does not support operator matchers from #to' do
          expect {
            expect(3).to == 3
          }.to raise_error(ArgumentError)
        end

        it 'does not support operator matchers from #not_to' do
          expect {
            expect(3).not_to == 4
          }.to raise_error(ArgumentError)
        end
      end

      context "when passed a block" do
        it 'can be used with a block matcher' do
          expect { }.not_to raise_error
        end

        context 'when passed a value matcher' do
          not_a_block_matcher_error = /You must pass an argument rather than a block to use the provided matcher/

          it 'raises an error that directs the user to pass an arg rather than a block' do
            expect {
              expect { }.to be_an(Object)
            }.to fail_with(not_a_block_matcher_error)

            expect {
              expect { }.not_to be_nil
            }.to fail_with(not_a_block_matcher_error)

            expect {
              expect { }.to_not be_nil
            }.to fail_with(not_a_block_matcher_error)
          end

          it 'assumes a custom matcher that does not define `supports_block_expectations?` is not a block matcher (since it is relatively rare)' do
            custom_matcher = Module.new do
              def self.matches?(value); true; end
              def self.description; "foo"; end
            end

            expect(3).to custom_matcher # to show the custom matcher can be used as a matcher

            expect {
              expect { 3 }.to custom_matcher
            }.to fail_with(not_a_block_matcher_error)
          end

          def new_non_dsl_matcher(&method_defs)
            Module.new do
              def self.matches?(object); end
              def self.failure_message; end
              module_eval(&method_defs)
            end
          end

          it "uses the matcher's `description` in the error message" do
            custom_matcher = new_non_dsl_matcher do
              def self.supports_block_expectations?; false; end
              def self.description; "matcher-description"; end
            end

            expect {
              expect { }.to custom_matcher
            }.to fail_with(/\(matcher-description\)/)
          end

          context 'when the matcher does not define `description` (since it is an optional part of the protocol)' do
            it 'uses `inspect` in the error message instead' do
              custom_matcher = new_non_dsl_matcher do
                def self.supports_block_expectations?; false; end
                def self.inspect; "matcher-inspect"; end
              end

              expect {
                expect { }.to custom_matcher
              }.to fail_with(/\(matcher-inspect\)/)
            end
          end
        end
      end
    end
  end
end