rspec-expectations 3.0.0.beta2 → 3.0.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +2 -2
- data/.yardopts +0 -1
- data/Changelog.md +115 -35
- data/README.md +2 -2
- data/lib/rspec/expectations.rb +13 -8
- data/lib/rspec/{matchers → expectations}/configuration.rb +38 -13
- data/lib/rspec/expectations/expectation_target.rb +72 -8
- data/lib/rspec/expectations/fail_with.rb +10 -52
- data/lib/rspec/expectations/handler.rb +9 -11
- data/lib/rspec/expectations/syntax.rb +37 -35
- data/lib/rspec/expectations/version.rb +1 -1
- data/lib/rspec/matchers.rb +60 -9
- data/lib/rspec/matchers/aliased_matcher.rb +6 -0
- data/lib/rspec/matchers/built_in.rb +9 -1
- data/lib/rspec/matchers/built_in/all.rb +78 -0
- data/lib/rspec/matchers/built_in/base_matcher.rb +39 -1
- data/lib/rspec/matchers/built_in/be.rb +117 -42
- data/lib/rspec/matchers/built_in/be_between.rb +22 -0
- data/lib/rspec/matchers/built_in/be_instance_of.rb +11 -3
- data/lib/rspec/matchers/built_in/be_kind_of.rb +5 -0
- data/lib/rspec/matchers/built_in/be_within.rb +26 -6
- data/lib/rspec/matchers/built_in/change.rb +89 -13
- data/lib/rspec/matchers/built_in/compound.rb +19 -3
- data/lib/rspec/matchers/built_in/contain_exactly.rb +17 -6
- data/lib/rspec/matchers/built_in/cover.rb +3 -0
- data/lib/rspec/matchers/built_in/eq.rb +20 -5
- data/lib/rspec/matchers/built_in/eql.rb +15 -3
- data/lib/rspec/matchers/built_in/equal.rb +23 -6
- data/lib/rspec/matchers/built_in/exist.rb +74 -10
- data/lib/rspec/matchers/built_in/has.rb +58 -3
- data/lib/rspec/matchers/built_in/include.rb +16 -1
- data/lib/rspec/matchers/built_in/match.rb +14 -4
- data/lib/rspec/matchers/built_in/operators.rb +16 -0
- data/lib/rspec/matchers/built_in/output.rb +47 -5
- data/lib/rspec/matchers/built_in/raise_error.rb +40 -23
- data/lib/rspec/matchers/built_in/respond_to.rb +37 -16
- data/lib/rspec/matchers/built_in/satisfy.rb +15 -0
- data/lib/rspec/matchers/built_in/start_and_end_with.rb +29 -14
- data/lib/rspec/matchers/built_in/throw_symbol.rb +32 -3
- data/lib/rspec/matchers/built_in/yield.rb +148 -44
- data/lib/rspec/matchers/composable.rb +48 -7
- data/lib/rspec/matchers/dsl.rb +45 -17
- data/lib/rspec/matchers/generated_descriptions.rb +7 -0
- data/lib/rspec/matchers/matcher_delegator.rb +6 -2
- data/lib/rspec/matchers/pretty.rb +15 -19
- metadata +33 -236
- metadata.gz.sig +0 -0
- data/features/README.md +0 -48
- data/features/Upgrade.md +0 -53
- data/features/built_in_matchers/README.md +0 -96
- data/features/built_in_matchers/be.feature +0 -175
- data/features/built_in_matchers/be_within.feature +0 -48
- data/features/built_in_matchers/comparisons.feature +0 -97
- data/features/built_in_matchers/contain_exactly.feature +0 -46
- data/features/built_in_matchers/cover.feature +0 -47
- data/features/built_in_matchers/end_with.feature +0 -48
- data/features/built_in_matchers/equality.feature +0 -136
- data/features/built_in_matchers/exist.feature +0 -45
- data/features/built_in_matchers/expect_change.feature +0 -59
- data/features/built_in_matchers/expect_error.feature +0 -144
- data/features/built_in_matchers/include.feature +0 -126
- data/features/built_in_matchers/match.feature +0 -51
- data/features/built_in_matchers/output.feature +0 -70
- data/features/built_in_matchers/predicates.feature +0 -161
- data/features/built_in_matchers/respond_to.feature +0 -84
- data/features/built_in_matchers/satisfy.feature +0 -33
- data/features/built_in_matchers/start_with.feature +0 -48
- data/features/built_in_matchers/throw_symbol.feature +0 -91
- data/features/built_in_matchers/types.feature +0 -116
- data/features/built_in_matchers/yield.feature +0 -161
- data/features/composing_matchers.feature +0 -250
- data/features/compound_expectations.feature +0 -45
- data/features/custom_matchers/access_running_example.feature +0 -53
- data/features/custom_matchers/define_diffable_matcher.feature +0 -27
- data/features/custom_matchers/define_matcher.feature +0 -340
- data/features/custom_matchers/define_matcher_outside_rspec.feature +0 -34
- data/features/custom_matchers/define_matcher_with_fluent_interface.feature +0 -24
- data/features/customized_message.feature +0 -39
- data/features/diffing.feature +0 -85
- data/features/implicit_docstrings.feature +0 -52
- data/features/step_definitions/additional_cli_steps.rb +0 -22
- data/features/support/env.rb +0 -21
- data/features/support/rubinius.rb +0 -6
- data/features/syntax_configuration.feature +0 -71
- data/features/test_frameworks/minitest.feature +0 -44
- data/lib/rspec-expectations.rb +0 -1
- data/lib/rspec/expectations/diff_presenter.rb +0 -141
- data/lib/rspec/expectations/differ.rb +0 -44
- data/lib/rspec/expectations/encoded_string.rb +0 -56
- data/spec/rspec/expectations/diff_presenter_spec.rb +0 -249
- data/spec/rspec/expectations/encoded_string_spec.rb +0 -74
- data/spec/rspec/expectations/expectation_target_spec.rb +0 -82
- data/spec/rspec/expectations/extensions/kernel_spec.rb +0 -67
- data/spec/rspec/expectations/fail_with_spec.rb +0 -114
- data/spec/rspec/expectations/handler_spec.rb +0 -205
- data/spec/rspec/expectations/minitest_integration_spec.rb +0 -27
- data/spec/rspec/expectations/syntax_spec.rb +0 -89
- data/spec/rspec/expectations_spec.rb +0 -12
- data/spec/rspec/matchers/aliased_matcher_spec.rb +0 -48
- data/spec/rspec/matchers/aliases_spec.rb +0 -449
- data/spec/rspec/matchers/built_in/base_matcher_spec.rb +0 -83
- data/spec/rspec/matchers/built_in/be_between_spec.rb +0 -159
- data/spec/rspec/matchers/built_in/be_instance_of_spec.rb +0 -63
- data/spec/rspec/matchers/built_in/be_kind_of_spec.rb +0 -41
- data/spec/rspec/matchers/built_in/be_spec.rb +0 -592
- data/spec/rspec/matchers/built_in/be_within_spec.rb +0 -141
- data/spec/rspec/matchers/built_in/change_spec.rb +0 -808
- data/spec/rspec/matchers/built_in/compound_spec.rb +0 -292
- data/spec/rspec/matchers/built_in/contain_exactly_spec.rb +0 -441
- data/spec/rspec/matchers/built_in/cover_spec.rb +0 -69
- data/spec/rspec/matchers/built_in/eq_spec.rb +0 -156
- data/spec/rspec/matchers/built_in/eql_spec.rb +0 -41
- data/spec/rspec/matchers/built_in/equal_spec.rb +0 -106
- data/spec/rspec/matchers/built_in/exist_spec.rb +0 -124
- data/spec/rspec/matchers/built_in/has_spec.rb +0 -161
- data/spec/rspec/matchers/built_in/include_spec.rb +0 -540
- data/spec/rspec/matchers/built_in/match_spec.rb +0 -102
- data/spec/rspec/matchers/built_in/operators_spec.rb +0 -252
- data/spec/rspec/matchers/built_in/output_spec.rb +0 -165
- data/spec/rspec/matchers/built_in/raise_error_spec.rb +0 -461
- data/spec/rspec/matchers/built_in/respond_to_spec.rb +0 -292
- data/spec/rspec/matchers/built_in/satisfy_spec.rb +0 -44
- data/spec/rspec/matchers/built_in/start_and_end_with_spec.rb +0 -253
- data/spec/rspec/matchers/built_in/throw_symbol_spec.rb +0 -135
- data/spec/rspec/matchers/built_in/yield_spec.rb +0 -627
- data/spec/rspec/matchers/configuration_spec.rb +0 -213
- data/spec/rspec/matchers/description_generation_spec.rb +0 -191
- data/spec/rspec/matchers/dsl_spec.rb +0 -895
- data/spec/rspec/matchers/legacy_spec.rb +0 -101
- data/spec/rspec/matchers_spec.rb +0 -74
- data/spec/spec_helper.rb +0 -85
- data/spec/support/matchers.rb +0 -22
- data/spec/support/shared_examples.rb +0 -35
@@ -1,213 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'delegate'
|
3
|
-
|
4
|
-
module RSpec
|
5
|
-
module Matchers
|
6
|
-
describe "RSpec::Matchers.configuration" do
|
7
|
-
it 'returns a memoized configuration instance' do
|
8
|
-
expect(RSpec::Matchers.configuration).to be_a(RSpec::Matchers::Configuration)
|
9
|
-
expect(RSpec::Matchers.configuration).to be(RSpec::Matchers.configuration)
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
describe Configuration do
|
14
|
-
let(:config) { Configuration.new }
|
15
|
-
|
16
|
-
describe "#backtrace_formatter" do
|
17
|
-
let(:original_backtrace) { %w[ clean-me/a.rb other/file.rb clean-me/b.rb ] }
|
18
|
-
let(:cleaned_backtrace) { %w[ other/file.rb ] }
|
19
|
-
|
20
|
-
let(:formatted_backtrace) do
|
21
|
-
config.backtrace_formatter.format_backtrace(original_backtrace)
|
22
|
-
end
|
23
|
-
|
24
|
-
before do
|
25
|
-
@old_patterns = RSpec.configuration.backtrace_exclusion_patterns
|
26
|
-
@orig_full_backtrace = RSpec.configuration.full_backtrace?
|
27
|
-
RSpec.configuration.full_backtrace = false
|
28
|
-
RSpec.configuration.backtrace_exclusion_patterns = [/clean-me/]
|
29
|
-
end
|
30
|
-
|
31
|
-
after do
|
32
|
-
RSpec.configuration.backtrace_exclusion_patterns = @old_patterns
|
33
|
-
RSpec.configuration.full_backtrace = @orig_full_backtrace
|
34
|
-
end
|
35
|
-
|
36
|
-
it "defaults to rspec-core's backtrace formatter when rspec-core is loaded" do
|
37
|
-
expect(config.backtrace_formatter).to be(RSpec::Core::BacktraceFormatter)
|
38
|
-
expect(formatted_backtrace).to eq(cleaned_backtrace)
|
39
|
-
end
|
40
|
-
|
41
|
-
it "defaults to a null formatter when rspec-core is not loaded" do
|
42
|
-
hide_const("RSpec::Core::BacktraceFormatter")
|
43
|
-
expect(formatted_backtrace).to eq(original_backtrace)
|
44
|
-
end
|
45
|
-
|
46
|
-
it "can be set to another backtrace formatter" do
|
47
|
-
config.backtrace_formatter = double(:format_backtrace => ['a'])
|
48
|
-
expect(formatted_backtrace).to eq(['a'])
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
context 'on an interpreter that does not provide BasicObject', :uses_should, :unless => defined?(::BasicObject) do
|
53
|
-
before { RSpec::Expectations::Syntax.disable_should(Delegator) }
|
54
|
-
|
55
|
-
let(:klass) do
|
56
|
-
Class.new(SimpleDelegator) do
|
57
|
-
def delegated?; true; end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
let(:instance) { klass.new(Object.new) }
|
62
|
-
|
63
|
-
it 'provides a means to manually add it Delegator' do
|
64
|
-
instance.should_not respond_to(:delegated?) # because #should is being delegated...
|
65
|
-
config.add_should_and_should_not_to Delegator
|
66
|
-
instance.should respond_to(:delegated?) # now it should work!
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
shared_examples_for "configuring the expectation syntax" do
|
71
|
-
before do
|
72
|
-
@orig_syntax = RSpec::Matchers.configuration.syntax
|
73
|
-
end
|
74
|
-
|
75
|
-
after do
|
76
|
-
configure_syntax(@orig_syntax)
|
77
|
-
end
|
78
|
-
|
79
|
-
it 'can limit the syntax to :should' do
|
80
|
-
configure_syntax :should
|
81
|
-
configured_syntax.should eq([:should])
|
82
|
-
|
83
|
-
3.should eq(3)
|
84
|
-
3.should_not eq(4)
|
85
|
-
lambda { expect(6).to eq(6) }.should raise_error(NameError)
|
86
|
-
end
|
87
|
-
|
88
|
-
it 'is a no-op when configured to :should twice' do
|
89
|
-
configure_syntax :should
|
90
|
-
method_added_count = 0
|
91
|
-
allow(Expectations::Syntax.default_should_host).to receive(:method_added) { method_added_count += 1 }
|
92
|
-
configure_syntax :should
|
93
|
-
|
94
|
-
method_added_count.should eq(0)
|
95
|
-
end
|
96
|
-
|
97
|
-
it 'can limit the syntax to :expect' do
|
98
|
-
configure_syntax :expect
|
99
|
-
expect(configured_syntax).to eq([:expect])
|
100
|
-
|
101
|
-
expect(3).to eq(3)
|
102
|
-
expect { 3.should eq(3) }.to raise_error(NameError)
|
103
|
-
expect { 3.should_not eq(3) }.to raise_error(NameError)
|
104
|
-
end
|
105
|
-
|
106
|
-
it 'is a no-op when configured to :expect twice' do
|
107
|
-
allow(RSpec::Matchers).to receive(:method_added).and_raise("no methods should be added here")
|
108
|
-
|
109
|
-
configure_syntax :expect
|
110
|
-
configure_syntax :expect
|
111
|
-
end
|
112
|
-
|
113
|
-
describe "`:should` being enabled by default deprecation" do
|
114
|
-
before { configure_default_syntax }
|
115
|
-
|
116
|
-
it "warns when the should syntax is called by default" do
|
117
|
-
expected_arguments = [
|
118
|
-
/Using.*without explicitly enabling/,
|
119
|
-
{:replacement=>"the new `:expect` syntax or explicitly enable `:should`"}
|
120
|
-
]
|
121
|
-
|
122
|
-
expect(RSpec).to receive(:deprecate).with(*expected_arguments)
|
123
|
-
3.should eq(3)
|
124
|
-
end
|
125
|
-
|
126
|
-
it "includes the call site in the deprecation warning by default" do
|
127
|
-
expect_deprecation_with_call_site(__FILE__, __LINE__ + 1)
|
128
|
-
3.should eq(3)
|
129
|
-
end
|
130
|
-
|
131
|
-
it "does not warn when only the should syntax is explicitly configured" do
|
132
|
-
configure_syntax(:should)
|
133
|
-
RSpec.should_not receive(:deprecate)
|
134
|
-
3.should eq(3)
|
135
|
-
end
|
136
|
-
|
137
|
-
it "does not warn when both the should and expect syntaxes are explicitly configured" do
|
138
|
-
configure_syntax([:should, :expect])
|
139
|
-
expect(RSpec).not_to receive(:deprecate)
|
140
|
-
3.should eq(3)
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
it 'can re-enable the :should syntax' do
|
145
|
-
configure_syntax :expect
|
146
|
-
configure_syntax [:should, :expect]
|
147
|
-
configured_syntax.should eq([:should, :expect])
|
148
|
-
|
149
|
-
3.should eq(3)
|
150
|
-
3.should_not eq(4)
|
151
|
-
expect(3).to eq(3)
|
152
|
-
end
|
153
|
-
|
154
|
-
it 'can re-enable the :expect syntax' do
|
155
|
-
configure_syntax :should
|
156
|
-
configure_syntax [:should, :expect]
|
157
|
-
configured_syntax.should eq([:should, :expect])
|
158
|
-
|
159
|
-
3.should eq(3)
|
160
|
-
3.should_not eq(4)
|
161
|
-
expect(3).to eq(3)
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
def configure_default_syntax
|
166
|
-
RSpec::Matchers.configuration.reset_syntaxes_to_default
|
167
|
-
end
|
168
|
-
|
169
|
-
describe "configuring rspec-expectations directly" do
|
170
|
-
it_behaves_like "configuring the expectation syntax" do
|
171
|
-
def configure_syntax(syntax)
|
172
|
-
RSpec::Matchers.configuration.syntax = syntax
|
173
|
-
end
|
174
|
-
|
175
|
-
def configured_syntax
|
176
|
-
RSpec::Matchers.configuration.syntax
|
177
|
-
end
|
178
|
-
end
|
179
|
-
end
|
180
|
-
|
181
|
-
describe "configuring using the rspec-core config API" do
|
182
|
-
it_behaves_like "configuring the expectation syntax" do
|
183
|
-
def configure_syntax(syntax)
|
184
|
-
RSpec.configure do |rspec|
|
185
|
-
rspec.expect_with :rspec do |c|
|
186
|
-
c.syntax = syntax
|
187
|
-
end
|
188
|
-
end
|
189
|
-
end
|
190
|
-
|
191
|
-
|
192
|
-
def configured_syntax
|
193
|
-
RSpec.configure do |rspec|
|
194
|
-
rspec.expect_with :rspec do |c|
|
195
|
-
return c.syntax
|
196
|
-
end
|
197
|
-
end
|
198
|
-
end
|
199
|
-
end
|
200
|
-
end
|
201
|
-
|
202
|
-
it 'enables both syntaxes by default' do
|
203
|
-
# This is kinda a hack, but since we want to enforce use of
|
204
|
-
# the expect syntax within our specs here, we have modified the
|
205
|
-
# config setting, which makes it hard to get at the original
|
206
|
-
# default value. in spec_helper.rb we store the default value
|
207
|
-
# in $default_expectation_syntax so we can use it here.
|
208
|
-
expect($default_expectation_syntax).to contain_exactly(:expect, :should)
|
209
|
-
end
|
210
|
-
end
|
211
|
-
end
|
212
|
-
end
|
213
|
-
|
@@ -1,191 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe "Matchers should be able to generate their own descriptions" do
|
4
|
-
after(:each) do
|
5
|
-
RSpec::Matchers.clear_generated_description
|
6
|
-
end
|
7
|
-
|
8
|
-
it "expect(...).to eq expected" do
|
9
|
-
expect("this").to eq "this"
|
10
|
-
expect(RSpec::Matchers.generated_description).to eq "should eq \"this\""
|
11
|
-
end
|
12
|
-
|
13
|
-
it "expect(...).to not eq expected" do
|
14
|
-
expect("this").not_to eq "that"
|
15
|
-
expect(RSpec::Matchers.generated_description).to eq "should not eq \"that\""
|
16
|
-
end
|
17
|
-
|
18
|
-
it "expect(...).to be empty (arbitrary predicate)" do
|
19
|
-
expect([]).to be_empty
|
20
|
-
expect(RSpec::Matchers.generated_description).to eq "should be empty"
|
21
|
-
end
|
22
|
-
|
23
|
-
it "expect(...).to not be empty (arbitrary predicate)" do
|
24
|
-
expect([1]).not_to be_empty
|
25
|
-
expect(RSpec::Matchers.generated_description).to eq "should not be empty"
|
26
|
-
end
|
27
|
-
|
28
|
-
it "expect(...).to be truthy" do
|
29
|
-
expect(true).to be_truthy
|
30
|
-
expect(RSpec::Matchers.generated_description).to eq "should be truthy"
|
31
|
-
end
|
32
|
-
|
33
|
-
it "expect(...).to be falsey" do
|
34
|
-
expect(false).to be_falsey
|
35
|
-
expect(RSpec::Matchers.generated_description).to eq "should be falsey"
|
36
|
-
end
|
37
|
-
|
38
|
-
it "expect(...).to be nil" do
|
39
|
-
expect(nil).to be_nil
|
40
|
-
expect(RSpec::Matchers.generated_description).to eq "should be nil"
|
41
|
-
end
|
42
|
-
|
43
|
-
it "expect(...).to be > n" do
|
44
|
-
expect(5).to be > 3
|
45
|
-
expect(RSpec::Matchers.generated_description).to eq "should be > 3"
|
46
|
-
end
|
47
|
-
|
48
|
-
it "expect(...).to be between min and max" do
|
49
|
-
expect(10).to be_between(0, 10)
|
50
|
-
expect(RSpec::Matchers.generated_description).to eq "should be between 0 and 10 (inclusive)"
|
51
|
-
end
|
52
|
-
|
53
|
-
it "expect(...).to be exclusively between min and max" do
|
54
|
-
expect(9).to be_between(0, 10).exclusive
|
55
|
-
expect(RSpec::Matchers.generated_description).to eq "should be between 0 and 10 (exclusive)"
|
56
|
-
end
|
57
|
-
|
58
|
-
it "expect(...).to be predicate arg1, arg2 and arg3" do
|
59
|
-
class Parent; end
|
60
|
-
class Child < Parent
|
61
|
-
def child_of?(*parents)
|
62
|
-
parents.all? { |parent| self.is_a?(parent) }
|
63
|
-
end
|
64
|
-
end
|
65
|
-
expect(Child.new).to be_a_child_of(Parent, Object)
|
66
|
-
expect(RSpec::Matchers.generated_description).to eq "should be a child of Parent and Object"
|
67
|
-
end
|
68
|
-
|
69
|
-
it "expect(...).to equal" do
|
70
|
-
expected = "expected"
|
71
|
-
expect(expected).to equal(expected)
|
72
|
-
expect(RSpec::Matchers.generated_description).to eq "should equal \"expected\""
|
73
|
-
end
|
74
|
-
|
75
|
-
it "expect(...).not_to equal" do
|
76
|
-
expect(5).not_to equal(37)
|
77
|
-
expect(RSpec::Matchers.generated_description).to eq "should not equal 37"
|
78
|
-
end
|
79
|
-
|
80
|
-
it "expect(...).to eql" do
|
81
|
-
expect("string").to eql("string")
|
82
|
-
expect(RSpec::Matchers.generated_description).to eq "should eql \"string\""
|
83
|
-
end
|
84
|
-
|
85
|
-
it "expect(...).not_to eql" do
|
86
|
-
expect("a").not_to eql(:a)
|
87
|
-
expect(RSpec::Matchers.generated_description).to eq "should not eql :a"
|
88
|
-
end
|
89
|
-
|
90
|
-
it "expect(...).to have_key" do
|
91
|
-
expect({:a => "a"}).to have_key(:a)
|
92
|
-
expect(RSpec::Matchers.generated_description).to eq "should have key :a"
|
93
|
-
end
|
94
|
-
|
95
|
-
it "expect(...).to have_some_method" do
|
96
|
-
object = Object.new
|
97
|
-
def object.has_eyes_closed?; true; end
|
98
|
-
|
99
|
-
expect(object).to have_eyes_closed
|
100
|
-
expect(RSpec::Matchers.generated_description).to eq 'should have eyes closed'
|
101
|
-
end
|
102
|
-
|
103
|
-
it "expect(...).to have_some_method(args*)" do
|
104
|
-
object = Object.new
|
105
|
-
def object.has_taste_for?(*args); true; end
|
106
|
-
|
107
|
-
expect(object).to have_taste_for("wine", "cheese")
|
108
|
-
expect(RSpec::Matchers.generated_description).to eq 'should have taste for "wine", "cheese"'
|
109
|
-
end
|
110
|
-
|
111
|
-
it "expect(...).to include(x)" do
|
112
|
-
expect([1,2,3]).to include(3)
|
113
|
-
expect(RSpec::Matchers.generated_description).to eq "should include 3"
|
114
|
-
end
|
115
|
-
|
116
|
-
it "expect(...).to include(x) when x responds to description but is not a matcher" do
|
117
|
-
obj = double(:description => "description", :inspect => "inspect")
|
118
|
-
expect([obj]).to include(obj)
|
119
|
-
expect(RSpec::Matchers.generated_description).to eq "should include inspect"
|
120
|
-
end
|
121
|
-
|
122
|
-
it "expect(...).to include(x) when x responds to description and is a matcher" do
|
123
|
-
matcher = double(:description => "description",
|
124
|
-
:matches? => true,
|
125
|
-
:failure_message => "")
|
126
|
-
expect([matcher]).to include(matcher)
|
127
|
-
expect(RSpec::Matchers.generated_description).to eq "should include (description)"
|
128
|
-
end
|
129
|
-
|
130
|
-
it "expect(array).to contain_exactly(1, 2, 3)" do
|
131
|
-
expect([1,2,3]).to contain_exactly(1, 2, 3)
|
132
|
-
expect(RSpec::Matchers.generated_description).to eq "should contain exactly 1, 2 and 3"
|
133
|
-
end
|
134
|
-
|
135
|
-
it "expect(...).to match" do
|
136
|
-
expect("this string").to match(/this string/)
|
137
|
-
expect(RSpec::Matchers.generated_description).to eq "should match /this string/"
|
138
|
-
end
|
139
|
-
|
140
|
-
it "expect(...).to raise_error" do
|
141
|
-
expect { raise }.to raise_error
|
142
|
-
expect(RSpec::Matchers.generated_description).to eq "should raise Exception"
|
143
|
-
end
|
144
|
-
|
145
|
-
it "expect(...).to raise_error with type" do
|
146
|
-
expect { raise }.to raise_error(RuntimeError)
|
147
|
-
expect(RSpec::Matchers.generated_description).to eq "should raise RuntimeError"
|
148
|
-
end
|
149
|
-
|
150
|
-
it "expect(...).to raise_error with type and message" do
|
151
|
-
expect { raise "there was an error" }.to raise_error(RuntimeError, "there was an error")
|
152
|
-
expect(RSpec::Matchers.generated_description).to eq "should raise RuntimeError with \"there was an error\""
|
153
|
-
end
|
154
|
-
|
155
|
-
it "expect(...).to respond_to" do
|
156
|
-
expect([]).to respond_to(:insert)
|
157
|
-
expect(RSpec::Matchers.generated_description).to eq "should respond to #insert"
|
158
|
-
end
|
159
|
-
|
160
|
-
it "expect(...).to throw symbol" do
|
161
|
-
expect { throw :what_a_mess }.to throw_symbol
|
162
|
-
expect(RSpec::Matchers.generated_description).to eq "should throw a Symbol"
|
163
|
-
end
|
164
|
-
|
165
|
-
it "expect(...).to throw symbol (with named symbol)" do
|
166
|
-
expect { throw :what_a_mess }.to throw_symbol(:what_a_mess)
|
167
|
-
expect(RSpec::Matchers.generated_description).to eq "should throw :what_a_mess"
|
168
|
-
end
|
169
|
-
|
170
|
-
def team
|
171
|
-
Class.new do
|
172
|
-
def players
|
173
|
-
[1,2,3]
|
174
|
-
end
|
175
|
-
end.new
|
176
|
-
end
|
177
|
-
end
|
178
|
-
|
179
|
-
describe "a Matcher with no description" do
|
180
|
-
def matcher
|
181
|
-
Class.new do
|
182
|
-
def matches?(ignore); true; end
|
183
|
-
def failure_message; ""; end
|
184
|
-
end.new
|
185
|
-
end
|
186
|
-
|
187
|
-
it "provides a helpful message when used in a string-less example block" do
|
188
|
-
expect(5).to matcher
|
189
|
-
expect(RSpec::Matchers.generated_description).to match(/When you call.*description method/m)
|
190
|
-
end
|
191
|
-
end
|
@@ -1,895 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
require 'spec_helper'
|
3
|
-
|
4
|
-
describe "a matcher defined using the matcher DSL" do
|
5
|
-
def question?
|
6
|
-
:answer
|
7
|
-
end
|
8
|
-
|
9
|
-
def ok
|
10
|
-
"ok"
|
11
|
-
end
|
12
|
-
|
13
|
-
it "supports calling custom matchers from within other custom matchers" do
|
14
|
-
RSpec::Matchers.define :be_ok do
|
15
|
-
match { |actual| actual == ok }
|
16
|
-
end
|
17
|
-
|
18
|
-
RSpec::Matchers.define :be_well do
|
19
|
-
match { |actual| expect(actual).to be_ok }
|
20
|
-
end
|
21
|
-
|
22
|
-
expect(ok).to be_well
|
23
|
-
end
|
24
|
-
|
25
|
-
it "has access to methods available in the scope of the example" do
|
26
|
-
RSpec::Matchers::define(:matcher_a) {}
|
27
|
-
expect(matcher_a.question?).to eq(:answer)
|
28
|
-
end
|
29
|
-
|
30
|
-
it "raises when method is missing from local scope as well as matcher" do
|
31
|
-
RSpec::Matchers::define(:matcher_b) {}
|
32
|
-
expect { matcher_b.i_dont_exist }.to raise_error(NameError)
|
33
|
-
end
|
34
|
-
|
35
|
-
it "clears user instance variables between invocations" do
|
36
|
-
RSpec::Matchers::define(:be_just_like) do |expected|
|
37
|
-
match do |actual|
|
38
|
-
@foo ||= expected
|
39
|
-
@foo == actual
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
expect(3).to be_just_like(3)
|
44
|
-
expect(4).to be_just_like(4)
|
45
|
-
end
|
46
|
-
|
47
|
-
describe "#respond_to?" do
|
48
|
-
it "returns true for methods in example scope" do
|
49
|
-
RSpec::Matchers::define(:matcher_c) {}
|
50
|
-
expect(matcher_c).to respond_to(:question?)
|
51
|
-
end
|
52
|
-
|
53
|
-
it "returns false for methods not defined in matcher or example scope" do
|
54
|
-
RSpec::Matchers::define(:matcher_d) {}
|
55
|
-
expect(matcher_d).not_to respond_to(:i_dont_exist)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
class UnexpectedError < StandardError; end
|
61
|
-
module MatcherHelperModule
|
62
|
-
def self.included(base)
|
63
|
-
base.module_exec do
|
64
|
-
def included_method; end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def self.extended(base)
|
69
|
-
base.instance_exec do
|
70
|
-
def extended_method; end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
def greeting
|
75
|
-
"Hello, World"
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
module RSpec::Matchers::DSL
|
80
|
-
describe Matcher do
|
81
|
-
def new_matcher(name, *expected, &block)
|
82
|
-
RSpec::Matchers::DSL::Matcher.
|
83
|
-
new(name, block, *expected).
|
84
|
-
tap { |m| m.matcher_execution_context = self }
|
85
|
-
end
|
86
|
-
|
87
|
-
it_behaves_like "an RSpec matcher", :valid_value => 1, :invalid_value => 2 do
|
88
|
-
let(:matcher) do
|
89
|
-
new_matcher(:equal_to_1) do
|
90
|
-
match { |v| v == 1 }
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
it "can be stored aside and used later" do
|
96
|
-
# Supports using rspec-expectation matchers as argument matchers in
|
97
|
-
# rspec-mocks.
|
98
|
-
RSpec::Matchers.define :example_matcher do |expected|
|
99
|
-
match do |actual|
|
100
|
-
actual == expected
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
m1 = example_matcher(1)
|
105
|
-
m2 = example_matcher(2)
|
106
|
-
|
107
|
-
expect(m1.matches?(1)).to be_truthy
|
108
|
-
expect(m2.matches?(2)).to be_truthy
|
109
|
-
end
|
110
|
-
|
111
|
-
context 'using deprecated APIs' do
|
112
|
-
before { allow_deprecation }
|
113
|
-
|
114
|
-
describe "failure_message_for_should" do
|
115
|
-
let(:matcher) do
|
116
|
-
new_matcher(:foo) do
|
117
|
-
match { false }
|
118
|
-
failure_message_for_should { "failed" }
|
119
|
-
end
|
120
|
-
end
|
121
|
-
line = __LINE__ - 3
|
122
|
-
|
123
|
-
it 'defines the failure message for a positive expectation' do
|
124
|
-
expect {
|
125
|
-
expect(nil).to matcher
|
126
|
-
}.to fail_with("failed")
|
127
|
-
end
|
128
|
-
|
129
|
-
it 'prints a deprecation warning' do
|
130
|
-
expect_deprecation_with_call_site(__FILE__, line, /failure_message_for_should/)
|
131
|
-
matcher
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
describe "failure_message_for_should_not" do
|
136
|
-
let(:matcher) do
|
137
|
-
new_matcher(:foo) do
|
138
|
-
match { true }
|
139
|
-
failure_message_for_should_not { "failed" }
|
140
|
-
end
|
141
|
-
end
|
142
|
-
line = __LINE__ - 3
|
143
|
-
|
144
|
-
it 'defines the failure message for a negative expectation' do
|
145
|
-
expect {
|
146
|
-
expect(nil).not_to matcher
|
147
|
-
}.to fail_with("failed")
|
148
|
-
end
|
149
|
-
|
150
|
-
it 'prints a deprecation warning' do
|
151
|
-
expect_deprecation_with_call_site(__FILE__, line, /failure_message_for_should_not/)
|
152
|
-
matcher
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
|
-
describe "match_for_should" do
|
157
|
-
let(:matcher) do
|
158
|
-
new_matcher(:foo) do
|
159
|
-
match_for_should { |arg| arg }
|
160
|
-
end
|
161
|
-
end
|
162
|
-
line = __LINE__ - 3
|
163
|
-
|
164
|
-
it 'defines the positive expectation match logic' do
|
165
|
-
expect(true).to matcher
|
166
|
-
expect { expect(false).to matcher }.to fail_with(/foo/)
|
167
|
-
end
|
168
|
-
|
169
|
-
it 'prints a deprecation warning' do
|
170
|
-
expect_deprecation_with_call_site(__FILE__, line, /match_for_should/)
|
171
|
-
matcher
|
172
|
-
end
|
173
|
-
end
|
174
|
-
|
175
|
-
describe "match_for_should_not" do
|
176
|
-
let(:matcher) do
|
177
|
-
new_matcher(:foo) do
|
178
|
-
match_for_should_not { |arg| !arg }
|
179
|
-
end
|
180
|
-
end
|
181
|
-
line = __LINE__ - 3
|
182
|
-
|
183
|
-
it 'defines the positive expectation match logic' do
|
184
|
-
expect(false).not_to matcher
|
185
|
-
expect { expect(true).not_to matcher }.to fail_with(/foo/)
|
186
|
-
end
|
187
|
-
|
188
|
-
it 'prints a deprecation warning' do
|
189
|
-
expect_deprecation_with_call_site(__FILE__, line, /match_for_should_not/)
|
190
|
-
matcher
|
191
|
-
end
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
context "with an included module" do
|
196
|
-
let(:matcher) do
|
197
|
-
new_matcher(:be_a_greeting) do
|
198
|
-
include MatcherHelperModule
|
199
|
-
match { |actual| actual == greeting }
|
200
|
-
end
|
201
|
-
end
|
202
|
-
|
203
|
-
it "has access to the module's methods" do
|
204
|
-
matcher.matches?("Hello, World")
|
205
|
-
end
|
206
|
-
|
207
|
-
it "runs the module's included hook" do
|
208
|
-
expect(matcher).to respond_to(:included_method)
|
209
|
-
end
|
210
|
-
|
211
|
-
it "does not run the module's extended hook" do
|
212
|
-
expect(matcher).not_to respond_to(:extended_method)
|
213
|
-
end
|
214
|
-
|
215
|
-
it 'allows multiple modules to be included at once' do
|
216
|
-
m = new_matcher(:multiple_modules) do
|
217
|
-
include Enumerable, Comparable
|
218
|
-
end
|
219
|
-
expect(m).to be_a(Enumerable)
|
220
|
-
expect(m).to be_a(Comparable)
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
|
-
context "without overrides" do
|
225
|
-
let(:matcher) do
|
226
|
-
new_matcher(:be_a_multiple_of, 3) do |multiple|
|
227
|
-
match do |actual|
|
228
|
-
actual % multiple == 0
|
229
|
-
end
|
230
|
-
end
|
231
|
-
end
|
232
|
-
|
233
|
-
it "provides a default description" do
|
234
|
-
expect(matcher.description).to eq "be a multiple of 3"
|
235
|
-
end
|
236
|
-
|
237
|
-
it "provides a default positive expectation failure message" do
|
238
|
-
matcher.matches?(8)
|
239
|
-
expect(matcher.failure_message).to eq "expected 8 to be a multiple of 3"
|
240
|
-
end
|
241
|
-
|
242
|
-
it "provides a default negative expectation failure message" do
|
243
|
-
matcher.matches?(9)
|
244
|
-
expect(matcher.failure_message_when_negated).to eq "expected 9 not to be a multiple of 3"
|
245
|
-
end
|
246
|
-
end
|
247
|
-
|
248
|
-
context "with separate match logic for positive and negative expectations" do
|
249
|
-
let(:matcher) do
|
250
|
-
new_matcher(:to_be_composed_of, 7, 11) do |a, b|
|
251
|
-
match do |actual|
|
252
|
-
actual == a * b
|
253
|
-
end
|
254
|
-
|
255
|
-
match_when_negated do |actual|
|
256
|
-
actual == a + b
|
257
|
-
end
|
258
|
-
end
|
259
|
-
end
|
260
|
-
|
261
|
-
it "invokes the match block for #matches?" do
|
262
|
-
expect(matcher.matches?(77)).to be_truthy
|
263
|
-
expect(matcher.matches?(18)).to be_falsey
|
264
|
-
end
|
265
|
-
|
266
|
-
it "invokes the match_when_negated block for #does_not_match?" do
|
267
|
-
expect(matcher.does_not_match?(77)).to be_falsey
|
268
|
-
expect(matcher.does_not_match?(18)).to be_truthy
|
269
|
-
end
|
270
|
-
|
271
|
-
it "provides a default failure message for negative expectations" do
|
272
|
-
matcher.does_not_match?(77)
|
273
|
-
expect(matcher.failure_message_when_negated).to eq "expected 77 not to to be composed of 7 and 11"
|
274
|
-
end
|
275
|
-
|
276
|
-
it 'can access helper methods from `match_when_negated`' do
|
277
|
-
matcher = new_matcher(:be_foo) do
|
278
|
-
def foo
|
279
|
-
:foo
|
280
|
-
end
|
281
|
-
|
282
|
-
match_when_negated do |actual|
|
283
|
-
actual != foo
|
284
|
-
end
|
285
|
-
end
|
286
|
-
|
287
|
-
expect(matcher.does_not_match?(:bar)).to be true
|
288
|
-
end
|
289
|
-
end
|
290
|
-
|
291
|
-
it "allows helper methods to be defined with #define_method to have access to matcher parameters" do
|
292
|
-
matcher = new_matcher(:name, 3, 4) do |a, b|
|
293
|
-
define_method(:sum) { a + b }
|
294
|
-
end
|
295
|
-
|
296
|
-
expect(matcher.sum).to eq 7
|
297
|
-
end
|
298
|
-
|
299
|
-
it "is not diffable by default" do
|
300
|
-
matcher = new_matcher(:name) { }
|
301
|
-
expect(matcher).not_to be_diffable
|
302
|
-
end
|
303
|
-
|
304
|
-
it "is diffable when told to be" do
|
305
|
-
matcher = new_matcher(:name) { diffable }
|
306
|
-
expect(matcher).to be_diffable
|
307
|
-
end
|
308
|
-
|
309
|
-
it 'handles multiline string diffs' do
|
310
|
-
actual = "LINE1\nline2\n"
|
311
|
-
expected = "line1\nline2\n"
|
312
|
-
|
313
|
-
matcher = new_matcher(:custom_match, expected) do
|
314
|
-
match { |actual| actual == expected }
|
315
|
-
diffable
|
316
|
-
end
|
317
|
-
|
318
|
-
diff = nil
|
319
|
-
begin
|
320
|
-
allow(RSpec::Matchers.configuration).to receive(:color?).and_return(false)
|
321
|
-
expect(actual).to matcher
|
322
|
-
rescue RSpec::Expectations::ExpectationNotMetError => e
|
323
|
-
diff = e.message.sub(/\A.*Diff:/m, "Diff:").gsub(/^\s*/,'')
|
324
|
-
end
|
325
|
-
|
326
|
-
expect(diff).to eq "Diff:\n@@ -1,3 +1,3 @@\n-line1\n+LINE1\nline2\n"
|
327
|
-
end
|
328
|
-
|
329
|
-
it 'does not confuse the diffability of different matchers' do
|
330
|
-
# Necessary to guard against a regression that involved
|
331
|
-
# using a class variable to store the diffable state,
|
332
|
-
# which had the side effect of causing all custom matchers
|
333
|
-
# to share that state
|
334
|
-
m1 = new_matcher(:m1) { diffable }
|
335
|
-
m2 = new_matcher(:m2) { }
|
336
|
-
m3 = new_matcher(:m3) { diffable }
|
337
|
-
|
338
|
-
expect(m1).to be_diffable
|
339
|
-
expect(m2).not_to be_diffable
|
340
|
-
expect(m3).to be_diffable
|
341
|
-
end
|
342
|
-
|
343
|
-
it "provides expected" do
|
344
|
-
matcher = new_matcher(:name, "expected string") { }
|
345
|
-
expect(matcher.expected).to eq 'expected string'
|
346
|
-
end
|
347
|
-
|
348
|
-
it "provides expected when there is more than one argument" do
|
349
|
-
matcher = new_matcher(:name, "expected string", "another arg") { }
|
350
|
-
expect(matcher.expected).to eq ['expected string', "another arg"]
|
351
|
-
end
|
352
|
-
|
353
|
-
it "provides expected_as_array which returns an array regardless of expected" do
|
354
|
-
matcher = new_matcher(:name, "expected string") { }
|
355
|
-
expect(matcher.expected_as_array).to eq ['expected string']
|
356
|
-
matcher = new_matcher(:name, "expected\nstring") { }
|
357
|
-
expect(matcher.expected_as_array).to eq ["expected\nstring"]
|
358
|
-
matcher = new_matcher(:name, "expected string", "another arg") { }
|
359
|
-
expect(matcher.expected_as_array).to eq ['expected string', "another arg"]
|
360
|
-
end
|
361
|
-
|
362
|
-
it "provides actual when `match` is used" do
|
363
|
-
matcher = new_matcher(:name, 'expected string') do
|
364
|
-
match {|actual|}
|
365
|
-
end
|
366
|
-
|
367
|
-
matcher.matches?('actual string')
|
368
|
-
|
369
|
-
expect(matcher.actual).to eq 'actual string'
|
370
|
-
end
|
371
|
-
|
372
|
-
it "provides actual when the `match` block accepts splat args" do
|
373
|
-
matcher = new_matcher(:actual) do
|
374
|
-
match { |*actual| actual == [5] }
|
375
|
-
end
|
376
|
-
|
377
|
-
expect(matcher.matches?(5)).to be true
|
378
|
-
expect(matcher.matches?(4)).to be false
|
379
|
-
end
|
380
|
-
|
381
|
-
it 'allows an early `return` to be used from a `match` block' do
|
382
|
-
matcher = new_matcher(:with_return, 5) do |expected|
|
383
|
-
match { |actual| return true if expected == actual }
|
384
|
-
end
|
385
|
-
|
386
|
-
expect(matcher.matches?(5)).to be true
|
387
|
-
expect(matcher.matches?(4)).to be_falsey
|
388
|
-
end
|
389
|
-
|
390
|
-
it 'provides actual when `match_unless_raises` is used' do
|
391
|
-
matcher = new_matcher(:name, 'expected string') do
|
392
|
-
match_unless_raises(SyntaxError) {|actual|}
|
393
|
-
end
|
394
|
-
|
395
|
-
matcher.matches?('actual string')
|
396
|
-
|
397
|
-
expect(matcher.actual).to eq 'actual string'
|
398
|
-
end
|
399
|
-
|
400
|
-
it 'allows an early `return` to be used from a `match_unless_raises` block' do
|
401
|
-
matcher = new_matcher(:with_return) do
|
402
|
-
match_unless_raises(ArgumentError) do |actual|
|
403
|
-
return actual if [true, false].include?(actual)
|
404
|
-
raise ArgumentError
|
405
|
-
end
|
406
|
-
end
|
407
|
-
|
408
|
-
expect(matcher.matches?(true)).to be true
|
409
|
-
# It should match even if it returns false, because no error was raised.
|
410
|
-
expect(matcher.matches?(false)).to be true
|
411
|
-
expect(matcher.matches?(4)).to be_falsey
|
412
|
-
end
|
413
|
-
|
414
|
-
it 'provides actual when `match_when_negated` is used' do
|
415
|
-
matcher = new_matcher(:name, 'expected string') do
|
416
|
-
match_when_negated {|actual|}
|
417
|
-
end
|
418
|
-
|
419
|
-
matcher.does_not_match?('actual string')
|
420
|
-
|
421
|
-
expect(matcher.actual).to eq 'actual string'
|
422
|
-
end
|
423
|
-
|
424
|
-
it 'allows an early `return` to be used from a `match_when_negated` block' do
|
425
|
-
matcher = new_matcher(:with_return, 5) do |expected|
|
426
|
-
match_when_negated { |actual| return true if expected != actual }
|
427
|
-
end
|
428
|
-
|
429
|
-
expect(matcher.does_not_match?(5)).to be_falsey
|
430
|
-
expect(matcher.does_not_match?(4)).to be true
|
431
|
-
end
|
432
|
-
|
433
|
-
context "wrapping another expectation (expect(...).to eq ...)" do
|
434
|
-
let(:matcher) do
|
435
|
-
new_matcher(:name, "value") do |expected|
|
436
|
-
match do |actual|
|
437
|
-
expect(actual).to eq expected
|
438
|
-
end
|
439
|
-
end
|
440
|
-
end
|
441
|
-
|
442
|
-
it "returns true if the wrapped expectation passes" do
|
443
|
-
expect(matcher.matches?('value')).to be_truthy
|
444
|
-
end
|
445
|
-
|
446
|
-
it "returns false if the wrapped expectation fails" do
|
447
|
-
expect(matcher.matches?('other value')).to be_falsey
|
448
|
-
end
|
449
|
-
|
450
|
-
it "can use the `include` matcher from a `match` block" do
|
451
|
-
RSpec::Matchers.define(:descend_from) do |mod|
|
452
|
-
match do |klass|
|
453
|
-
expect(klass.ancestors).to include(mod)
|
454
|
-
end
|
455
|
-
end
|
456
|
-
|
457
|
-
expect(Fixnum).to descend_from(Object)
|
458
|
-
expect(Fixnum).not_to descend_from(Array)
|
459
|
-
|
460
|
-
expect {
|
461
|
-
expect(Fixnum).to descend_from(Array)
|
462
|
-
}.to fail_with(/expected Fixnum to descend from Array/)
|
463
|
-
|
464
|
-
expect {
|
465
|
-
expect(Fixnum).not_to descend_from(Object)
|
466
|
-
}.to fail_with(/expected Fixnum not to descend from Object/)
|
467
|
-
end
|
468
|
-
|
469
|
-
it "can use the `match` matcher from a `match` block" do
|
470
|
-
RSpec::Matchers.define(:be_a_phone_number_string) do
|
471
|
-
match do |string|
|
472
|
-
expect(string).to match(/\A\d{3}\-\d{3}\-\d{4}\z/)
|
473
|
-
end
|
474
|
-
end
|
475
|
-
|
476
|
-
expect("206-123-1234").to be_a_phone_number_string
|
477
|
-
expect("foo").not_to be_a_phone_number_string
|
478
|
-
|
479
|
-
expect {
|
480
|
-
expect("foo").to be_a_phone_number_string
|
481
|
-
}.to fail_with(/expected "foo" to be a phone number string/)
|
482
|
-
|
483
|
-
expect {
|
484
|
-
expect("206-123-1234").not_to be_a_phone_number_string
|
485
|
-
}.to fail_with(/expected "206-123-1234" not to be a phone number string/)
|
486
|
-
end
|
487
|
-
end
|
488
|
-
|
489
|
-
context "with overrides" do
|
490
|
-
let(:matcher) do
|
491
|
-
new_matcher(:be_boolean, true) do |boolean|
|
492
|
-
match do |actual|
|
493
|
-
actual
|
494
|
-
end
|
495
|
-
description do |actual|
|
496
|
-
"be the boolean #{boolean} (actual was #{actual})"
|
497
|
-
end
|
498
|
-
failure_message do |actual|
|
499
|
-
"expected #{actual} to be the boolean #{boolean}"
|
500
|
-
end
|
501
|
-
failure_message_when_negated do |actual|
|
502
|
-
"expected #{actual} not to be the boolean #{boolean}"
|
503
|
-
end
|
504
|
-
end
|
505
|
-
end
|
506
|
-
|
507
|
-
it "does not hide result of match block when true" do
|
508
|
-
expect(matcher.matches?(true)).to be_truthy
|
509
|
-
end
|
510
|
-
|
511
|
-
it "does not hide result of match block when false" do
|
512
|
-
expect(matcher.matches?(false)).to be_falsey
|
513
|
-
end
|
514
|
-
|
515
|
-
it "overrides the description (which yields `actual`)" do
|
516
|
-
matcher.matches?(true)
|
517
|
-
expect(matcher.description).to eq "be the boolean true (actual was true)"
|
518
|
-
end
|
519
|
-
|
520
|
-
it "overrides the failure message for positive expectations" do
|
521
|
-
matcher.matches?(false)
|
522
|
-
expect(matcher.failure_message).to eq "expected false to be the boolean true"
|
523
|
-
end
|
524
|
-
|
525
|
-
it "overrides the failure message for negative expectations" do
|
526
|
-
matcher.matches?(true)
|
527
|
-
expect(matcher.failure_message_when_negated).to eq "expected true not to be the boolean true"
|
528
|
-
end
|
529
|
-
|
530
|
-
it 'can access helper methods from `description`' do
|
531
|
-
matcher = new_matcher(:desc) do
|
532
|
-
def subdesc() "sub description" end
|
533
|
-
description { "Desc (#{subdesc})" }
|
534
|
-
end
|
535
|
-
|
536
|
-
expect(matcher.description).to eq("Desc (sub description)")
|
537
|
-
end
|
538
|
-
|
539
|
-
it 'can access helper methods from `failure_message`' do
|
540
|
-
matcher = new_matcher(:positive_failure_message) do
|
541
|
-
def helper() "helper" end
|
542
|
-
failure_message { helper }
|
543
|
-
end
|
544
|
-
|
545
|
-
expect(matcher.failure_message).to eq("helper")
|
546
|
-
end
|
547
|
-
|
548
|
-
it 'can access helper methods from `failure_message_when_negated`' do
|
549
|
-
matcher = new_matcher(:negative_failure_message) do
|
550
|
-
def helper() "helper" end
|
551
|
-
failure_message_when_negated { helper }
|
552
|
-
end
|
553
|
-
|
554
|
-
expect(matcher.failure_message_when_negated).to eq("helper")
|
555
|
-
end
|
556
|
-
|
557
|
-
it 'can exit early with a `return` from `description` just like in a method' do
|
558
|
-
matcher = new_matcher(:desc) do
|
559
|
-
description { return "Desc" }
|
560
|
-
end
|
561
|
-
|
562
|
-
expect(matcher.description).to eq("Desc")
|
563
|
-
end
|
564
|
-
|
565
|
-
it 'can exit early with a `return` from `failure_message` just like in a method' do
|
566
|
-
matcher = new_matcher(:positive_failure_message) do
|
567
|
-
failure_message { return "msg" }
|
568
|
-
end
|
569
|
-
|
570
|
-
expect(matcher.failure_message).to eq("msg")
|
571
|
-
end
|
572
|
-
|
573
|
-
it 'can exit early with a `return` from `failure_message_when_negated` just like in a method' do
|
574
|
-
matcher = new_matcher(:negative_failure_message) do
|
575
|
-
failure_message_when_negated { return "msg" }
|
576
|
-
end
|
577
|
-
|
578
|
-
expect(matcher.failure_message_when_negated).to eq("msg")
|
579
|
-
end
|
580
|
-
end
|
581
|
-
|
582
|
-
context "#new" do
|
583
|
-
it "passes matches? arg to match block" do
|
584
|
-
matcher = new_matcher(:ignore) do
|
585
|
-
match do |actual|
|
586
|
-
actual == 5
|
587
|
-
end
|
588
|
-
end
|
589
|
-
expect(matcher.matches?(5)).to be_truthy
|
590
|
-
end
|
591
|
-
|
592
|
-
it "exposes arg submitted through #new to matcher block" do
|
593
|
-
matcher = new_matcher(:ignore, 4) do |expected|
|
594
|
-
match do |actual|
|
595
|
-
actual > expected
|
596
|
-
end
|
597
|
-
end
|
598
|
-
expect(matcher.matches?(5)).to be_truthy
|
599
|
-
end
|
600
|
-
end
|
601
|
-
|
602
|
-
context "with no args" do
|
603
|
-
let(:matcher) do
|
604
|
-
new_matcher(:matcher_name) do
|
605
|
-
match do |actual|
|
606
|
-
actual == 5
|
607
|
-
end
|
608
|
-
end
|
609
|
-
end
|
610
|
-
|
611
|
-
it "matches" do
|
612
|
-
expect(matcher.matches?(5)).to be_truthy
|
613
|
-
end
|
614
|
-
|
615
|
-
it "describes" do
|
616
|
-
expect(matcher.description).to eq "matcher name"
|
617
|
-
end
|
618
|
-
end
|
619
|
-
|
620
|
-
context "with 1 arg" do
|
621
|
-
let(:matcher) do
|
622
|
-
new_matcher(:matcher_name, 1) do |expected|
|
623
|
-
match do |actual|
|
624
|
-
actual == 5 && expected == 1
|
625
|
-
end
|
626
|
-
end
|
627
|
-
end
|
628
|
-
|
629
|
-
it "matches" do
|
630
|
-
expect(matcher.matches?(5)).to be_truthy
|
631
|
-
end
|
632
|
-
|
633
|
-
it "describes" do
|
634
|
-
expect(matcher.description).to eq "matcher name 1"
|
635
|
-
end
|
636
|
-
end
|
637
|
-
|
638
|
-
context "with multiple args" do
|
639
|
-
let(:matcher) do
|
640
|
-
new_matcher(:matcher_name, 1, 2, 3, 4) do |a, b, c, d|
|
641
|
-
match do |sum|
|
642
|
-
a + b + c + d == sum
|
643
|
-
end
|
644
|
-
end
|
645
|
-
end
|
646
|
-
|
647
|
-
it "matches" do
|
648
|
-
expect(matcher.matches?(10)).to be_truthy
|
649
|
-
end
|
650
|
-
|
651
|
-
it "describes" do
|
652
|
-
expect(matcher.description).to eq "matcher name 1, 2, 3, and 4"
|
653
|
-
end
|
654
|
-
end
|
655
|
-
|
656
|
-
it "supports helper methods" do
|
657
|
-
matcher = new_matcher(:be_similar_to, [1, 2, 3]) do |sample|
|
658
|
-
match do |actual|
|
659
|
-
similar?(sample, actual)
|
660
|
-
end
|
661
|
-
|
662
|
-
def similar?(a, b)
|
663
|
-
a.sort == b.sort
|
664
|
-
end
|
665
|
-
end
|
666
|
-
|
667
|
-
expect(matcher.matches?([2,3,1])).to be_truthy
|
668
|
-
end
|
669
|
-
|
670
|
-
it "supports fluent interface" do
|
671
|
-
matcher = new_matcher(:first_word) do
|
672
|
-
def second_word
|
673
|
-
self
|
674
|
-
end
|
675
|
-
end
|
676
|
-
|
677
|
-
expect(matcher.second_word).to eq matcher
|
678
|
-
end
|
679
|
-
|
680
|
-
it "treats method missing normally for undeclared methods" do
|
681
|
-
matcher = new_matcher(:ignore) { }
|
682
|
-
expect { matcher.non_existent_method }.to raise_error(NoMethodError)
|
683
|
-
end
|
684
|
-
|
685
|
-
it "has access to other matchers" do
|
686
|
-
matcher = new_matcher(:ignore, 3) do |expected|
|
687
|
-
match do |actual|
|
688
|
-
extend RSpec::Matchers
|
689
|
-
expect(actual).to eql(5 + expected)
|
690
|
-
end
|
691
|
-
end
|
692
|
-
|
693
|
-
expect(matcher.matches?(8)).to be_truthy
|
694
|
-
end
|
695
|
-
|
696
|
-
context 'when multiple instances of the same matcher are used in the same example' do
|
697
|
-
RSpec::Matchers.define(:be_like_a) do |expected|
|
698
|
-
match { |actual| actual == expected }
|
699
|
-
description { "be like a #{expected}" }
|
700
|
-
failure_message { "expected to be like a #{expected}" }
|
701
|
-
failure_message_when_negated { "expected not to be like a #{expected}" }
|
702
|
-
end
|
703
|
-
|
704
|
-
# Note: these bugs were only exposed when creating both instances
|
705
|
-
# first, then checking their descriptions/failure messages.
|
706
|
-
#
|
707
|
-
# That's why we eager-instantiate them here.
|
708
|
-
let!(:moose) { be_like_a("moose") }
|
709
|
-
let!(:horse) { be_like_a("horse") }
|
710
|
-
|
711
|
-
it 'allows them to use the expected value in the description' do
|
712
|
-
expect(horse.description).to eq("be like a horse")
|
713
|
-
expect(moose.description).to eq("be like a moose")
|
714
|
-
end
|
715
|
-
|
716
|
-
it 'allows them to use the expected value in the positive failure message' do
|
717
|
-
expect(moose.failure_message).to eq("expected to be like a moose")
|
718
|
-
expect(horse.failure_message).to eq("expected to be like a horse")
|
719
|
-
end
|
720
|
-
|
721
|
-
it 'allows them to use the expected value in the negative failure message' do
|
722
|
-
expect(moose.failure_message_when_negated).to eq("expected not to be like a moose")
|
723
|
-
expect(horse.failure_message_when_negated).to eq("expected not to be like a horse")
|
724
|
-
end
|
725
|
-
|
726
|
-
it 'allows them to match separately' do
|
727
|
-
expect("moose").to moose
|
728
|
-
expect("horse").to horse
|
729
|
-
expect("horse").not_to moose
|
730
|
-
expect("moose").not_to horse
|
731
|
-
end
|
732
|
-
end
|
733
|
-
|
734
|
-
describe "#match_unless_raises" do
|
735
|
-
context "with an assertion" do
|
736
|
-
mod = Module.new do
|
737
|
-
def assert_equal(a,b)
|
738
|
-
raise UnexpectedError.new("#{b} does not equal #{a}") unless a == b
|
739
|
-
end
|
740
|
-
end
|
741
|
-
|
742
|
-
let(:matcher) do
|
743
|
-
new_matcher(:equal, 4) do |expected|
|
744
|
-
include mod
|
745
|
-
match_unless_raises UnexpectedError do
|
746
|
-
assert_equal expected, actual
|
747
|
-
end
|
748
|
-
end
|
749
|
-
end
|
750
|
-
|
751
|
-
context "with passing assertion" do
|
752
|
-
it "passes" do
|
753
|
-
expect(matcher.matches?(4)).to be_truthy
|
754
|
-
end
|
755
|
-
end
|
756
|
-
|
757
|
-
context "with failing assertion" do
|
758
|
-
it "fails" do
|
759
|
-
expect(matcher.matches?(5)).to be_falsey
|
760
|
-
end
|
761
|
-
|
762
|
-
it "provides the raised exception" do
|
763
|
-
matcher.matches?(5)
|
764
|
-
expect(matcher.rescued_exception.message).to eq("5 does not equal 4")
|
765
|
-
end
|
766
|
-
end
|
767
|
-
end
|
768
|
-
|
769
|
-
context "with an unexpected error" do
|
770
|
-
let(:matcher) do
|
771
|
-
new_matcher(:foo, :bar) do |expected|
|
772
|
-
match_unless_raises SyntaxError do |actual|
|
773
|
-
raise "unexpected exception"
|
774
|
-
end
|
775
|
-
end
|
776
|
-
end
|
777
|
-
|
778
|
-
it "raises the error" do
|
779
|
-
expect {
|
780
|
-
matcher.matches?(:bar)
|
781
|
-
}.to raise_error("unexpected exception")
|
782
|
-
end
|
783
|
-
end
|
784
|
-
|
785
|
-
context "without a specified error class" do
|
786
|
-
let(:matcher) do
|
787
|
-
new_matcher(:foo) do
|
788
|
-
match_unless_raises do |actual|
|
789
|
-
raise Exception unless actual == 5
|
790
|
-
end
|
791
|
-
end
|
792
|
-
end
|
793
|
-
|
794
|
-
it 'passes if no error is raised' do
|
795
|
-
expect(matcher.matches?(5)).to be true
|
796
|
-
end
|
797
|
-
|
798
|
-
it 'fails if an exception is raised' do
|
799
|
-
expect(matcher.matches?(4)).to be false
|
800
|
-
end
|
801
|
-
end
|
802
|
-
|
803
|
-
end
|
804
|
-
|
805
|
-
it "can define chainable methods" do
|
806
|
-
matcher = new_matcher(:name) do
|
807
|
-
chain(:expecting) do |expected_value|
|
808
|
-
@expected_value = expected_value
|
809
|
-
end
|
810
|
-
match { |actual| actual == @expected_value }
|
811
|
-
end
|
812
|
-
|
813
|
-
expect(matcher.expecting('value').matches?('value')).to be_truthy
|
814
|
-
expect(matcher.expecting('value').matches?('other value')).to be_falsey
|
815
|
-
end
|
816
|
-
|
817
|
-
it 'can use an early return from a `chain` block' do
|
818
|
-
matcher = new_matcher(:name) do
|
819
|
-
chain(:expecting) do |expected_value|
|
820
|
-
@expected_value = expected_value
|
821
|
-
return
|
822
|
-
end
|
823
|
-
match { |actual| actual == @expected_value }
|
824
|
-
end
|
825
|
-
|
826
|
-
expect(matcher.expecting('value').matches?('value')).to be_truthy
|
827
|
-
expect(matcher.expecting('value').matches?('other value')).to be_falsey
|
828
|
-
end
|
829
|
-
|
830
|
-
it 'allows chainable methods to accept blocks' do
|
831
|
-
matcher = new_matcher(:name) do
|
832
|
-
chain(:for_block) { |&b| @block = b }
|
833
|
-
match { |value| @block.call == value }
|
834
|
-
end
|
835
|
-
|
836
|
-
expect(matcher.for_block { 5 }.matches?(5)).to be true
|
837
|
-
expect(matcher.for_block { 3 }.matches?(4)).to be false
|
838
|
-
end
|
839
|
-
|
840
|
-
it "prevents name collisions on chainable methods from different matchers" do
|
841
|
-
m1 = new_matcher(:m1) { chain(:foo) { raise "foo in m1" } }
|
842
|
-
m2 = new_matcher(:m2) { chain(:foo) { raise "foo in m2" } }
|
843
|
-
|
844
|
-
expect { m1.foo }.to raise_error("foo in m1")
|
845
|
-
expect { m2.foo }.to raise_error("foo in m2")
|
846
|
-
end
|
847
|
-
|
848
|
-
context "defined using the dsl" do
|
849
|
-
def a_method_in_the_example
|
850
|
-
"method defined in the example"
|
851
|
-
end
|
852
|
-
|
853
|
-
it "can access methods in the running example" do |example|
|
854
|
-
RSpec::Matchers.define(:__access_running_example) do
|
855
|
-
match do |actual|
|
856
|
-
a_method_in_the_example == "method defined in the example"
|
857
|
-
end
|
858
|
-
end
|
859
|
-
expect(example).to __access_running_example
|
860
|
-
end
|
861
|
-
|
862
|
-
it 'can get a method object for methods in the running example', :if => (RUBY_VERSION.to_f > 1.8) do
|
863
|
-
matcher = new_matcher(:get_method_object) { }
|
864
|
-
method = matcher.method(:a_method_in_the_example)
|
865
|
-
expect(method.call).to eq("method defined in the example")
|
866
|
-
end
|
867
|
-
|
868
|
-
it 'indicates that it responds to a method from the running example' do
|
869
|
-
matcher = new_matcher(:respond_to) { }
|
870
|
-
expect(matcher).to respond_to(:a_method_in_the_example)
|
871
|
-
expect(matcher).not_to respond_to(:a_method_not_in_the_example)
|
872
|
-
end
|
873
|
-
|
874
|
-
it "raises NoMethodError for methods not in the running_example" do |example|
|
875
|
-
RSpec::Matchers.define(:__raise_no_method_error) do
|
876
|
-
match do |actual|
|
877
|
-
self.a_method_not_in_the_example == "method defined in the example"
|
878
|
-
end
|
879
|
-
end
|
880
|
-
|
881
|
-
expected_msg = "RSpec::Matchers::DSL::Matcher"
|
882
|
-
expected_msg << " __raise_no_method_error" unless rbx?
|
883
|
-
|
884
|
-
expect {
|
885
|
-
expect(example).to __raise_no_method_error
|
886
|
-
}.to raise_error(NoMethodError, /#{expected_msg}/)
|
887
|
-
end
|
888
|
-
|
889
|
-
def rbx?
|
890
|
-
defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
|
891
|
-
end
|
892
|
-
end
|
893
|
-
|
894
|
-
end
|
895
|
-
end
|