rspec-expectations 2.9.1 → 2.10.0
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.
- data/.yardopts +4 -1
- data/Changelog.md +19 -1
- data/README.md +23 -0
- data/features/{README.markdown → README.md} +0 -0
- data/features/built_in_matchers/be_within.feature +14 -11
- data/features/built_in_matchers/end_with.feature +46 -0
- data/features/built_in_matchers/start_with.feature +46 -0
- data/features/built_in_matchers/yield.feature +146 -0
- data/lib/rspec/expectations/version.rb +1 -1
- data/lib/rspec/matchers.rb +110 -0
- data/lib/rspec/matchers/built_in.rb +6 -0
- data/lib/rspec/matchers/built_in/base_matcher.rb +5 -4
- data/lib/rspec/matchers/built_in/be_within.rb +1 -1
- data/lib/rspec/matchers/built_in/start_and_end_with.rb +50 -0
- data/lib/rspec/matchers/built_in/yield.rb +222 -0
- data/lib/rspec/matchers/dsl.rb +1 -1
- data/lib/rspec/matchers/matcher.rb +3 -3
- data/spec/rspec/matchers/base_matcher_spec.rb +8 -2
- data/spec/rspec/matchers/be_within_spec.rb +4 -4
- data/spec/rspec/matchers/have_spec.rb +1 -1
- data/spec/rspec/matchers/raise_error_spec.rb +8 -8
- data/spec/rspec/matchers/start_with_end_with_spec.rb +174 -0
- data/spec/rspec/matchers/yield_spec.rb +374 -0
- metadata +21 -8
@@ -24,8 +24,14 @@ module RSpec
|
|
24
24
|
autoload :MatchArray, 'rspec/matchers/built_in/match_array'
|
25
25
|
autoload :RaiseError, 'rspec/matchers/built_in/raise_error'
|
26
26
|
autoload :RespondTo, 'rspec/matchers/built_in/respond_to'
|
27
|
+
autoload :StartWith, 'rspec/matchers/built_in/start_and_end_with'
|
28
|
+
autoload :EndWith, 'rspec/matchers/built_in/start_and_end_with'
|
27
29
|
autoload :Satisfy, 'rspec/matchers/built_in/satisfy'
|
28
30
|
autoload :ThrowSymbol, 'rspec/matchers/built_in/throw_symbol'
|
31
|
+
autoload :YieldControl, 'rspec/matchers/built_in/yield'
|
32
|
+
autoload :YieldWithArgs, 'rspec/matchers/built_in/yield'
|
33
|
+
autoload :YieldWithNoArgs, 'rspec/matchers/built_in/yield'
|
34
|
+
autoload :YieldSuccessiveArgs, 'rspec/matchers/built_in/yield'
|
29
35
|
end
|
30
36
|
end
|
31
37
|
end
|
@@ -24,13 +24,14 @@ module RSpec
|
|
24
24
|
@actual = actual
|
25
25
|
end
|
26
26
|
|
27
|
-
def match_unless_raises(
|
27
|
+
def match_unless_raises(*exceptions)
|
28
|
+
exceptions.unshift Exception if exceptions.empty?
|
28
29
|
begin
|
29
30
|
yield
|
30
|
-
|
31
|
-
|
32
|
-
false
|
31
|
+
rescue *exceptions => @rescued_exception
|
32
|
+
return false
|
33
33
|
end
|
34
|
+
true
|
34
35
|
end
|
35
36
|
|
36
37
|
def failure_message_for_should
|
@@ -14,7 +14,7 @@ module RSpec
|
|
14
14
|
unless defined?(@expected)
|
15
15
|
raise ArgumentError.new("You must set an expected value using #of: be_within(#{delta}).of(expected_value)")
|
16
16
|
end
|
17
|
-
(super(actual) - expected).abs
|
17
|
+
(super(actual) - expected).abs <= delta
|
18
18
|
end
|
19
19
|
|
20
20
|
def of(expected)
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Matchers
|
3
|
+
module BuiltIn
|
4
|
+
class StartAndEndWith
|
5
|
+
include BaseMatcher
|
6
|
+
|
7
|
+
def initialize(*expected)
|
8
|
+
@expected = expected.length == 1 ? expected.first : expected
|
9
|
+
end
|
10
|
+
|
11
|
+
def matches?(actual)
|
12
|
+
@actual = actual.respond_to?(:[]) ? actual : (raise ArgumentError.new("#{actual.inspect} does not respond to :[]"))
|
13
|
+
begin
|
14
|
+
@expected.respond_to?(:length) ? subset_matches?(@expected, @actual) : element_matches?(@expected, @actual)
|
15
|
+
rescue ArgumentError
|
16
|
+
raise ArgumentError.new("#{actual.inspect} does not have ordered elements")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def failure_message_for_should
|
21
|
+
"expected #{@actual.inspect} to #{self.class.name.split('::').last.sub(/With/,'').downcase} with #{@expected.inspect}"
|
22
|
+
end
|
23
|
+
|
24
|
+
def failure_message_for_should_not
|
25
|
+
"expected #{@actual.inspect} not to #{self.class.name.split('::').last.sub(/With/,'').downcase} with #{@expected.inspect}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class StartWith < StartAndEndWith
|
30
|
+
def subset_matches?(expected, actual)
|
31
|
+
actual[0, expected.length] == expected
|
32
|
+
end
|
33
|
+
|
34
|
+
def element_matches?(expected, actual)
|
35
|
+
@actual[0] == @expected
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class EndWith < StartAndEndWith
|
40
|
+
def subset_matches?(expected, actual)
|
41
|
+
actual[-expected.length, expected.length] == expected
|
42
|
+
end
|
43
|
+
|
44
|
+
def element_matches?(expected, actual)
|
45
|
+
actual[-1] == expected
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,222 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Matchers
|
3
|
+
module BuiltIn
|
4
|
+
class YieldProbe
|
5
|
+
def self.probe(block)
|
6
|
+
probe = new
|
7
|
+
assert_valid_expect_block!(block)
|
8
|
+
block.call(probe)
|
9
|
+
probe.assert_used!
|
10
|
+
probe
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_accessor :num_yields, :yielded_args
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@used = false
|
17
|
+
self.num_yields, self.yielded_args = 0, []
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_proc
|
21
|
+
@used = true
|
22
|
+
|
23
|
+
probe = self
|
24
|
+
Proc.new do |*args|
|
25
|
+
probe.num_yields += 1
|
26
|
+
probe.yielded_args << args
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def single_yield_args
|
31
|
+
yielded_args.first
|
32
|
+
end
|
33
|
+
|
34
|
+
def yielded_once?(matcher_name)
|
35
|
+
case num_yields
|
36
|
+
when 1 then true
|
37
|
+
when 0 then false
|
38
|
+
else
|
39
|
+
raise "The #{matcher_name} matcher is not designed to be used with a " +
|
40
|
+
"method that yields multiple times. Use the yield_successive_args " +
|
41
|
+
"matcher for that case."
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def successive_yield_args
|
46
|
+
yielded_args.map do |arg_array|
|
47
|
+
arg_array.size == 1 ? arg_array.first : arg_array
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def assert_used!
|
52
|
+
return if @used
|
53
|
+
raise "You must pass the argument yielded to your expect block on " +
|
54
|
+
"to the method-under-test as a block. It acts as a probe that " +
|
55
|
+
"allows the matcher to detect whether or not the method-under-test " +
|
56
|
+
"yields, and, if so, how many times, and what the yielded arguments " +
|
57
|
+
"are."
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.assert_valid_expect_block!(block)
|
61
|
+
return if block.arity == 1
|
62
|
+
raise "Your expect block must accept an argument to be used with this " +
|
63
|
+
"matcher. Pass the argument as a block on to the method you are testing."
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
class YieldControl
|
68
|
+
include BaseMatcher
|
69
|
+
|
70
|
+
def matches?(block)
|
71
|
+
probe = YieldProbe.probe(block)
|
72
|
+
probe.yielded_once?(:yield_control)
|
73
|
+
end
|
74
|
+
|
75
|
+
def failure_message_for_should
|
76
|
+
"expected given block to yield control"
|
77
|
+
end
|
78
|
+
|
79
|
+
def failure_message_for_should_not
|
80
|
+
"expected given block not to yield control"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
class YieldWithNoArgs
|
85
|
+
include BaseMatcher
|
86
|
+
|
87
|
+
def matches?(block)
|
88
|
+
@probe = YieldProbe.probe(block)
|
89
|
+
@probe.yielded_once?(:yield_with_no_args) && @probe.single_yield_args.none?
|
90
|
+
end
|
91
|
+
|
92
|
+
def failure_message_for_should
|
93
|
+
"expected given block to yield with no arguments, but #{failure_reason}"
|
94
|
+
end
|
95
|
+
|
96
|
+
def failure_message_for_should_not
|
97
|
+
"expected given block not to yield with no arguments, but did"
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
def failure_reason
|
103
|
+
if @probe.num_yields.zero?
|
104
|
+
"did not yield"
|
105
|
+
else
|
106
|
+
"yielded with arguments: #{@probe.single_yield_args.inspect}"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
class YieldWithArgs
|
112
|
+
def initialize(*args)
|
113
|
+
@expected = args
|
114
|
+
end
|
115
|
+
|
116
|
+
def matches?(block)
|
117
|
+
@probe = YieldProbe.probe(block)
|
118
|
+
@actual = @probe.single_yield_args
|
119
|
+
@probe.yielded_once?(:yield_with_args) && args_match?
|
120
|
+
end
|
121
|
+
|
122
|
+
def failure_message_for_should
|
123
|
+
"expected given block to yield with arguments, but #{positive_failure_reason}"
|
124
|
+
end
|
125
|
+
|
126
|
+
def failure_message_for_should_not
|
127
|
+
"expected given block not to yield with arguments, but #{negative_failure_reason}"
|
128
|
+
end
|
129
|
+
|
130
|
+
def description
|
131
|
+
desc = "yield with args"
|
132
|
+
desc << "(" + @expected.map { |e| e.inspect }.join(", ") + ")" if @expected.any?
|
133
|
+
desc
|
134
|
+
end
|
135
|
+
|
136
|
+
private
|
137
|
+
|
138
|
+
def positive_failure_reason
|
139
|
+
if @probe.num_yields.zero?
|
140
|
+
"did not yield"
|
141
|
+
else
|
142
|
+
@positive_args_failure
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def negative_failure_reason
|
147
|
+
if all_args_match?
|
148
|
+
"yielded with expected arguments" +
|
149
|
+
"\nexpected not: #{@expected.inspect}" +
|
150
|
+
"\n got: #{@actual.inspect} (compared using === and ==)"
|
151
|
+
else
|
152
|
+
"did"
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def args_match?
|
157
|
+
if @expected.none? # expect {...}.to yield_with_args
|
158
|
+
@positive_args_failure = "yielded with no arguments" if @actual.none?
|
159
|
+
return @actual.any?
|
160
|
+
end
|
161
|
+
|
162
|
+
unless match = all_args_match?
|
163
|
+
@positive_args_failure = "yielded with unexpected arguments" +
|
164
|
+
"\nexpected: #{@expected.inspect}" +
|
165
|
+
"\n got: #{@actual.inspect} (compared using === and ==)"
|
166
|
+
end
|
167
|
+
|
168
|
+
match
|
169
|
+
end
|
170
|
+
|
171
|
+
def all_args_match?
|
172
|
+
return false if @expected.size != @actual.size
|
173
|
+
|
174
|
+
@expected.zip(@actual).all? do |expected, actual|
|
175
|
+
expected === actual || actual == expected
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
class YieldSuccessiveArgs
|
181
|
+
def initialize(*args)
|
182
|
+
@expected = args
|
183
|
+
end
|
184
|
+
|
185
|
+
def matches?(block)
|
186
|
+
@probe = YieldProbe.probe(block)
|
187
|
+
@actual = @probe.successive_yield_args
|
188
|
+
args_match?
|
189
|
+
end
|
190
|
+
|
191
|
+
def failure_message_for_should
|
192
|
+
"expected given block to yield successively with arguments, but yielded with unexpected arguments" +
|
193
|
+
"\nexpected: #{@expected.inspect}" +
|
194
|
+
"\n got: #{@actual.inspect} (compared using === and ==)"
|
195
|
+
end
|
196
|
+
|
197
|
+
def failure_message_for_should_not
|
198
|
+
"expected given block not to yield successively with arguments, but yielded with expected arguments" +
|
199
|
+
"\nexpected not: #{@expected.inspect}" +
|
200
|
+
"\n got: #{@actual.inspect} (compared using === and ==)"
|
201
|
+
end
|
202
|
+
|
203
|
+
def description
|
204
|
+
desc = "yield successive args"
|
205
|
+
desc << "(" + @expected.map { |e| e.inspect }.join(", ") + ")"
|
206
|
+
desc
|
207
|
+
end
|
208
|
+
|
209
|
+
private
|
210
|
+
|
211
|
+
def args_match?
|
212
|
+
return false if @expected.size != @actual.size
|
213
|
+
|
214
|
+
@expected.zip(@actual).all? do |expected, actual|
|
215
|
+
expected === actual || actual == expected
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
data/lib/rspec/matchers/dsl.rb
CHANGED
@@ -7,7 +7,7 @@ module RSpec
|
|
7
7
|
matcher_template = RSpec::Matchers::DSL::Matcher.new(name, &declarations)
|
8
8
|
define_method name do |*expected|
|
9
9
|
matcher = matcher_template.for_expected(*expected)
|
10
|
-
matcher.matcher_execution_context = @matcher_execution_context
|
10
|
+
matcher.matcher_execution_context = @matcher_execution_context ||= self
|
11
11
|
matcher
|
12
12
|
end
|
13
13
|
end
|
@@ -223,14 +223,14 @@ module RSpec
|
|
223
223
|
end
|
224
224
|
|
225
225
|
def respond_to?(method, include_private=false)
|
226
|
-
super ||
|
226
|
+
super || matcher_execution_context.respond_to?(method, include_private)
|
227
227
|
end
|
228
228
|
|
229
229
|
private
|
230
230
|
|
231
231
|
def method_missing(method, *args, &block)
|
232
|
-
if
|
233
|
-
|
232
|
+
if matcher_execution_context.respond_to?(method)
|
233
|
+
matcher_execution_context.send method, *args, &block
|
234
234
|
else
|
235
235
|
super(method, *args, &block)
|
236
236
|
end
|
@@ -15,11 +15,17 @@ module RSpec::Matchers::BuiltIn
|
|
15
15
|
matcher.match_unless_raises { raise }.should be_false
|
16
16
|
end
|
17
17
|
|
18
|
-
it "returns false if the submitted error is raised" do
|
18
|
+
it "returns false if the only submitted error is raised" do
|
19
19
|
matcher.match_unless_raises(RuntimeError){ raise "foo" }.should be_false
|
20
20
|
end
|
21
21
|
|
22
|
-
it "
|
22
|
+
it "returns false if any of several errors submitted is raised" do
|
23
|
+
matcher.match_unless_raises(RuntimeError, ArgumentError, NameError) { raise "foo" }.should be_false
|
24
|
+
matcher.match_unless_raises(RuntimeError, ArgumentError, NameError) { raise ArgumentError.new('') }.should be_false
|
25
|
+
matcher.match_unless_raises(RuntimeError, ArgumentError, NameError) { raise NameError.new('') }.should be_false
|
26
|
+
end
|
27
|
+
|
28
|
+
it "re-raises any error other than one of those specified" do
|
23
29
|
expect do
|
24
30
|
matcher.match_unless_raises(ArgumentError){ raise "foo" }
|
25
31
|
end.to raise_error
|
@@ -15,16 +15,16 @@ module RSpec
|
|
15
15
|
be_within(0.5).of(5.0).matches?(4.51).should be_true
|
16
16
|
end
|
17
17
|
|
18
|
-
it "
|
19
|
-
be_within(0.5).of(5.0).matches?(4.5).should
|
18
|
+
it "matches when actual == (expected - delta)" do
|
19
|
+
be_within(0.5).of(5.0).matches?(4.5).should be_true
|
20
20
|
end
|
21
21
|
|
22
22
|
it "does not match when actual < (expected - delta)" do
|
23
23
|
be_within(0.5).of(5.0).matches?(4.49).should be_false
|
24
24
|
end
|
25
25
|
|
26
|
-
it "
|
27
|
-
be_within(0.5).of(5.0).matches?(5.5).should
|
26
|
+
it "matches when actual == (expected + delta)" do
|
27
|
+
be_within(0.5).of(5.0).matches?(5.5).should be_true
|
28
28
|
end
|
29
29
|
|
30
30
|
it "does not match when actual > (expected + delta)" do
|
@@ -386,7 +386,7 @@ EOF
|
|
386
386
|
|
387
387
|
describe "have(n).things on an object which is not a collection nor contains one" do
|
388
388
|
it "fails" do
|
389
|
-
lambda { Object.new.should have(2).things }.should raise_error(NoMethodError
|
389
|
+
lambda { Object.new.should have(2).things }.should raise_error(NoMethodError) {|e| e.name.should eq :things }
|
390
390
|
end
|
391
391
|
end
|
392
392
|
|
@@ -43,8 +43,8 @@ describe "should_not raise_error" do
|
|
43
43
|
|
44
44
|
it "fails if anything is raised" do
|
45
45
|
lambda {
|
46
|
-
lambda {raise}.should_not raise_error
|
47
|
-
}.should fail_with("expected no Exception, got RuntimeError")
|
46
|
+
lambda { raise RuntimeError, "example message" }.should_not raise_error
|
47
|
+
}.should fail_with("expected no Exception, got #<RuntimeError: example message>")
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
@@ -102,8 +102,8 @@ describe "should raise_error(NamedError)" do
|
|
102
102
|
|
103
103
|
it "fails if another error is raised (NameError)" do
|
104
104
|
lambda {
|
105
|
-
lambda { raise }.should raise_error(NameError)
|
106
|
-
}.should fail_with("expected NameError, got RuntimeError")
|
105
|
+
lambda { raise RuntimeError, "example message" }.should raise_error(NameError)
|
106
|
+
}.should fail_with("expected NameError, got #<RuntimeError: example message>")
|
107
107
|
end
|
108
108
|
|
109
109
|
it "fails if another error is raised (NameError)" do
|
@@ -142,8 +142,8 @@ describe "should raise_error(NamedError, error_message) with String" do
|
|
142
142
|
|
143
143
|
it "fails if incorrect error is raised" do
|
144
144
|
lambda {
|
145
|
-
lambda { raise }.should raise_error(NameError, "example message")
|
146
|
-
}.should fail_with("expected NameError with \"example message\", got RuntimeError")
|
145
|
+
lambda { raise RuntimeError, "example message" }.should raise_error(NameError, "example message")
|
146
|
+
}.should fail_with("expected NameError with \"example message\", got #<RuntimeError: example message>")
|
147
147
|
end
|
148
148
|
|
149
149
|
it "fails if correct error is raised with incorrect message" do
|
@@ -307,8 +307,8 @@ describe "should raise_error(NamedError, error_message) with Regexp" do
|
|
307
307
|
|
308
308
|
it "fails if incorrect error is raised" do
|
309
309
|
lambda {
|
310
|
-
lambda { raise }.should raise_error(NameError, /ample mess/)
|
311
|
-
}.should fail_with("expected NameError with message matching /ample mess/, got RuntimeError")
|
310
|
+
lambda { raise RuntimeError, "example message" }.should raise_error(NameError, /ample mess/)
|
311
|
+
}.should fail_with("expected NameError with message matching /ample mess/, got #<RuntimeError: example message>")
|
312
312
|
end
|
313
313
|
|
314
314
|
it "fails if correct error is raised with incorrect message" do
|
@@ -0,0 +1,174 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "should start_with" do
|
4
|
+
context "with a string" do
|
5
|
+
it "passes if it matches the start of the actual string" do
|
6
|
+
"this string".should start_with "this str"
|
7
|
+
end
|
8
|
+
|
9
|
+
it "fails if it does not match the start of the actual string" do
|
10
|
+
expect {
|
11
|
+
"this string".should start_with "that str"
|
12
|
+
}.to fail_with("expected \"this string\" to start with \"that str\"")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context "with an array" do
|
17
|
+
it "passes if it is the first element of the array" do
|
18
|
+
[0, 1, 2].should start_with 0
|
19
|
+
end
|
20
|
+
|
21
|
+
it "passes if the first elements of the array match" do
|
22
|
+
[0, 1, 2].should start_with 0, 1
|
23
|
+
end
|
24
|
+
|
25
|
+
it "fails if it does not match the first element of the array" do
|
26
|
+
expect {
|
27
|
+
[0, 1, 2].should start_with 2
|
28
|
+
}.to fail_with("expected [0, 1, 2] to start with 2")
|
29
|
+
end
|
30
|
+
|
31
|
+
it "fails if it the first elements of the array do not match" do
|
32
|
+
expect {
|
33
|
+
[0, 1, 2].should start_with 1, 2
|
34
|
+
}.to fail_with("expected [0, 1, 2] to start with [1, 2]")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context "with an object that does not respond to :[]" do
|
39
|
+
it "raises an ArgumentError" do
|
40
|
+
expect { Object.new.should start_with 0 }.to raise_error(ArgumentError, /does not respond to :\[\]/)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context "with a hash" do
|
45
|
+
it "raises an ArgumentError if trying to match more than one element" do
|
46
|
+
expect{
|
47
|
+
{:a => 'b', :b => 'b', :c => 'c'}.should start_with({:a => 'b', :b => 'b'})
|
48
|
+
}.to raise_error(ArgumentError, /does not have ordered elements/)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "should_not start_with" do
|
54
|
+
context "with a string" do
|
55
|
+
it "passes if it does not match the start of the actual string" do
|
56
|
+
"this string".should_not start_with "that str"
|
57
|
+
end
|
58
|
+
|
59
|
+
it "fails if it does match the start of the actual string" do
|
60
|
+
expect {
|
61
|
+
"this string".should_not start_with "this str"
|
62
|
+
}.to fail_with("expected \"this string\" not to start with \"this str\"")
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context "with an array" do
|
67
|
+
it "passes if it is not the first element of the array" do
|
68
|
+
[0, 1, 2].should_not start_with 2
|
69
|
+
end
|
70
|
+
|
71
|
+
it "passes if the first elements of the array do not match" do
|
72
|
+
[0, 1, 2].should_not start_with 1, 2
|
73
|
+
end
|
74
|
+
|
75
|
+
it "fails if it matches the first element of the array" do
|
76
|
+
expect {
|
77
|
+
[0, 1, 2].should_not start_with 0
|
78
|
+
}.to fail_with("expected [0, 1, 2] not to start with 0")
|
79
|
+
end
|
80
|
+
|
81
|
+
it "fails if it the first elements of the array match" do
|
82
|
+
expect {
|
83
|
+
[0, 1, 2].should_not start_with 0, 1
|
84
|
+
}.to fail_with("expected [0, 1, 2] not to start with [0, 1]")
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe "should end_with" do
|
90
|
+
context "with a string" do
|
91
|
+
it "passes if it matches the end of the actual string" do
|
92
|
+
"this string".should end_with "is string"
|
93
|
+
end
|
94
|
+
|
95
|
+
it "fails if it does not match the end of the actual string" do
|
96
|
+
expect {
|
97
|
+
"this string".should end_with "is stringy"
|
98
|
+
}.to fail_with("expected \"this string\" to end with \"is stringy\"")
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
context "with an array" do
|
103
|
+
it "passes if it is the last element of the array" do
|
104
|
+
[0, 1, 2].should end_with 2
|
105
|
+
end
|
106
|
+
|
107
|
+
it "passes if the last elements of the array match" do
|
108
|
+
[0, 1, 2].should end_with [1, 2]
|
109
|
+
end
|
110
|
+
|
111
|
+
it "fails if it does not match the last element of the array" do
|
112
|
+
expect {
|
113
|
+
[0, 1, 2].should end_with 1
|
114
|
+
}.to fail_with("expected [0, 1, 2] to end with 1")
|
115
|
+
end
|
116
|
+
|
117
|
+
it "fails if it the last elements of the array do not match" do
|
118
|
+
expect {
|
119
|
+
[0, 1, 2].should end_with [0, 1]
|
120
|
+
}.to fail_with("expected [0, 1, 2] to end with [0, 1]")
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
context "with an object that does not respond to :[]" do
|
125
|
+
it "should raise an error if expected value can't be indexed'" do
|
126
|
+
expect { Object.new.should end_with 0 }.to raise_error(ArgumentError, /does not respond to :\[\]/)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
context "with a hash" do
|
131
|
+
it "raises an ArgumentError if trying to match more than one element" do
|
132
|
+
expect{
|
133
|
+
{:a => 'b', :b => 'b', :c => 'c'}.should end_with({:a => 'b', :b =>'b'})
|
134
|
+
}.to raise_error(ArgumentError, /does not have ordered elements/)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
|
140
|
+
describe "should_not end_with" do
|
141
|
+
context "with a sting" do
|
142
|
+
it "passes if it does not match the end of the actual string" do
|
143
|
+
"this string".should_not end_with "stringy"
|
144
|
+
end
|
145
|
+
|
146
|
+
it "fails if it matches the end of the actual string" do
|
147
|
+
expect {
|
148
|
+
"this string".should_not end_with "string"
|
149
|
+
}.to fail_with("expected \"this string\" not to end with \"string\"")
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
context "an array" do
|
154
|
+
it "passes if it is not the last element of the array" do
|
155
|
+
[0, 1, 2].should_not end_with 1
|
156
|
+
end
|
157
|
+
|
158
|
+
it "passes if the last elements of the array do not match" do
|
159
|
+
[0, 1, 2].should_not end_with [0, 1]
|
160
|
+
end
|
161
|
+
|
162
|
+
it "fails if it matches the last element of the array" do
|
163
|
+
expect {
|
164
|
+
[0, 1, 2].should_not end_with 2
|
165
|
+
}.to fail_with("expected [0, 1, 2] not to end with 2")
|
166
|
+
end
|
167
|
+
|
168
|
+
it "fails if it the last elements of the array match" do
|
169
|
+
expect {
|
170
|
+
[0, 1, 2].should_not end_with [1, 2]
|
171
|
+
}.to fail_with("expected [0, 1, 2] not to end with [1, 2]")
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|