rspec-expectations 2.8.0 → 2.9.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. data/.document +5 -0
  2. data/.yardopts +3 -0
  3. data/Changelog.md +176 -0
  4. data/README.md +2 -13
  5. data/features/custom_matchers/access_running_example.feature +1 -1
  6. data/features/step_definitions/additional_cli_steps.rb +4 -4
  7. data/lib/rspec/expectations/fail_with.rb +3 -3
  8. data/lib/rspec/expectations/handler.rb +3 -5
  9. data/lib/rspec/expectations/version.rb +1 -1
  10. data/lib/rspec/matchers.rb +387 -21
  11. data/lib/rspec/matchers/built_in.rb +33 -0
  12. data/lib/rspec/matchers/built_in/base_matcher.rb +58 -0
  13. data/lib/rspec/matchers/built_in/be.rb +183 -0
  14. data/lib/rspec/matchers/built_in/be_instance_of.rb +13 -0
  15. data/lib/rspec/matchers/built_in/be_kind_of.rb +13 -0
  16. data/lib/rspec/matchers/built_in/be_within.rb +39 -0
  17. data/lib/rspec/matchers/built_in/change.rb +132 -0
  18. data/lib/rspec/matchers/built_in/cover.rb +22 -0
  19. data/lib/rspec/matchers/built_in/eq.rb +26 -0
  20. data/lib/rspec/matchers/built_in/eql.rb +25 -0
  21. data/lib/rspec/matchers/built_in/equal.rb +48 -0
  22. data/lib/rspec/matchers/built_in/exist.rb +28 -0
  23. data/lib/rspec/matchers/built_in/has.rb +47 -0
  24. data/lib/rspec/matchers/built_in/have.rb +107 -0
  25. data/lib/rspec/matchers/built_in/include.rb +52 -0
  26. data/lib/rspec/matchers/built_in/match.rb +13 -0
  27. data/lib/rspec/matchers/built_in/match_array.rb +52 -0
  28. data/lib/rspec/matchers/built_in/raise_error.rb +96 -0
  29. data/lib/rspec/matchers/built_in/respond_to.rb +73 -0
  30. data/lib/rspec/matchers/built_in/satisfy.rb +29 -0
  31. data/lib/rspec/matchers/built_in/throw_symbol.rb +93 -0
  32. data/lib/rspec/matchers/dsl.rb +1 -1
  33. data/lib/rspec/matchers/matcher.rb +263 -233
  34. data/lib/rspec/matchers/method_missing.rb +2 -2
  35. data/lib/rspec/matchers/operator_matcher.rb +19 -20
  36. data/spec/rspec/expectations/handler_spec.rb +1 -1
  37. data/spec/rspec/matchers/base_matcher_spec.rb +1 -2
  38. data/spec/rspec/matchers/change_spec.rb +3 -3
  39. data/spec/rspec/matchers/cover_spec.rb +46 -46
  40. data/spec/rspec/matchers/dsl_spec.rb +36 -3
  41. data/spec/rspec/matchers/have_spec.rb +2 -2
  42. data/spec/rspec/matchers/include_spec.rb +1 -1
  43. data/spec/rspec/matchers/matcher_spec.rb +319 -305
  44. data/spec/rspec/matchers/method_missing_spec.rb +1 -0
  45. data/spec/rspec/matchers/operator_matcher_spec.rb +2 -2
  46. data/spec/rspec/matchers/throw_symbol_spec.rb +103 -105
  47. metadata +93 -39
  48. data/lib/rspec/matchers/base_matcher.rb +0 -56
  49. data/lib/rspec/matchers/be.rb +0 -232
  50. data/lib/rspec/matchers/be_instance_of.rb +0 -24
  51. data/lib/rspec/matchers/be_kind_of.rb +0 -24
  52. data/lib/rspec/matchers/be_within.rb +0 -47
  53. data/lib/rspec/matchers/change.rb +0 -197
  54. data/lib/rspec/matchers/cover.rb +0 -36
  55. data/lib/rspec/matchers/eq.rb +0 -36
  56. data/lib/rspec/matchers/eql.rb +0 -35
  57. data/lib/rspec/matchers/equal.rb +0 -58
  58. data/lib/rspec/matchers/errors.rb +0 -5
  59. data/lib/rspec/matchers/exist.rb +0 -34
  60. data/lib/rspec/matchers/has.rb +0 -44
  61. data/lib/rspec/matchers/have.rb +0 -162
  62. data/lib/rspec/matchers/include.rb +0 -66
  63. data/lib/rspec/matchers/match.rb +0 -21
  64. data/lib/rspec/matchers/match_array.rb +0 -65
  65. data/lib/rspec/matchers/raise_error.rb +0 -116
  66. data/lib/rspec/matchers/respond_to.rb +0 -80
  67. data/lib/rspec/matchers/satisfy.rb +0 -46
  68. data/lib/rspec/matchers/throw_symbol.rb +0 -112
