rspec-expectations 2.5.0 → 2.6.0.rc2

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.
Files changed (48) hide show
  1. data/.travis.yml +7 -0
  2. data/Gemfile +13 -11
  3. data/README.md +2 -0
  4. data/Rakefile +28 -17
  5. data/features/Changelog.md +16 -0
  6. data/features/built_in_matchers/be.feature +4 -4
  7. data/features/built_in_matchers/be_within.feature +1 -1
  8. data/features/built_in_matchers/equality.feature +5 -5
  9. data/features/built_in_matchers/exist.feature +1 -1
  10. data/features/built_in_matchers/expect_change.feature +2 -2
  11. data/features/built_in_matchers/expect_error.feature +7 -7
  12. data/features/built_in_matchers/have.feature +2 -2
  13. data/features/built_in_matchers/include.feature +3 -3
  14. data/features/built_in_matchers/match.feature +2 -2
  15. data/features/built_in_matchers/operators.feature +3 -3
  16. data/features/built_in_matchers/predicates.feature +5 -5
  17. data/features/built_in_matchers/respond_to.feature +2 -2
  18. data/features/built_in_matchers/satisfy.feature +1 -1
  19. data/features/built_in_matchers/throw_symbol.feature +3 -3
  20. data/features/built_in_matchers/types.feature +2 -2
  21. data/features/custom_matchers/access_running_example.feature +2 -2
  22. data/features/custom_matchers/define_diffable_matcher.feature +1 -1
  23. data/features/custom_matchers/define_matcher.feature +40 -11
  24. data/features/custom_matchers/define_matcher_outside_rspec.feature +1 -1
  25. data/features/custom_matchers/define_matcher_with_fluent_interface.feature +1 -1
  26. data/features/customized_message.feature +1 -1
  27. data/features/diffing.feature +4 -4
  28. data/features/implicit_docstrings.feature +2 -2
  29. data/features/step_definitions/additional_cli_steps.rb +2 -2
  30. data/features/support/env.rb +5 -1
  31. data/features/test_frameworks/test_unit.feature +1 -1
  32. data/lib/rspec/expectations/backward_compatibility.rb +22 -1
  33. data/lib/rspec/expectations/version.rb +1 -1
  34. data/lib/rspec/matchers.rb +10 -5
  35. data/lib/rspec/matchers/change.rb +47 -32
  36. data/lib/rspec/matchers/has.rb +15 -11
  37. data/lib/rspec/matchers/matcher.rb +4 -0
  38. data/spec/rspec/matchers/be_spec.rb +0 -4
  39. data/spec/rspec/matchers/change_spec.rb +84 -9
  40. data/spec/rspec/matchers/description_generation_spec.rb +41 -25
  41. data/spec/rspec/matchers/has_spec.rb +2 -2
  42. data/spec/rspec/matchers/have_spec.rb +21 -21
  43. data/spec/rspec/matchers/matcher_spec.rb +46 -0
  44. data/spec/rspec/matchers/matchers_spec.rb +3 -23
  45. data/spec/rspec/matchers/method_missing_spec.rb +23 -0
  46. data/spec/spec_helper.rb +2 -0
  47. metadata +23 -18
  48. data/spec/suite.rb +0 -1
@@ -41,7 +41,7 @@ Feature: respond_to matcher
41
41
  it { should_not respond_to(:length, :flatten) }
42
42
  end
43
43
  """
44
- When I run "rspec respond_to_matcher_spec.rb"
44
+ When I run `rspec respond_to_matcher_spec.rb`
45
45
  Then the output should contain all of these:
46
46
  | 10 examples, 6 failures |
47
47
  | expected "a string" to respond to :to_model |
@@ -69,7 +69,7 @@ Feature: respond_to matcher
69
69
  it { should_not respond_to(:between?).with(2).arguments }
70
70
  end
71
71
  """
72
- When I run "rspec respond_to_matcher_argument_checking_spec.rb"
72
+ When I run `rspec respond_to_matcher_argument_checking_spec.rb`
73
73
  Then the output should contain all of these:
