rspec-expectations 2.0.0.a1

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 (55) hide show
  1. data/.document +5 -0
  2. data/.gitignore +5 -0
  3. data/License.txt +22 -0
  4. data/README.markdown +8 -0
  5. data/Rakefile +43 -0
  6. data/VERSION +1 -0
  7. data/VERSION.yml +5 -0
  8. data/lib/rspec/expectations.rb +36 -0
  9. data/lib/rspec/expectations/differs/default.rb +62 -0
  10. data/lib/rspec/expectations/differs/load-diff-lcs.rb +12 -0
  11. data/lib/rspec/expectations/errors.rb +12 -0
  12. data/lib/rspec/expectations/extensions.rb +1 -0
  13. data/lib/rspec/expectations/extensions/kernel.rb +52 -0
  14. data/lib/rspec/expectations/fail_with.rb +43 -0
  15. data/lib/rspec/expectations/handler.rb +50 -0
  16. data/lib/rspec/matchers.rb +195 -0
  17. data/lib/rspec/matchers/be.rb +210 -0
  18. data/lib/rspec/matchers/be_close.rb +32 -0
  19. data/lib/rspec/matchers/be_instance_of.rb +26 -0
  20. data/lib/rspec/matchers/be_kind_of.rb +26 -0
  21. data/lib/rspec/matchers/change.rb +151 -0
  22. data/lib/rspec/matchers/compatibility.rb +14 -0
  23. data/lib/rspec/matchers/dsl.rb +14 -0
  24. data/lib/rspec/matchers/eql.rb +42 -0
  25. data/lib/rspec/matchers/equal.rb +53 -0
  26. data/lib/rspec/matchers/errors.rb +5 -0
  27. data/lib/rspec/matchers/exist.rb +16 -0
  28. data/lib/rspec/matchers/extensions/instance_exec.rb +23 -0
  29. data/lib/rspec/matchers/generated_descriptions.rb +36 -0
  30. data/lib/rspec/matchers/has.rb +35 -0
  31. data/lib/rspec/matchers/have.rb +151 -0
  32. data/lib/rspec/matchers/include.rb +44 -0
  33. data/lib/rspec/matchers/match.rb +21 -0
  34. data/lib/rspec/matchers/match_array.rb +71 -0
  35. data/lib/rspec/matchers/matcher.rb +86 -0
  36. data/lib/rspec/matchers/method_missing.rb +9 -0
  37. data/lib/rspec/matchers/operator_matcher.rb +78 -0
  38. data/lib/rspec/matchers/pretty.rb +37 -0
  39. data/lib/rspec/matchers/raise_error.rb +129 -0
  40. data/lib/rspec/matchers/respond_to.rb +71 -0
  41. data/lib/rspec/matchers/satisfy.rb +47 -0
  42. data/lib/rspec/matchers/simple_matcher.rb +133 -0
  43. data/lib/rspec/matchers/throw_symbol.rb +104 -0
  44. data/lib/rspec/matchers/wrap_expectation.rb +55 -0
  45. data/rspec-expectations.gemspec +104 -0
  46. data/spec/rspec/expectations/differs/default_spec.rb +128 -0
  47. data/spec/rspec/expectations/extensions/kernel_spec.rb +45 -0
  48. data/spec/rspec/expectations/fail_with_spec.rb +88 -0
  49. data/spec/rspec/expectations/handler_spec.rb +206 -0
  50. data/spec/rspec/expectations/wrap_expectation_spec.rb +30 -0
  51. data/spec/spec.opts +6 -0
  52. data/spec/spec_helper.rb +31 -0
  53. data/spec/suite.rb +1 -0
  54. data/spec/support/macros.rb +29 -0
  55. metadata +135 -0
