rspec-expectations 2.99.0.beta1 → 2.99.0.beta2

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 (38) hide show
  1. data/Changelog.md +35 -1
  2. data/features/step_definitions/additional_cli_steps.rb +10 -0
  3. data/features/test_frameworks/test_unit.feature +40 -0
  4. data/lib/rspec/expectations/caller_filter.rb +50 -45
  5. data/lib/rspec/expectations/deprecation.rb +8 -0
  6. data/lib/rspec/expectations/handler.rb +5 -1
  7. data/lib/rspec/expectations/version.rb +1 -1
  8. data/lib/rspec/matchers.rb +10 -1
  9. data/lib/rspec/matchers/be_close.rb +4 -1
  10. data/lib/rspec/matchers/built_in/base_matcher.rb +8 -9
  11. data/lib/rspec/matchers/built_in/be_within.rb +2 -1
  12. data/lib/rspec/matchers/built_in/change.rb +37 -1
  13. data/lib/rspec/matchers/built_in/has.rb +2 -1
  14. data/lib/rspec/matchers/built_in/have.rb +6 -2
  15. data/lib/rspec/matchers/built_in/raise_error.rb +2 -1
  16. data/lib/rspec/matchers/built_in/respond_to.rb +2 -1
  17. data/lib/rspec/matchers/built_in/satisfy.rb +2 -1
  18. data/lib/rspec/matchers/built_in/throw_symbol.rb +2 -1
  19. data/lib/rspec/matchers/built_in/yield.rb +4 -2
  20. data/lib/rspec/matchers/match_aliases.rb +22 -0
  21. data/lib/rspec/matchers/matcher.rb +18 -1
  22. data/lib/rspec/matchers/operator_matcher.rb +70 -70
  23. data/lib/rspec/matchers/test_unit_integration.rb +22 -5
  24. data/spec/rspec/expectations_spec.rb +1 -1
  25. data/spec/rspec/matchers/base_matcher_spec.rb +27 -12
  26. data/spec/rspec/matchers/be_close_spec.rb +4 -1
  27. data/spec/rspec/matchers/be_spec.rb +2 -2
  28. data/spec/rspec/matchers/change_spec.rb +76 -1
  29. data/spec/rspec/matchers/equal_spec.rb +26 -0
  30. data/spec/rspec/matchers/have_spec.rb +26 -18
  31. data/spec/rspec/matchers/matcher_spec.rb +13 -0
  32. data/spec/rspec/matchers/operator_matcher_spec.rb +25 -6
  33. data/spec/spec_helper.rb +0 -21
  34. data/spec/support/helper_methods.rb +28 -3
  35. data/spec/support/shared_examples.rb +42 -0
  36. metadata +20 -8
  37. checksums.yaml +0 -15
  38. data/spec/rspec/matchers/matchers_spec.rb +0 -37