74
74
  | 8 examples, 4 failures |
75
75
  | expected 7 to respond to :zero? with 1 argument |
@@ -23,7 +23,7 @@ Feature: satisfy matcher
23
23
  it { should satisfy { |v| v > 15 } }
24
24
  end
25
25
  """
26
- When I run "rspec satisfy_matcher_spec.rb"
26
+ When I run `rspec satisfy_matcher_spec.rb`
27
27
  Then the output should contain all of these:
28
28
  | 4 examples, 2 failures |
29
29
  | expected 10 not to satisfy block |
@@ -28,7 +28,7 @@ Feature: throw_symbol matcher
28
28
  specify { expect { 5 + 5 }.to throw_symbol }
29
29
  end
30
30
  """
31
- When I run "rspec throw_symbol_matcher_spec.rb"
31
+ When I run `rspec throw_symbol_matcher_spec.rb`
32
32
  Then the output should contain all of these:
33
33
  | 6 examples, 3 failures |
34
34
  | expected no Symbol to be thrown, got :foo |
@@ -51,7 +51,7 @@ Feature: throw_symbol matcher
51
51
  specify { expect { throw :bar }.to throw_symbol(:foo) }
52
52
  end
53
53
  """
54
- When I run "rspec throw_symbol_matcher_spec.rb"
54
+ When I run `rspec throw_symbol_matcher_spec.rb`
55
55
  Then the output should contain all of these:
56
56
  | 8 examples, 4 failures |
57
57
  | expected :foo not to be thrown, got :foo |
@@ -75,7 +75,7 @@ Feature: throw_symbol matcher
75
75
  specify { expect { throw :foo }.to throw_symbol(:foo, 7) }
76
76
  end
77
77
  """
78
- When I run "rspec throw_symbol_argument_matcher_spec.rb"
78
+ When I run `rspec throw_symbol_argument_matcher_spec.rb`
79
79
  Then the output should contain all of these:
80
80
  | 8 examples, 4 failures |
81
81
  | expected :foo with 7 not to be thrown, got :foo with 7 |
@@ -60,7 +60,7 @@ Feature: specify types of objects
60
60
  it { should be_a(String) }
61
61
  end
62
62
  """
63
- When I run "rspec be_kind_of_matcher_spec.rb"
63
+ When I run `rspec be_kind_of_matcher_spec.rb`
64
64
  Then the output should contain all of these:
65
65
  | 24 examples, 12 failures |
66
66
  | expected 17 not to be a kind of Fixnum |
@@ -105,7 +105,7 @@ Feature: specify types of objects
105
105
  it { should be_an_instance_of(String) }
106
106
  end
107
107
  """
108
- When I run "rspec be_instance_of_matcher_spec.rb"
108
+ When I run `rspec be_instance_of_matcher_spec.rb`
109
109
  Then the output should contain all of these:
110
110
  | 16 examples, 8 failures |
111
111
  | expected 17 not to be an instance of Fixnum |
@@ -28,7 +28,7 @@ Feature: access running example
28
28
  end
29
29
  end
30
30
  """
31
- When I run "rspec ./example_spec.rb"
31
+ When I run `rspec ./example_spec.rb`
32
32
  Then the output should contain "1 example, 0 failures"
33
33
 
34
34
  Scenario: call method _not_ defined on example from matcher
@@ -46,7 +46,7 @@ Feature: access running example
46
46
  end
47
47
  end
48
48
  """
49
- When I run "rspec ./example_spec.rb"
49
+ When I run `rspec ./example_spec.rb`
50
50
  Then the output should contain "1 example, 1 failure"
51
51
  And the output should contain "undefined local variable"
52
52
  And the output should contain "RSpec::Matchers::Matcher"
@@ -20,7 +20,7 @@ Feature: define diffable matcher
20
20
  it {should be_just_like("that")}
21
21
  end