@@ -0,0 +1,210 @@
1
+ module Rspec
2
+ module Matchers
3
+
4
+ class Be #:nodoc:
5
+ include Rspec::Matchers::Pretty
6
+
7
+ def initialize(*args)
8
+ @expected = args.empty? ? true : set_expected(args.shift)
9
+ @args = args
10
+ @comparison_method = nil
11
+ end
12
+
13
+ def matches?(actual)
14
+ @actual = actual
15
+ handling_predicate? ? run_predicate_on(actual) : match_or_compare(actual)
16
+ end
17
+
18
+ def run_predicate_on(actual)
19
+ begin
20
+ return @result = actual.__send__(predicate, *@args)
21
+ rescue NameError => predicate_missing_error
22
+ "this needs to be here or rcov will not count this branch even though it's executed in a code example"
23
+ end
24
+
25
+ begin
26
+ return @result = actual.__send__(present_tense_predicate, *@args)
27
+ rescue NameError
28
+ raise predicate_missing_error
29
+ end
30
+ end
31
+
32
+ def failure_message_for_should
33
+ if handling_predicate?
34
+ if predicate == :nil?
35
+ "expected nil, got #{@actual.inspect}"
36
+ else
37
+ "expected #{predicate}#{args_to_s} to return true, got #{@result.inspect}"
38
+ end
39
+ else
40
+ "expected #{@comparison_method} #{expected}, got #{@actual.inspect}".gsub(' ',' ')
41
+ end
42
+ end
43
+
44
+ def failure_message_for_should_not
45
+ if handling_predicate?
46
+ if predicate == :nil?
47
+ "expected not nil, got nil"
48
+ else
49
+ "expected #{predicate}#{args_to_s} to return false, got #{@result.inspect}"
50
+ end
51
+ else
52
+ message = <<-MESSAGE
53
+ 'should_not be #{@comparison_method} #{expected}' not only FAILED,
54
+ it is a bit confusing.
55
+ MESSAGE
56
+
57
+ raise message << ([:===,:==].include?(@comparison_method) ?
58
+ "It might be more clearly expressed without the \"be\"?" :
59
+ "It might be more clearly expressed in the positive?")
60
+ end
61
+ end
62
+
63
+ def description
64
+ "#{prefix_to_sentence}#{comparison} #{expected_to_sentence}#{args_to_sentence}".gsub(/\s+/,' ')
65
+ end
66
+
67
+ [:==, :<, :<=, :>=, :>, :===].each do |method|
68
+ define_method method do |expected|
69
+ compare_to(expected, :using => method)
70
+ self
71
+ end
72
+ end
73
+
74
+ private
75
+ def match_or_compare(actual)
76
+ TrueClass === @expected ? @actual : @actual.__send__(comparison_method, @expected)
77
+ end
78
+
79
+ def comparison_method
80
+ @comparison_method || :equal?
81
+ end
82
+
83
+ def expected
84
+ @expected
85
+ end
86
+
87
+ def compare_to(expected, opts)
88
+ @expected, @comparison_method = expected, opts[:using]
89
+ end
90
+
91
+ def set_expected(expected)
92
+ Symbol === expected ? parse_expected(expected) : expected
93
+ end
94
+
95
+ def parse_expected(expected)
96
+ ["be_an_","be_a_","be_"].each do |prefix|
97
+ handling_predicate!
98
+ if expected.to_s =~ /^#{prefix}/
99
+ set_prefix(prefix)
100
+ expected = expected.to_s.sub(prefix,"")
101
+ [true, false, nil].each do |val|
102
+ return val if val.to_s == expected
103
+ end
104
+ return expected.to_sym
105
+ end
106
+ end
107
+ end
108
+
109
+ def set_prefix(prefix)
110
+ @prefix = prefix
111
+ end
112
+
113
+ def prefix
114
+ # FIXME - this is a bit goofy - but we get failures
115
+ # if just defining @prefix = nil in initialize
116
+ @prefix = nil unless defined?(@prefix)
117
+ @prefix
118
+ end
119
+
120
+ def handling_predicate!
121
+ @handling_predicate = true
122
+ end
123
+
124
+ def handling_predicate?
125
+ return false if [true, false, nil].include?(expected)
126
+ # FIXME - this is a bit goofy - but we get failures
127
+ # if just defining @handling_predicate = nil or false in initialize
128
+ return defined?(@handling_predicate) ? @handling_predicate : nil
129
+ end
130
+
131
+ def predicate
132
+ "#{@expected.to_s}?".to_sym
133
+ end
134
+
135
+ def present_tense_predicate
136
+ "#{@expected.to_s}s?".to_sym
137
+ end
138
+
139
+ def args_to_s
140
+ @args.empty? ? "" : parenthesize(inspected_args.join(', '))
141
+ end
142
+
143
+ def parenthesize(string)
144
+ return "(#{string})"
145
+ end
146
+
147
+ def inspected_args
148
+ @args.collect{|a| a.inspect}
149
+ end
150
+
151
+ def comparison
152
+ @comparison_method.nil? ? " " : "be #{@comparison_method.to_s} "
153
+ end
154
+
155
+ def expected_to_sentence
156
+ split_words(expected)
157
+ end
158
+
159
+ def prefix_to_sentence
160
+ split_words(prefix)
161
+ end
162
+
163
+ def args_to_sentence
164
+ to_sentence(@args)
165
+ end
166
+
167
+ end
168
+
169
+ # :call-seq:
170
+ # should be_true
171
+ # should be_false
172
+ # should be_nil
173
+ # should be_[arbitrary_predicate](*args)
174
+ # should_not be_nil
175
+ # should_not be_[arbitrary_predicate](*args)
176
+ #
177
+ # Given true, false, or nil, will pass if actual value is
178
+ # true, false or nil (respectively). Given no args means
179
+ # the caller should satisfy an if condition (to be or not to be).
180
+ #
181
+ # Predicates are any Ruby method that ends in a "?" and returns true or false.
182
+ # Given be_ followed by arbitrary_predicate (without the "?"), RSpec will match
183
+ # convert that into a query against the target object.
184
+ #
185
+ # The arbitrary_predicate feature will handle any predicate
186
+ # prefixed with "be_an_" (e.g. be_an_instance_of), "be_a_" (e.g. be_a_kind_of)
187
+ # or "be_" (e.g. be_empty), letting you choose the prefix that best suits the predicate.
188
+ #
189
+ # == Examples
190
+ #
191
+ # target.should be_true
192
+ # target.should be_false
193
+ # target.should be_nil
194
+ # target.should_not be_nil
195
+ #
196
+ # collection.should be_empty #passes if target.empty?
197
+ # target.should_not be_empty #passes unless target.empty?
198
+ # target.should_not be_old_enough(16) #passes unless target.old_enough?(16)
199
+ def be(*args)
200
+ Matchers::Be.new(*args)
201
+ end
202
+
203
+ # passes if target.kind_of?(klass)
204
+ def be_a(klass)
205
+ be_a_kind_of(klass)
206
+ end
207
+
208
+ alias_method :be_an, :be_a
209
+ end
210
+ end
@@ -0,0 +1,32 @@
1
+ module Rspec
2
+ module Matchers
3
+ # :call-seq:
4
+ # should be_close(expected, delta)
5
+ # should_not be_close(expected, delta)
6
+ #
7
+ # Passes if actual == expected +/- delta
8
+ #
9
+ # == Example
10
+ #
11
+ # result.should be_close(3.0, 0.5)
12
+ def be_close(expected, delta)
13
+ Matcher.new :be_close, expected, delta do |_expected_, _delta_|
14
+ match do |actual|
15
+ (actual - _expected_).abs < _delta_
16
+ end
17
+
18
+ failure_message_for_should do |actual|
19
+ "expected #{_expected_} +/- (< #{_delta_}), got #{actual}"
20
+ end
21
+
22
+ failure_message_for_should_not do |actual|
23
+ "expected #{_expected_} +/- (< #{_delta_}), got #{actual}"
24
+ end
25
+
26
+ description do
27
+ "be close to #{_expected_} (within +- #{_delta_})"
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,26 @@
1
+ module Rspec
2
+ module Matchers
3
+ # :call-seq:
4
+ # should be_instance_of(expected)
5
+ # should be_an_instance_of(expected)
6
+ # should_not be_instance_of(expected)
7
+ # should_not be_an_instance_of(expected)
8
+ #
9
+ # Passes if actual.instance_of?(expected)
10
+ #
11
+ # == Examples
12
+ #
13
+ # 5.should be_instance_of(Fixnum)
14
+ # 5.should_not be_instance_of(Numeric)
15
+ # 5.should_not be_instance_of(Float)
16
+ def be_an_instance_of(expected)
17
+ Matcher.new :be_an_instance_of, expected do |_expected_|
18
+ match do |actual|
19
+ actual.instance_of?(_expected_)
20
+ end
21
+ end
22
+ end
23
+
24
+ alias_method :be_instance_of, :be_an_instance_of
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ module Rspec
2
+ module Matchers
3
+ # :call-seq:
4
+ # should be_kind_of(expected)
5
+ # should be_a_kind_of(expected)
6
+ # should_not be_kind_of(expected)
7
+ # should_not be_a_kind_of(expected)
8
+ #
9
+ # Passes if actual.kind_of?(expected)
10
+ #
11
+ # == Examples
12
+ #
13
+ # 5.should be_kind_of(Fixnum)
14
+ # 5.should be_kind_of(Numeric)
15
+ # 5.should_not be_kind_of(Float)
16
+ def be_a_kind_of(expected)
17
+ Matcher.new :be_a_kind_of, expected do |_expected_|
18
+ match do |actual|
19
+ actual.kind_of?(_expected_)
20
+ end
21
+ end
22
+ end
23
+
24
+ alias_method :be_kind_of, :be_a_kind_of
25
+ end
26
+ end
@@ -0,0 +1,151 @@
1
+ module Rspec
2
+ module Matchers
3
+
4
+ #Based on patch from Wilson Bilkovich
5
+ class Change #:nodoc:
6
+ def initialize(receiver=nil, message=nil, &block)
7
+ @message = message || "result"
8
+ @value_proc = block || lambda {receiver.__send__(message)}
9
+ @to = @from = @minimum = @maximum = @amount = nil
10
+ end
11
+
12
+ def matches?(event_proc)
13
+ raise_block_syntax_error if block_given?
14
+
15
+ @before = evaluate_value_proc
16
+ event_proc.call
17
+ @after = evaluate_value_proc
18
+
19
+ return (@to = false) if @from unless @from == @before
20
+ return false if @to unless @to == @after
21
+ return (@before + @amount == @after) if @amount
22
+ return ((@after - @before) >= @minimum) if @minimum
23
+ return ((@after - @before) <= @maximum) if @maximum
24
+ return @before != @after
25
+ end
26
+
27
+ def raise_block_syntax_error
28
+ raise MatcherError.new(<<-MESSAGE
29
+ block passed to should or should_not change must use {} instead of do/end
30
+ MESSAGE
31
+ )
32
+ end
33
+
34
+ def evaluate_value_proc
35
+ @value_proc.call
36
+ end
37
+
38
+ def failure_message_for_should
39
+ if @to
40
+ "#{@message} should have been changed to #{@to.inspect}, but is now #{@after.inspect}"
41
+ elsif @from
42
+ "#{@message} should have initially been #{@from.inspect}, but was #{@before.inspect}"
43
+ elsif @amount
44
+ "#{@message} should have been changed by #{@amount.inspect}, but was changed by #{actual_delta.inspect}"
45
+ elsif @minimum
46
+ "#{@message} should have been changed by at least #{@minimum.inspect}, but was changed by #{actual_delta.inspect}"
47
+ elsif @maximum
48
+ "#{@message} should have been changed by at most #{@maximum.inspect}, but was changed by #{actual_delta.inspect}"
49
+ else
50
+ "#{@message} should have changed, but is still #{@before.inspect}"
51
+ end
52
+ end
53
+
54
+ def actual_delta
55
+ @after - @before
56
+ end
57
+
58
+ def failure_message_for_should_not
59
+ "#{@message} should not have changed, but did change from #{@before.inspect} to #{@after.inspect}"
60
+ end
61
+
62
+ def by(amount)
63
+ @amount = amount
64
+ self
65
+ end
66
+
67
+ def by_at_least(minimum)
68
+ @minimum = minimum
69
+ self
70
+ end
71
+
72
+ def by_at_most(maximum)
73
+ @maximum = maximum
74
+ self
75
+ end
76
+
77
+ def to(to)
78
+ @to = to
79
+ self
80
+ end
81
+
82
+ def from (from)
83
+ @from = from
84
+ self
85
+ end
86
+
87
+ def description
88
+ "change ##{@message}"
89
+ end
90
+ end
91
+
92
+ # :call-seq:
93
+ # should change(receiver, message, &block)
94
+ # should change(receiver, message, &block).by(value)
95
+ # should change(receiver, message, &block).from(old).to(new)
96
+ # should_not change(receiver, message, &block)
97
+ #
98
+ # Allows you to specify that a Proc will cause some value to change.
99
+ #
100
+ # == Examples
101
+ #
102
+ # lambda {
103
+ # team.add_player(player)
104
+ # }.should change(roster, :count)
105
+ #
106
+ # lambda {
107
+ # team.add_player(player)
108
+ # }.should change(roster, :count).by(1)
109
+ #
110
+ # lambda {
111
+ # team.add_player(player)
112
+ # }.should change(roster, :count).by_at_least(1)
113
+ #
114
+ # lambda {
115
+ # team.add_player(player)
116
+ # }.should change(roster, :count).by_at_most(1)
117
+ #
118
+ # string = "string"
119
+ # lambda {
120
+ # string.reverse!
121
+ # }.should change { string }.from("string").to("gnirts")
122
+ #
123
+ # lambda {
124
+ # person.happy_birthday
125
+ # }.should change(person, :birthday).from(32).to(33)
126
+ #
127
+ # lambda {
128
+ # employee.develop_great_new_social_networking_app
129
+ # }.should change(employee, :title).from("Mail Clerk").to("CEO")
130
+ #
131
+ # Evaluates <tt>receiver.message</tt> or <tt>block</tt> before and after
132
+ # it evaluates the c object (generated by the lambdas in the examples
133
+ # above).
134
+ #
135
+ # Then compares the values before and after the <tt>receiver.message</tt>
136
+ # and evaluates the difference compared to the expected difference.
137
+ #
138
+ # == WARNING
139
+ # <tt>should_not change</tt> only supports the form with no
140
+ # subsequent calls to <tt>by</tt>, <tt>by_at_least</tt>,
141
+ # <tt>by_at_most</tt>, <tt>to</tt> or <tt>from</tt>.
142
+ #
143
+ # blocks passed to <tt>should</tt> <tt>change</tt> and <tt>should_not</tt>
144
+ # <tt>change</tt> must use the <tt>{}</tt> form (<tt>do/end</tt> is not
145
+ # supported).
146
+ #
147
+ def change(receiver=nil, message=nil, &block)
148
+ Matchers::Change.new(receiver, message, &block)
149
+ end
150
+ end
151
+ end