@@ -1,7 +1,33 @@
1
+ ### 2.99.0.beta2 / 2014-02-17
2
+ [full changelog](http://github.com/rspec/rspec-expectations/compare/v2.99.0.beta1...v2.99.0.beta2)
3
+
4
+ Deprecations:
5
+
6
+ * Deprecate chaining `by`, `by_at_least`, `by_at_most` or `to` off of
7
+ `expect { }.not_to change { }`. The docs have always said these are
8
+ not supported for the negative form but now they explicitly raise
9
+ errors in RSpec 3. (Myron Marston)
10
+ * Change the semantics of `expect { }.not_to change { x }.from(y)`.
11
+ In RSpec 2.x, this expectation would only fail if `x` started with
12
+ the value of `y` and changed. If it started with a different value
13
+ and changed, it would pass. In RSpec 3, it will pass only if the
14
+ value starts at `y` and it does not change. (Myron Marston)
15
+ * Deprecate `matcher == value` as an alias for `matcher.matches?(value)`,
16
+ in favor of `matcher === value`. (Myron Marston)
17
+ * Deprecate `RSpec::Matchers::OperatorMatcher` in favor of
18
+ `RSpec::Matchers::BuiltIn::OperatorMatcher`. (Myron Marston)
19
+ * Deprecate auto-integration with Test::Unit and minitest.
20
+ Instead, include `RSpec::Matchers` in the appropriate test case
21
+ base class yourself. (Myron Marston)
22
+ * Deprecate treating `#expected` on a DSL-generated custom matcher
23
+ as an array when only 1 argument is passed to the matcher method.
24
+ In RSpec 3 it will be the single value in order to make diffs
25
+ work properly. (Jon Rowe)
26
+
1
27
  ### 2.99.0.beta1 / 2013-11-07
2
28
  [full changelog](http://github.com/rspec/rspec-expectations/compare/v2.14.4...v2.99.0.beta1)
3
29
 
4
- Deprecations
30
+ Deprecations:
5
31
 
6
32
  * Deprecate `have`, `have_at_least` and `have_at_most`. You can continue using those
7
33
  matchers through https://github.com/rspec/rspec-collection_matchers, or
@@ -23,6 +49,14 @@ Deprecations
23
49
  * RSpec 2.x allowed helper methods defined either way to be used for
24
50
  either purpose, but RSpec 3.0 will not.
25
51
 
52
+ ### 2.14.5 / 2014-02-01
53
+ [full changelog](http://github.com/rspec/rspec-expectations/compare/v2.14.4...v2.14.5)
54
+
55
+ Bug fixes
56
+
57
+ * Fix wrong matcher descriptions with falsey expected value
58
+ (yujinakayama)
59
+
26
60
  ### 2.14.4 / 2013-11-06
27
61
  [full changelog](http://github.com/rspec/rspec-expectations/compare/v2.14.3...v2.14.4)
28
62
 
@@ -20,3 +20,13 @@ Then /^the example should fail$/ do
20
20
  step %q{the output should contain "1 failure"}
21
21
  step %q{the exit status should not be 0}
22
22
  end
23
+
24
+ deprecation_message = /rspec-expectations' built-in integration with (Test::Unit|minitest < 5.x) is deprecated/
25
+
26
+ Then /^the output should contain a deprecation warning about rspec\-expecations' built\-in integration$/ do
27
+ expect(all_output).to match(deprecation_message)
28
+ end
29
+
30
+ Then /^the output should not contain a deprecation warning about rspec\-expecations' built\-in integration$/ do
31
+ expect(all_output).not_to match(deprecation_message)
32
+ end
@@ -42,3 +42,43 @@ Feature: Test::Unit integration
42
42
  Then the output should contain "3 tests, 0 assertions, 0 failures, 1 errors" or "3 tests, 0 assertions, 1 failures, 0 errors"
43
43
  And the output should contain "expected empty? to return true, got false"
44
44
  And the output should contain "be_an_int is deprecated"
45
+ And the output should contain a deprecation warning about rspec-expecations' built-in integration
46
+
47
+ Scenario: use rspec/expectations with Test::Unit
48
+ Given a file named "rspec_expectations_with_manual_integration_test.rb" with:
49
+ """
50
+ require 'test/unit'
51
+ require "rspec/expectations"
52
+
53
+ class RSpecExpectationsTest < Test::Unit::TestCase
54
+ include ::RSpec::Matchers
55
+
56
+ RSpec::Matchers.define :be_an_integer do
57
+ match { |actual| Integer === actual }
58
+ end
59
+
60
+ def be_an_int
61
+ # This is actually an internal rspec-expectations API, but is used
62
+ # here to demonstrate that deprecation warnings from within
63
+ # rspec-expectations work correcty without depending on rspec-core
64
+ RSpec.deprecate(:be_an_int, :replacement => :be_an_integer)
65
+ be_an_integer
66
+ end
67
+
68
+ def test_passing_expectation
69
+ expect(1 + 3).to eq 4
70
+ end
71
+
72
+ def test_failing_expectation
73
+ expect([1,2]).to be_empty
74
+ end
75
+
76
+ def test_custom_matcher_with_deprecation_warning
77
+ expect(1).to be_an_int
78
+ end
79
+ end
80
+ """
81
+ When I run `ruby rspec_expectations_with_manual_integration_test.rb`
82
+ Then the output should contain "3 tests, 0 assertions, 0 failures, 1 errors" or "3 tests, 0 assertions, 1 failures, 0 errors"
83
+ And the output should not contain a deprecation warning about rspec-expecations' built-in integration
84
+
@@ -3,53 +3,58 @@ module RSpec
3
3
  # non-rspec lines. This enables errors to be reported at the call site in
4
4
  # the code using the library, which is far more useful than the particular
5
5
  # internal method that raised an error.
6
- class CallerFilter
7
-
8
- RSPEC_LIBS = %w[
9
- core
10
- mocks
11
- expectations
12
- matchers
13
- rails
14
- ]
15
-
16
- ADDITIONAL_TOP_LEVEL_FILES = %w[ autorun ]
17
-
18
- LIB_REGEX = %r{/lib/rspec/(#{(RSPEC_LIBS + ADDITIONAL_TOP_LEVEL_FILES).join('|')})(\.rb|/)}
19
-
20
- if RUBY_VERSION >= '2.0.0'
21
- def self.first_non_rspec_line
22
- # `caller` is an expensive method that scales linearly with the size of
23
- # the stack. The performance hit for fetching it in chunks is small,
24
- # and since the target line is probably near the top of the stack, the
25
- # overall improvement of a chunked search like this is significant.
26
- #
27
- # See benchmarks/caller.rb for measurements.
28
-
29
- # Initial value here is mostly arbitrary, but is chosen to give good
30
- # performance on the common case of creating a double.
31
- increment = 5
32
- i = 1
33
- line = nil
34
-
35
- while !line
36
- stack = caller(i, increment)
37
- raise "No non-lib lines in stack" unless stack
38
-
39
- line = stack.find { |l| l !~ LIB_REGEX }
40
-
41
- i += increment
42
- increment *= 2 # The choice of two here is arbitrary.
43
- end
44
6
 
45
- line
46
- end
47
- else
48
- # Earlier rubies do not support the two argument form of `caller`. This
49
- # fallback is logically the same, but slower.
50
- def self.first_non_rspec_line
51
- caller.find { |line| line !~ LIB_REGEX }
7
+ unless defined?(CallerFilter)
8
+
9
+ class CallerFilter
10
+
11
+ RSPEC_LIBS = %w[
12
+ core
13
+ mocks
14
+ expectations
15
+ matchers
16
+ rails
17
+ ]
18
+
19
+ ADDITIONAL_TOP_LEVEL_FILES = %w[ autorun ]
20
+
21
+ LIB_REGEX = %r{/lib/rspec/(#{(RSPEC_LIBS + ADDITIONAL_TOP_LEVEL_FILES).join('|')})(\.rb|/)}
22
+
23
+ if RUBY_VERSION >= '2.0.0'
24
+ def self.first_non_rspec_line
25
+ # `caller` is an expensive method that scales linearly with the size of
26
+ # the stack. The performance hit for fetching it in chunks is small,
27
+ # and since the target line is probably near the top of the stack, the
28
+ # overall improvement of a chunked search like this is significant.
29
+ #
30
+ # See benchmarks/caller.rb for measurements.
31
+
32
+ # Initial value here is mostly arbitrary, but is chosen to give good
33
+ # performance on the common case of creating a double.
34
+ increment = 5
35
+ i = 1
36
+ line = nil
37
+
38
+ while !line
39
+ stack = caller(i, increment)
40
+ return nil unless stack
41
+
42
+ line = stack.find { |l| l !~ LIB_REGEX }
43
+
44
+ i += increment
45
+ increment *= 2 # The choice of two here is arbitrary.
46
+ end
47
+
48
+ line
49
+ end
50
+ else
51
+ # Earlier rubies do not support the two argument form of `caller`. This
52
+ # fallback is logically the same, but slower.
53
+ def self.first_non_rspec_line
54
+ caller.find { |line| line !~ LIB_REGEX }
55
+ end
52
56
  end
53
57
  end
58
+
54
59
  end
55
60
  end
@@ -12,6 +12,14 @@ module RSpec
12
12
  message << " Called from #{CallerFilter.first_non_rspec_line}."
13
13
  warn message
14
14
  end
15
+
16
+ # @private
17
+ #
18
+ # Used internally to print deprecation warnings
19
+ def warn_deprecation(warning)
20
+ message = "\nDEPRECATION: #{warning}\n"
21
+ warn message
22
+ end
15
23
  end
16
24
  end
17
25
 
@@ -31,7 +31,11 @@ module RSpec
31
31
  matcher.failure_message
32
32
 
33
33
  if matcher.respond_to?(:diffable?) && matcher.diffable?
34
- ::RSpec::Expectations.fail_with message, matcher.expected, matcher.actual
34
+ if RSpec::Matchers::DSL::Matcher === matcher
35
+ ::RSpec::Expectations.fail_with message, matcher.expected_as_array, matcher.actual
36
+ else
37
+ ::RSpec::Expectations.fail_with message, matcher.expected, matcher.actual
38
+ end
35
39
  else
36
40
  ::RSpec::Expectations.fail_with message
37
41
  end
@@ -2,7 +2,7 @@ module RSpec
2
2
  module Expectations
3
3
  # @private
4
4
  module Version
5
- STRING = '2.99.0.beta1'
5
+ STRING = '2.99.0.beta2'
6
6
  end
7
7
  end
8
8
  end
@@ -1,6 +1,7 @@
1
1
  require 'rspec/matchers/extensions/instance_eval_with_args'
2
2
  require 'rspec/matchers/pretty'
3
3
 
4
+ require 'rspec/matchers/match_aliases'
4
5
  require 'rspec/matchers/built_in'
5
6
  require 'rspec/matchers/matcher'
6
7
  require 'rspec/matchers/operator_matcher'
@@ -707,6 +708,14 @@ module RSpec
707
708
  BuiltIn::MatchArray.new(array)
708
709
  end
709
710
 
710
- OperatorMatcher.register(Enumerable, '=~', BuiltIn::MatchArray)
711
+ BuiltIn::OperatorMatcher.register(Enumerable, '=~', BuiltIn::MatchArray)
712
+
713
+ def self.const_missing(name)
714
+ return super unless name == :OperatorMatcher
715
+
716
+ RSpec.deprecate("RSpec::Matchers::OperatorMatcher",
717
+ :replacement => "RSpec::Matchers::BuiltIn::OperatorMatcher")
718
+ BuiltIn::OperatorMatcher
719
+ end
711
720
  end
712
721
  end
@@ -2,7 +2,10 @@ module RSpec
2
2
  module Matchers
3
3
  # @deprecated use +be_within+ instead.
4
4
  def be_close(expected, delta)
5
- RSpec.deprecate("be_close(#{expected}, #{delta})", :replacement => "be_within(#{delta}).of(#{expected})")
5
+ RSpec.deprecate("be_close(#{expected}, #{delta})",
6
+ :replacement => "be_within(#{delta}).of(#{expected})",
7
+ :type => 'the be_close matcher'
8
+ )
6
9
  be_within(delta).of(expected)
7
10
  end
8
11
  end
@@ -13,11 +13,14 @@ module RSpec
13
13
  # class. If/when this changes, we will announce it and remove this warning.
14
14
  class BaseMatcher
15
15
  include RSpec::Matchers::Pretty
16
+ include RSpec::Matchers::MatchAliases
17
+
18
+ UNDEFINED = Object.new.freeze
16
19
 
17
20
  attr_reader :actual, :expected, :rescued_exception
18
21
 
19
- def initialize(expected = nil)
20
- @expected = expected
22
+ def initialize(expected = UNDEFINED)
23
+ @expected = expected unless UNDEFINED.equal?(expected)
21
24
  end
22
25
 
23
26
  def matches?(actual)
@@ -36,27 +39,23 @@ module RSpec
36
39
  end
37
40
 
38
41
  def failure_message_for_should
39
- assert_ivars :@actual, :@expected
42
+ assert_ivars :@actual
40
43
  "expected #{@actual.inspect} to #{name_to_sentence}#{expected_to_sentence}"
41
44
  end
42
45
 
43
46
  def failure_message_for_should_not
44
- assert_ivars :@actual, :@expected
47
+ assert_ivars :@actual
45
48
  "expected #{@actual.inspect} not to #{name_to_sentence}#{expected_to_sentence}"
46
49
  end
47
50
 
48
51
  def description
49
- expected ? "#{name_to_sentence} #{@expected.inspect}" : name_to_sentence
52
+ defined?(@expected) ? "#{name_to_sentence} #{@expected.inspect}" : name_to_sentence
50
53
  end
51
54
 
52
55
  def diffable?
53
56
  false
54
57
  end
55
58
 
56
- def ==(other)
57
- matches?(other)
58
- end
59
-
60
59
  private
61
60
 
62
61
  def assert_ivars *ivars
@@ -2,6 +2,8 @@ module RSpec
2
2
  module Matchers
3
3
  module BuiltIn
4
4
  class BeWithin
5
+ include MatchAliases
6
+
5
7
  def initialize(delta)
6
8
  @delta = delta
7
9
  end
@@ -12,7 +14,6 @@ module RSpec
12
14
  raise needs_subtractable unless @actual.respond_to? :-
13
15
  (@actual - @expected).abs <= @tolerance
14
16
  end
15
- alias == matches?
16
17
 
17
18
  def of(expected)
18
19
  @expected = expected
@@ -2,6 +2,8 @@ module RSpec
2
2
  module Matchers
3
3
  module BuiltIn
4
4
  class Change
5
+ include MatchAliases
6
+
5
7
  def initialize(receiver=nil, message=nil, &block)
6
8
  @message = message
7
9
  @value_proc = block || lambda {receiver.__send__(message)}
@@ -18,7 +20,41 @@ module RSpec
18
20
 
19
21
  (!change_expected? || changed?) && matches_before? && matches_after? && matches_expected_delta? && matches_min? && matches_max?
20
22
  end
21
- alias == matches?
23
+
24
+ def does_not_match?(event_proc, &block)
25
+ expression = if @expected_delta
26
+ "by()"
27
+ elsif @minimum
28
+ "by_at_least()"
29
+ elsif @maximum
30
+ "by_at_most()"
31
+ elsif @eval_after
32
+ "to()"
33
+ end
34
+
35
+ if expression
36
+ RSpec.deprecate("`expect { }.not_to change { }.#{expression}`")
37
+ end
38
+
39
+ matched_positively = matches?(event_proc, &block)
40
+
41
+ unless matches_before?
42
+ RSpec.warn_deprecation(<<-EOS.gsub(/^\s+\|/, ''))
43
+ |--------------------------------------------------------------------
44
+ |The semantics of `expect { }.not_to change { }.from()` are changing
45
+ |in RSpec 3. In RSpec 2.x, this would pass if the value changed but
46
+ |the starting value was not what you specified with `from()`. In
47
+ |RSpec 3, this will only pass if the starting value matches your
48
+ |`from()` value _and_ it has not changed.
49
+ |
50
+ |You have an expectation that relies upon the old RSpec 2.x semantics
51
+ |at: #{CallerFilter.first_non_rspec_line}"
52
+ |--------------------------------------------------------------------
53
+ EOS
54
+ end
55
+
56
+ !matched_positively
57
+ end
22
58
 
23
59
  def raise_block_syntax_error
24
60
  raise SyntaxError.new(<<-MESSAGE)
@@ -2,6 +2,8 @@ module RSpec
2
2
  module Matchers
3
3
  module BuiltIn
4
4
  class Has
5
+ include MatchAliases
6
+
5
7
  def initialize(expected, *args)
6
8
  @expected, @args = expected, args
7
9
  end
@@ -9,7 +11,6 @@ module RSpec
9
11
  def matches?(actual)
10
12
  actual.__send__(predicate(@expected), *@args)
11
13
  end
12
- alias == matches?
13
14
 
14
15
  def failure_message_for_should
15
16
  "expected ##{predicate(@expected)}#{failure_message_args_description} to return true, got false"
@@ -2,6 +2,8 @@ module RSpec
2
2
  module Matchers
3
3
  module BuiltIn
4
4
  class Have
5
+ include MatchAliases
6
+
5
7
  QUERY_METHODS = [:size, :length, :count].freeze
6
8
 
7
9
  def initialize(expected, relativity=:exactly)
@@ -54,7 +56,6 @@ module RSpec
54
56
  else @actual == @expected
55
57
  end
56
58
  end
57
- alias == matches?
58
59
 
59
60
  def does_not_match?(collection_or_owner)
60
61
  @negative_expectation = true
@@ -143,7 +144,10 @@ EOF
143
144
  deprecation_message << "or replace your expectation with something like "
144
145
  deprecation_message << "`expect(#{cardinality_expression(query_method)}).#{expectation_format_method} #{suggested_matcher_expression}`"
145
146
 
146
- RSpec.deprecate("`#{expectation_expression(query_method)}`", :replacement => deprecation_message)
147
+ RSpec.deprecate("`#{expectation_expression(query_method)}`",
148
+ :replacement => deprecation_message,
149
+ :type => "the have matcher"
150
+ )
147
151
  end
148
152
 
149
153
  def expectation_expression(query_method)