22
22
  """
23
- When I run "rspec ./diffable_matcher_spec.rb --diff"
23
+ When I run `rspec ./diffable_matcher_spec.rb --diff`
24
24
  Then the exit status should not be 0
25
25
 
26
26
  And the output should contain "should be just like that"
@@ -34,7 +34,7 @@ Feature: define matcher
34
34
  end
35
35
 
36
36
  """
37
- When I run "rspec ./matcher_with_default_message_spec.rb --format documentation"
37
+ When I run `rspec ./matcher_with_default_message_spec.rb --format documentation`
38
38
  Then the exit status should not be 0
39
39
 
40
40
  And the output should contain "should be a multiple of 3"
@@ -65,7 +65,7 @@ Feature: define matcher
65
65
  it {should be_a_multiple_of(4)}
66
66
  end
67
67
  """
68
- When I run "rspec ./matcher_with_failure_message_spec.rb"
68
+ When I run `rspec ./matcher_with_failure_message_spec.rb`
69
69
  Then the exit status should not be 0
70
70
  And the stdout should contain "1 example, 1 failure"
71
71
  And the stdout should contain "expected that 9 would be a multiple of 4"
@@ -89,7 +89,7 @@ Feature: define matcher
89
89
  it {should_not be_a_multiple_of(3)}
90
90
  end
91
91
  """
92
- When I run "rspec ./matcher_with_failure_for_message_spec.rb"
92
+ When I run `rspec ./matcher_with_failure_for_message_spec.rb`
93
93
  Then the exit status should not be 0
94
94
  And the stdout should contain "1 example, 1 failure"
95
95
  And the stdout should contain "expected that 9 would not be a multiple of 3"
@@ -116,7 +116,7 @@ Feature: define matcher
116
116
  it {should_not be_a_multiple_of(4)}
117
117
  end
118
118
  """
119
- When I run "rspec ./matcher_overriding_description_spec.rb --format documentation"
119
+ When I run `rspec ./matcher_overriding_description_spec.rb --format documentation`
120
120
  Then the exit status should be 0
121
121
  And the stdout should contain "2 examples, 0 failures"
122
122
  And the stdout should contain "should be multiple of 3"
@@ -141,7 +141,7 @@ Feature: define matcher
141
141
  it {should have_7_fingers}
142
142
  end
143
143
  """
144
- When I run "rspec ./matcher_with_no_args_spec.rb --format documentation"
144
+ When I run `rspec ./matcher_with_no_args_spec.rb --format documentation`
145
145
  Then the exit status should be 0
146
146
  And the stdout should contain "1 example, 0 failures"
147
147
  And the stdout should contain "should have 7 fingers"
@@ -161,7 +161,7 @@ Feature: define matcher
161
161
  it {should be_the_sum_of(1,2,3,4)}
162
162
  end
163
163
  """
164
- When I run "rspec ./matcher_with_multiple_args_spec.rb --format documentation"
164
+ When I run `rspec ./matcher_with_multiple_args_spec.rb --format documentation`
165
165
  Then the exit status should be 0
166
166
  And the stdout should contain "1 example, 0 failures"
167
167
  And the stdout should contain "should be the sum of 1, 2, 3, and 4"
@@ -187,7 +187,7 @@ Feature: define matcher
187
187
  end
188
188
  end
189
189
  """
190
- When I run "rspec ./matcher_with_internal_helper_spec.rb"
190
+ When I run `rspec ./matcher_with_internal_helper_spec.rb`
191
191
  Then the exit status should be 0
192
192
  And the stdout should contain "1 example, 0 failures"
193
193
 
@@ -220,7 +220,7 @@ Feature: define matcher
220
220
  end
221
221
  """
222
222
 
223
- When I run "rspec ./scoped_matcher_spec.rb"
223
+ When I run `rspec ./scoped_matcher_spec.rb`
224
224
  Then the stdout should contain "2 examples, 0 failures"
225
225
 
226
226
  Scenario: scoped in an example group
@@ -254,7 +254,7 @@ Feature: define matcher
254
254
  end
255
255
  """
256
256
 