@@ -0,0 +1,33 @@
1
+ module RSpec
2
+ module Matchers
3
+ module BuiltIn
4
+ require 'rspec/matchers/built_in/base_matcher'
5
+ autoload :BeAnInstanceOf, 'rspec/matchers/built_in/be_instance_of'
6
+ autoload :Be, 'rspec/matchers/built_in/be'
7
+ autoload :BeTrue, 'rspec/matchers/built_in/be'
8
+ autoload :BeFalse, 'rspec/matchers/built_in/be'
9
+ autoload :BeNil, 'rspec/matchers/built_in/be'
10
+ autoload :BeComparedTo, 'rspec/matchers/built_in/be'
11
+ autoload :BePredicate, 'rspec/matchers/built_in/be'
12
+ autoload :BeAKindOf, 'rspec/matchers/built_in/be_kind_of'
13
+ autoload :BeWithin, 'rspec/matchers/built_in/be_within'
14
+ autoload :Change, 'rspec/matchers/built_in/change'
15
+ autoload :Cover, 'rspec/matchers/built_in/cover' if (1..2).respond_to?(:cover?)
16
+ autoload :Eq, 'rspec/matchers/built_in/eq'
17
+ autoload :Eql, 'rspec/matchers/built_in/eql'
18
+ autoload :Equal, 'rspec/matchers/built_in/equal'
19
+ autoload :Exist, 'rspec/matchers/built_in/exist'
20
+ autoload :Has, 'rspec/matchers/built_in/has'
21
+ autoload :Have, 'rspec/matchers/built_in/have'
22
+ autoload :Include, 'rspec/matchers/built_in/include'
23
+ autoload :Match, 'rspec/matchers/built_in/match'
24
+ autoload :MatchArray, 'rspec/matchers/built_in/match_array'
25
+ autoload :RaiseError, 'rspec/matchers/built_in/raise_error'
26
+ autoload :RespondTo, 'rspec/matchers/built_in/respond_to'
27
+ autoload :Satisfy, 'rspec/matchers/built_in/satisfy'
28
+ autoload :ThrowSymbol, 'rspec/matchers/built_in/throw_symbol'
29
+ end
30
+ end
31
+ end
32
+
33
+
@@ -0,0 +1,58 @@
1
+ module RSpec
2
+ module Matchers
3
+ module BuiltIn
4
+ # @api private
5
+ #
6
+ # Used _internally_ as a base class for matchers that ship with
7
+ # rspec-expectations.
8
+ #
9
+ # ### Warning:
10
+ #
11
+ # This class is for internal use, and subject to change without notice. We
12
+ # strongly recommend that you do not base your custom matchers on this
13
+ # class. If/when this changes, we will announce it and remove this warning.
14
+ module BaseMatcher
15
+ include RSpec::Matchers::Pretty
16
+
17
+ attr_reader :actual, :expected, :rescued_exception
18
+
19
+ def initialize(expected=nil)
20
+ @expected = expected
21
+ end
22
+
23
+ def matches?(actual)
24
+ @actual = actual
25
+ end
26
+
27
+ def match_unless_raises(exception=Exception)
28
+ begin
29
+ yield
30
+ true
31
+ rescue exception => @rescued_exception
32
+ false
33
+ end
34
+ end
35
+
36
+ def failure_message_for_should
37
+ "expected #{actual.inspect} to #{name_to_sentence}#{expected_to_sentence}"
38
+ end
39
+
40
+ def failure_message_for_should_not
41
+ "expected #{actual.inspect} not to #{name_to_sentence}#{expected_to_sentence}"
42
+ end
43
+
44
+ def description
45
+ expected ? "#{name_to_sentence} #{expected.inspect}" : name_to_sentence
46
+ end
47
+
48
+ def diffable?
49
+ false
50
+ end
51
+
52
+ def ==(other)
53
+ matches?(other)
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,183 @@
1
+ require 'rspec/matchers/dsl'
2
+
3
+ module RSpec
4
+ module Matchers
5
+ module BuiltIn
6
+ class BeTrue
7
+ include BaseMatcher
8
+
9
+ def matches?(actual)
10
+ super(actual)
11
+ end
12
+ end
13
+
14
+ class BeFalse
15
+ include BaseMatcher
16
+
17
+ def matches?(actual)
18
+ !super(actual)
19
+ end
20
+ end
21
+
22
+ class BeNil
23
+ include BaseMatcher
24
+
25
+ def matches?(actual)
26
+ super(actual).nil?
27
+ end
28
+
29
+ def failure_message_for_should
30
+ "expected: nil\n got: #{actual.inspect}"
31
+ end
32
+
33
+ def failure_message_for_should_not
34
+ "expected: not nil\n got: nil"
35
+ end
36
+ end
37
+
38
+ class Be
39
+ include RSpec::Matchers::Pretty
40
+
41
+ def initialize(*args, &block)
42
+ @args = args
43
+ end
44
+
45
+ def matches?(actual)
46
+ @actual = actual
47
+ !!@actual
48
+ end
49
+
50
+ def failure_message_for_should
51
+ "expected #{@actual.inspect} to evaluate to true"
52
+ end
53
+
54
+ def failure_message_for_should_not
55
+ "expected #{@actual.inspect} to evaluate to false"
56
+ end
57
+
58
+ def description
59
+ "be"
60
+ end
61
+
62
+ [:==, :<, :<=, :>=, :>, :===].each do |operator|
63
+ define_method operator do |operand|
64
+ BeComparedTo.new(operand, operator)
65
+ end
66
+ end
67
+
68
+ private
69
+
70
+ def args_to_s
71
+ @args.empty? ? "" : parenthesize(inspected_args.join(', '))
72
+ end
73
+
74
+ def parenthesize(string)
75
+ "(#{string})"
76
+ end
77
+
78
+ def inspected_args
79
+ @args.collect{|a| a.inspect}
80
+ end
81
+
82
+ def expected_to_sentence
83
+ split_words(@expected)
84
+ end
85
+
86
+ def args_to_sentence
87
+ to_sentence(@args)
88
+ end
89
+ end
90
+
91
+ class BeComparedTo < Be
92
+ def initialize(operand, operator)
93
+ @expected, @operator = operand, operator
94
+ @args = []
95
+ end
96
+
97
+ def matches?(actual)
98
+ @actual = actual
99
+ @actual.__send__(@operator, @expected)
100
+ end
101
+
102
+ def failure_message_for_should
103
+ "expected: #{@operator} #{@expected.inspect}\n got: #{@operator.to_s.gsub(/./, ' ')} #{@actual.inspect}"
104
+ end
105
+
106
+ def failure_message_for_should_not
107
+ message = <<-MESSAGE
108
+ 'should_not be #{@operator} #{@expected}' not only FAILED,
109
+ it is a bit confusing.
110
+ MESSAGE
111
+
112
+ raise message << ([:===,:==].include?(@operator) ?
113
+ "It might be more clearly expressed without the \"be\"?" :
114
+ "It might be more clearly expressed in the positive?")
115
+ end
116
+
117
+ def description
118
+ "be #{@operator} #{expected_to_sentence}#{args_to_sentence}"
119
+ end
120
+ end
121
+
122
+ class BePredicate < Be
123
+ def initialize(*args, &block)
124
+ @expected = parse_expected(args.shift)
125
+ @args = args
126
+ @block = block
127
+ end
128
+
129
+ def matches?(actual)
130
+ @actual = actual
131
+ begin
132
+ return @result = actual.__send__(predicate, *@args, &@block)
133
+ rescue NameError => predicate_missing_error
134
+ "this needs to be here or rcov will not count this branch even though it's executed in a code example"
135
+ end
136
+
137
+ begin
138
+ return @result = actual.__send__(present_tense_predicate, *@args, &@block)
139
+ rescue NameError
140
+ raise predicate_missing_error
141
+ end
142
+ end
143
+
144
+ def failure_message_for_should
145
+ "expected #{predicate}#{args_to_s} to return true, got #{@result.inspect}"
146
+ end
147
+
148
+ def failure_message_for_should_not
149
+ "expected #{predicate}#{args_to_s} to return false, got #{@result.inspect}"
150
+ end
151
+
152
+ def description
153
+ "#{prefix_to_sentence}#{expected_to_sentence}#{args_to_sentence}"
154
+ end
155
+
156
+ private
157
+
158
+ def predicate
159
+ "#{@expected}?".to_sym
160
+ end
161
+
162
+ def present_tense_predicate
163
+ "#{@expected}s?".to_sym
164
+ end
165
+
166
+ def parse_expected(expected)
167
+ @prefix, expected = prefix_and_expected(expected)
168
+ expected
169
+ end
170
+
171
+ def prefix_and_expected(symbol)
172
+ symbol.to_s =~ /^(be_(an?_)?)(.*)/
173
+ return $1, $3
174
+ end
175
+
176
+ def prefix_to_sentence
177
+ split_words(@prefix)
178
+ end
179
+ end
180
+ end
181
+
182
+ end
183
+ end
@@ -0,0 +1,13 @@
1
+ module RSpec
2
+ module Matchers
3
+ module BuiltIn
4
+ class BeAnInstanceOf
5
+ include BaseMatcher
6
+
7
+ def matches?(actual)
8
+ super(actual).instance_of?(expected)
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module RSpec
2
+ module Matchers
3
+ module BuiltIn
4
+ class BeAKindOf
5
+ include BaseMatcher
6
+
7
+ def matches?(actual)
8
+ super(actual).kind_of?(expected)
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,39 @@
1
+ module RSpec
2
+ module Matchers
3
+ module BuiltIn
4
+ class BeWithin
5
+ include BaseMatcher
6
+
7
+ attr_reader :delta
8
+
9
+ def initialize(delta)
10
+ @delta = delta
11
+ end
12
+
13
+ def matches?(actual)
14
+ unless defined?(@expected)
15
+ raise ArgumentError.new("You must set an expected value using #of: be_within(#{delta}).of(expected_value)")
16
+ end
17
+ (super(actual) - expected).abs < delta
18
+ end
19
+
20
+ def of(expected)
21
+ @expected = expected
22
+ self
23
+ end
24
+
25
+ def failure_message_for_should
26
+ "expected #{actual} to #{description}"
27
+ end
28
+
29
+ def failure_message_for_should_not
30
+ "expected #{actual} not to #{description}"
31
+ end
32
+
33
+ def description
34
+ "be within #{delta} of #{expected}"
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,132 @@
1
+ module RSpec
2
+ module Matchers
3
+ module BuiltIn
4
+ class Change
5
+ def initialize(receiver=nil, message=nil, &block)
6
+ @message = message
7
+ @value_proc = block || lambda {receiver.__send__(message)}
8
+ @expected_after = @expected_before = @minimum = @maximum = @expected_delta = nil
9
+ @eval_before = @eval_after = false
10
+ end
11
+
12
+ def matches?(event_proc)
13
+ raise_block_syntax_error if block_given?
14
+
15
+ @actual_before = evaluate_value_proc
16
+ event_proc.call
17
+ @actual_after = evaluate_value_proc
18
+
19
+ (!change_expected? || changed?) && matches_before? && matches_after? && matches_expected_delta? && matches_min? && matches_max?
20
+ end
21
+
22
+ def raise_block_syntax_error
23
+ raise SyntaxError.new(<<-MESSAGE)
24
+ block passed to should or should_not change must use {} instead of do/end
25
+ MESSAGE
26
+ end
27
+
28
+ def evaluate_value_proc
29
+ case val = @value_proc.call
30
+ when Enumerable
31
+ val.dup
32
+ else
33
+ val
34
+ end
35
+ end
36
+
37
+ def failure_message_for_should
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}"
44
+ elsif @minimum
45
+ "#{message} should have been changed by at least #{@minimum.inspect}, but was changed by #{actual_delta.inspect}"
46
+ elsif @maximum
47
+ "#{message} should have been changed by at most #{@maximum.inspect}, but was changed by #{actual_delta.inspect}"
48
+ else
49
+ "#{message} should have changed, but is still #{@actual_before.inspect}"
50
+ end
51
+ end
52
+
53
+ def actual_delta
54
+ @actual_after - @actual_before
55
+ end
56
+
57
+ def failure_message_for_should_not
58
+ "#{message} should not have changed, but did change from #{@actual_before.inspect} to #{@actual_after.inspect}"
59
+ end
60
+
61
+ def by(expected_delta)
62
+ @expected_delta = expected_delta
63
+ self
64
+ end
65
+
66
+ def by_at_least(minimum)
67
+ @minimum = minimum
68
+ self
69
+ end
70
+
71
+ def by_at_most(maximum)
72
+ @maximum = maximum
73
+ self
74
+ end
75
+
76
+ def to(to)
77
+ @eval_after = true
78
+ @expected_after = to
79
+ self
80
+ end
81
+
82
+ def from (before)
83
+ @eval_before = true
84
+ @expected_before = before
85
+ self
86
+ end
87
+
88
+ def description
89
+ "change ##{message}"
90
+ end
91
+
92
+ private
93
+
94
+ def message
95
+ @message || "result"
96
+ end
97
+
98
+ def change_expected?
99
+ @expected_delta != 0
100
+ end
101
+
102
+ def changed?
103
+ @actual_before != @actual_after
104
+ end
105
+
106
+ def matches_before?
107
+ @eval_before ? expected_matches_actual?(@expected_before, @actual_before) : true
108
+ end
109
+
110
+ def matches_after?
111
+ @eval_after ? expected_matches_actual?(@expected_after, @actual_after) : true
112
+ end
113
+
114
+ def matches_expected_delta?
115
+ @expected_delta ? (@actual_before + @expected_delta == @actual_after) : true
116
+ end
117
+
118
+ def matches_min?
119
+ @minimum ? (@actual_after - @actual_before >= @minimum) : true
120
+ end
121
+
122
+ def matches_max?
123
+ @maximum ? (@actual_after - @actual_before <= @maximum) : true
124
+ end
125
+
126
+ def expected_matches_actual?(expected, actual)
127
+ expected === actual
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end