257
- When I run "rspec scoped_matcher_spec.rb"
257
+ When I run `rspec scoped_matcher_spec.rb`
258
258
  Then the output should contain "3 examples, 0 failures"
259
259
 
260
260
  Scenario: matcher with separate logic for should and should_not
@@ -279,7 +279,7 @@ Feature: define matcher
279
279
  it { should_not contain(1, 4) }
280
280
  end
281
281
  """
282
- When I run "rspec matcher_with_separate_should_not_logic_spec.rb"
282
+ When I run `rspec matcher_with_separate_should_not_logic_spec.rb`
283
283
  Then the output should contain all of these:
284
284
  | 4 examples, 2 failures |
285
285
  | expected [1, 2, 3] to contain 1 and 4 |
@@ -304,7 +304,36 @@ Feature: define matcher
304
304
  it { should_not be_a_multiple_of(3) }
305
305
  end
306
306
  """
307
- When I run "rspec define_method_spec.rb"
307
+ When I run `rspec define_method_spec.rb`
308
+ Then the output should contain all of these:
309
+ | 4 examples, 2 failures |
310
+ | expected 9 to be a multiple of 2 |
311
+ | expected 9 not to be a multiple of 3 |
312
+
313
+ Scenario: include a module with helper methods in the matcher
314
+ Given a file named "include_module_spec.rb" with:
315
+ """
316
+ module MatcherHelpers
317
+ def is_multiple?(actual, expected)
318
+ actual % expected == 0
319
+ end
320
+ end
321
+
322
+ RSpec::Matchers.define :be_a_multiple_of do |expected|
323
+ include MatcherHelpers
324
+ match { |actual| is_multiple?(actual, expected) }
325
+ end
326
+
327
+ describe 9 do
328
+ it { should be_a_multiple_of(3) }
329
+ it { should_not be_a_multiple_of(4) }
330
+
331
+ # deliberate failures
332
+ it { should be_a_multiple_of(2) }
333
+ it { should_not be_a_multiple_of(3) }
334
+ end
335
+ """
336
+ When I run `rspec include_module_spec.rb`
308
337
  Then the output should contain all of these:
309
338
  | 4 examples, 2 failures |
310
339
  | expected 9 to be a multiple of 2 |
@@ -32,7 +32,7 @@ Feature: define matcher outside rspec
32
32
 
33
33
  end
34
34
  """
35
- When I run "ruby test_multiples.rb"
35
+ When I run `ruby test_multiples.rb`
36
36
  Then the exit status should not be 0
37
37
  And the output should contain "expected 9 to be a multiple of 4"
38
38
  And the output should contain "2 tests, 0 assertions, 0 failures, 1 errors"
@@ -19,6 +19,6 @@ Feature: define matcher with fluent interface
19
19
  it { should be_bigger_than(4).but_smaller_than(6) }
20
20
  end
21
21
  """
22
- When I run "rspec between_spec.rb --format documentation"
22
+ When I run `rspec between_spec.rb --format documentation`
23
23
  Then the output should contain "1 example, 0 failures"
24
24
  And the output should contain "should be bigger than 4"
@@ -18,5 +18,5 @@ Feature: customized message
18
18
  end
19
19
 
20
20
  """
21
- When I run "rspec example_spec.rb --format documentation"
21
+ When I run `rspec example_spec.rb --format documentation`
22
22
  Then the output should contain "expected empty array, got [1]"
@@ -21,7 +21,7 @@ Feature: diffing
21
21
  end
22
22
  end
23
23
  """
24
- When I run "rspec example_spec.rb"
24
+ When I run `rspec example_spec.rb`
25
25
  Then the output should contain:
26
26
  """
27
27
  Diff:
@@ -47,7 +47,7 @@ Feature: diffing
47
47
  end
48
48
  end
49
49
  """
50
- When I run "rspec example_spec.rb"
50
+ When I run `rspec example_spec.rb`
51
51
  Then the output should contain:
52
52
  """
53
53
  Diff:
@@ -69,7 +69,7 @@ Feature: diffing
69
69
  end
70
70
  end
71
71
  """
72
- When I run "rspec example_spec.rb"
72
+ When I run `rspec example_spec.rb`
73
73
  Then the output should not contain "Diff:"
74
74
 
75
75
  Scenario: no diff for numbers
@@ -81,5 +81,5 @@ Feature: diffing
81
81
  end
82
82
  end
83
83
  """
84
- When I run "rspec example_spec.rb"
84
+ When I run `rspec example_spec.rb`
85
85
  Then the output should not contain "Diff:"
@@ -18,7 +18,7 @@ Feature: implicit docstrings
18
18
  end
19
19
  """
20
20
 
21
- When I run "rspec ./implicit_docstrings_spec.rb -fdoc"
21
+ When I run `rspec ./implicit_docstrings_spec.rb -fdoc`
22
22
 
23
23
  Then the output should contain "should be < 5"
24
24
  And the output should contain "should include 2"
@@ -44,7 +44,7 @@ Feature: implicit docstrings
44
44
  end
45
45
  """
46
46
 
47
- When I run "rspec ./failing_implicit_docstrings_spec.rb -fdoc"
47
+ When I run `rspec ./failing_implicit_docstrings_spec.rb -fdoc`
48
48
 
49
49
  Then the output should contain "should equal 2"
50
50
  And the output should contain "should be > 5"
@@ -1,7 +1,7 @@
1
1
  # Useful for when the output is slightly different on different versions of ruby
2
2
  Then /^the output should contain "([^"]*)" or "([^"]*)"$/ do |string1, string2|
3
- unless [string1, string2].any? { |s| combined_output =~ Regexp.compile(s) }
4
- fail %Q{Neither "#{string1}" or "#{string2}" were found in:\n#{combined_output}}
3
+ unless [string1, string2].any? { |s| all_output =~ regexp(s) }
4
+ fail %Q{Neither "#{string1}" or "#{string2}" were found in:\n#{all_output}}
5
5
  end
6
6
  end
7
7
 
@@ -1 +1,5 @@
1
- require 'aruba'
1
+ require 'aruba/cucumber'
2
+
3
+ Before do
4
+ @aruba_timeout_seconds = 3
5
+ end
@@ -40,7 +40,7 @@ Feature: Test::Unit integration
40
40
  end
41
41
  end
42
42
  """
43
- When I run "ruby rspec_expectations_test.rb"
43
+ When I run `ruby rspec_expectations_test.rb`
44
44
  Then the output should contain "4 tests, 0 assertions, 1 failures, 0 errors" or "4 tests, 0 assertions, 0 failures, 1 errors"
45
45
  And the output should contain "expected empty? to return true, got false"
46
46
  And the output should contain "be_an_int is deprecated"
@@ -3,7 +3,28 @@ module RSpec
3
3
  module Expectations
4
4
  module ConstMissing
5
5
  def const_missing(name)
6
- name == :Rspec ? RSpec : super(name)
6
+ case name
7
+ when :Rspec, :Spec
8
+ RSpec.warn_deprecation <<-WARNING
9
+ *****************************************************************
10
+ DEPRECATION WARNING: you are using a deprecated constant that will
11
+ be removed from a future version of RSpec.
12
+
13
+ #{caller(0)[2]}
14
+
15
+ * #{name} is deprecated.
16
+ * RSpec is the new top-level module in RSpec-2
17
+ ***************************************************************
18
+ WARNING
19
+ RSpec
20
+ else
21
+ begin
22
+ super
23
+ rescue Exception => e
24
+ e.backtrace.reject! {|l| l =~ Regexp.compile(__FILE__) }
25
+ raise e
26
+ end
27
+ end
7
28
  end
8
29
  end
9
30
 
@@ -1,7 +1,7 @@
1
1
  module RSpec # :nodoc:
2
2
  module Expectations # :nodoc:
3
3
  module Version # :nodoc:
4
- STRING = '2.5.0'
4
+ STRING = '2.6.0.rc2'
5
5
  end
6
6
  end
7
7
  end
@@ -16,7 +16,7 @@ module RSpec
16
16
  #
17
17
  # In addition to those Expression Matchers that are defined explicitly, RSpec will
18
18
  # create custom Matchers on the fly for any arbitrary predicate, giving your specs
19
- # a much more natural language feel.
19
+ # a much more natural language feel.
20
20
  #
21
21
  # A Ruby predicate is a method that ends with a "?" and returns true or false.
22
22
  # Common examples are +empty?+, +nil?+, and +instance_of?+.
@@ -155,13 +155,18 @@ module RSpec
155
155
  # end
156
156
  #
157
157
  module Matchers
158
- # Include Matchers for other test frameworks
159
- if defined?(Test::Unit::TestCase)
160
- Test::Unit::TestCase.send(:include, self)
161
- end
158
+ # Include Matchers for other test frameworks.
159
+ # Note that MiniTest _must_ come before TU because on ruby 1.9,
160
+ # T::U::TC is a subclass of MT::U::TC and a 1.9 bug can lead
161
+ # to infinite recursion from the `super` call in our method_missing
162
+ # hook. See this gist for more info:
163
+ # https://gist.github.com/845896
162
164
  if defined?(MiniTest::Unit::TestCase)
163
165
  MiniTest::Unit::TestCase.send(:include, self)
164
166
  end
167
+ if defined?(Test::Unit::TestCase)
168
+ Test::Unit::TestCase.send(:include, self)
169
+ end
165
170
  end
166
171
  end
167
172
 
@@ -1,23 +1,21 @@
1
1
  module RSpec
2
2
  module Matchers
3
-
4
- #Based on patch from Wilson Bilkovich
5
3
  class Change #:nodoc:
6
4
  def initialize(receiver=nil, message=nil, &block)
7
5
  @message = message
8
6
  @value_proc = block || lambda {receiver.__send__(message)}
9
- @to = @from = @minimum = @maximum = @amount = nil
10
- @given_from = @given_to = false
7
+ @expected_after = @expected_before = @minimum = @maximum = @expected_delta = nil
8
+ @eval_before = @eval_after = false
11
9
  end
12
10
 
13
11
  def matches?(event_proc)
14
12
  raise_block_syntax_error if block_given?
15
13
 
16
- @before = evaluate_value_proc
14
+ @actual_before = evaluate_value_proc
17
15
  event_proc.call
18
- @after = evaluate_value_proc
16
+ @actual_after = evaluate_value_proc
19
17
 
20
- (!change_expected? || changed?) && matches_before? && matches_after? && matches_amount? && matches_min? && matches_max?
18
+ (!change_expected? || changed?) && matches_before? && matches_after? && matches_expected_delta? && matches_min? && matches_max?
21
19
  end
22
20
 
23
21
  def raise_block_syntax_error
@@ -28,35 +26,40 @@ MESSAGE
28
26
  end
29
27
 
30
28
  def evaluate_value_proc
31
- @value_proc.call
29
+ case val = @value_proc.call
30
+ when Array, Hash
31
+ val.dup
32
+ else
33
+ val
34
+ end
32
35
  end
33
36
 
34
37
  def failure_message_for_should
35
- if @given_from && @before != @from
36
- "#{message} should have initially been #{@from.inspect}, but was #{@before.inspect}"
37
- elsif @given_to && @to != @after
38
- "#{message} should have been changed to #{@to.inspect}, but is now #{@after.inspect}"
39
- elsif @amount
40
- "#{message} should have been changed by #{@amount.inspect}, but was changed by #{actual_delta.inspect}"
38
+ if @eval_before && !expected_matches_actual?(@expected_before, @actual_before)
39
+ "#{message} should have initially been #{@expected_before.inspect}, but was #{@actual_before.inspect}"
40
+ elsif @eval_after && !expected_matches_actual?(@expected_after, @actual_after)
41
+ "#{message} should have been changed to #{@expected_after.inspect}, but is now #{@actual_after.inspect}"
42
+ elsif @expected_delta
43
+ "#{message} should have been changed by #{@expected_delta.inspect}, but was changed by #{actual_delta.inspect}"
41
44
  elsif @minimum
42
45
  "#{message} should have been changed by at least #{@minimum.inspect}, but was changed by #{actual_delta.inspect}"
43
46
  elsif @maximum
44
47
  "#{message} should have been changed by at most #{@maximum.inspect}, but was changed by #{actual_delta.inspect}"
45
48
  else
46
- "#{message} should have changed, but is still #{@before.inspect}"
49
+ "#{message} should have changed, but is still #{@actual_before.inspect}"
47
50
  end
48
51
  end
49
52
 
50
53
  def actual_delta
51
- @after - @before
54
+ @actual_after - @actual_before
52
55
  end
53
56
 
54
57
  def failure_message_for_should_not
55
- "#{message} should not have changed, but did change from #{@before.inspect} to #{@after.inspect}"
58
+ "#{message} should not have changed, but did change from #{@actual_before.inspect} to #{@actual_after.inspect}"
56
59
  end
57
60
 
58
- def by(amount)
59
- @amount = amount
61
+ def by(expected_delta)
62
+ @expected_delta = expected_delta
60
63
  self
61
64
  end
62
65
 
@@ -71,14 +74,14 @@ MESSAGE
71
74
  end
72
75
 
73
76
  def to(to)
74
- @given_to = true
75
- @to = to
77
+ @eval_after = true
78
+ @expected_after = to
76
79
  self
77
80
  end
78
81
 
79
- def from (from)
80
- @given_from = true
81
- @from = from
82
+ def from (before)
83
+ @eval_before = true
84
+ @expected_before = before
82
85
  self
83
86
  end
84
87
 
@@ -93,33 +96,36 @@ MESSAGE
93
96
  end
94
97
 
95
98
  def change_expected?
96
- @amount != 0
99
+ @expected_delta != 0
97
100
  end
98
101
 
99
102
  def changed?
100
- @before != @after
103
+ @actual_before != @actual_after
101
104
  end
102
105
 
103
106
  def matches_before?
104
- @given_from ? @from == @before : true
107
+ @eval_before ? expected_matches_actual?(@expected_before, @actual_before) : true
105
108
  end
106
109
 
107
110
  def matches_after?
108
- @given_to ? @to == @after : true
111
+ @eval_after ? expected_matches_actual?(@expected_after, @actual_after) : true
109
112
  end
110
113
 
111
- def matches_amount?
112
- @amount ? (@before + @amount == @after) : true
114
+ def matches_expected_delta?
115
+ @expected_delta ? (@actual_before + @expected_delta == @actual_after) : true
113
116
  end
114
117
 
115
118
  def matches_min?
116
- @minimum ? (@after - @before >= @minimum) : true
119
+ @minimum ? (@actual_after - @actual_before >= @minimum) : true
117
120
  end
118
121
 
119
122
  def matches_max?
120
- @maximum ? (@after - @before <= @maximum) : true
123
+ @maximum ? (@actual_after - @actual_before <= @maximum) : true
121
124
  end
122
125
 
126
+ def expected_matches_actual?(expected, actual)
127
+ expected === actual
128
+ end
123
129
  end
124
130
 
125
131
  # :call-seq:
@@ -174,6 +180,15 @@ MESSAGE
174
180
  # employee.develop_great_new_social_networking_app
175
181
  # }.should change(employee, :title).from("Mail Clerk").to("CEO")
176
182
  #
183
+ # lambda {
184
+ # doctor.leave_office
185
+ # }.should change(doctor, :sign).from(/is in/).to(/is out/)
186
+ #
187
+ # user = User.new(:type => "admin")
188
+ # lambda {
189
+ # user.symbolize_type
190
+ # }.should change(user, :type).from(String).to(Symbol)
191
+ #
177
192
  # == Notes
178
193
  #
179
194
  # Evaluates <tt>receiver.message</tt> or <tt>block</tt> before and after it