rspec-expectations 2.11.3 → 2.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/Changelog.md +25 -2
  2. data/README.md +5 -1
  3. data/features/built_in_matchers/be.feature +4 -4
  4. data/features/built_in_matchers/be_within.feature +1 -1
  5. data/features/built_in_matchers/cover.feature +1 -1
  6. data/features/built_in_matchers/end_with.feature +2 -2
  7. data/features/built_in_matchers/equality.feature +5 -5
  8. data/features/built_in_matchers/exist.feature +1 -1
  9. data/features/built_in_matchers/expect_change.feature +3 -3
  10. data/features/built_in_matchers/expect_error.feature +4 -4
  11. data/features/built_in_matchers/have.feature +2 -2
  12. data/features/built_in_matchers/include.feature +3 -3
  13. data/features/built_in_matchers/match.feature +2 -2
  14. data/features/built_in_matchers/operators.feature +3 -3
  15. data/features/built_in_matchers/predicates.feature +9 -8
  16. data/features/built_in_matchers/respond_to.feature +2 -2
  17. data/features/built_in_matchers/satisfy.feature +1 -1
  18. data/features/built_in_matchers/start_with.feature +2 -2
  19. data/features/built_in_matchers/throw_symbol.feature +3 -3
  20. data/features/built_in_matchers/types.feature +2 -2
  21. data/features/built_in_matchers/yield.feature +5 -5
  22. data/features/custom_matchers/access_running_example.feature +3 -3
  23. data/features/custom_matchers/define_diffable_matcher.feature +1 -1
  24. data/features/custom_matchers/define_matcher.feature +12 -12
  25. data/features/custom_matchers/define_matcher_outside_rspec.feature +1 -1
  26. data/features/custom_matchers/define_matcher_with_fluent_interface.feature +1 -1
  27. data/features/customized_message.feature +1 -1
  28. data/features/diffing.feature +4 -4
  29. data/features/implicit_docstrings.feature +2 -2
  30. data/features/test_frameworks/test_unit.feature +1 -1
  31. data/lib/rspec/expectations/differ.rb +35 -1
  32. data/lib/rspec/expectations/handler.rb +21 -6
  33. data/lib/rspec/expectations/version.rb +1 -1
  34. data/lib/rspec/matchers/built_in/be_instance_of.rb +4 -0
  35. data/lib/rspec/matchers/built_in/include.rb +3 -1
  36. data/lib/rspec/matchers/built_in/match_array.rb +12 -6
  37. data/lib/rspec/matchers/built_in/raise_error.rb +17 -7
  38. data/lib/rspec/matchers/built_in/yield.rb +5 -5
  39. data/lib/rspec/matchers/configuration.rb +42 -0
  40. data/lib/rspec/matchers/generated_descriptions.rb +2 -3
  41. data/spec/rspec/expectations/differ_spec.rb +24 -0
  42. data/spec/rspec/expectations/handler_spec.rb +40 -40
  43. data/spec/rspec/expectations/syntax_spec.rb +35 -0
  44. data/spec/rspec/matchers/be_instance_of_spec.rb +19 -2
  45. data/spec/rspec/matchers/be_spec.rb +10 -10
  46. data/spec/rspec/matchers/configuration_spec.rb +155 -123
  47. data/spec/rspec/matchers/dsl_spec.rb +8 -8
  48. data/spec/rspec/matchers/have_spec.rb +8 -38
  49. data/spec/rspec/matchers/include_spec.rb +6 -0
  50. data/spec/rspec/matchers/match_array_spec.rb +14 -0
  51. data/spec/rspec/matchers/raise_error_spec.rb +89 -38
  52. data/spec/rspec/matchers/start_with_end_with_spec.rb +1 -1
  53. data/spec/rspec/matchers/yield_spec.rb +35 -0
  54. metadata +70 -78
@@ -29,7 +29,9 @@ module RSpec
29
29
  def perform_match(predicate, hash_predicate, actuals, expecteds)
30
30
  expecteds.send(predicate) do |expected|
31
31
  if comparing_hash_values?(actuals, expected)
32
- expected.send(hash_predicate) {|k,v| actuals[k] == v}
32
+ expected.send(hash_predicate) {|k,v|
33
+ actuals.has_key?(k) && actuals[k] == v
34
+ }
33
35
  elsif comparing_hash_keys?(actuals, expected)
34
36
  actuals.has_key?(expected)
35
37
  else
@@ -3,16 +3,22 @@ module RSpec
3
3
  module BuiltIn
4
4
  class MatchArray < BaseMatcher
5
5
  def match(expected, actual)
6
+ return false unless actual.respond_to? :to_ary
6
7
  @extra_items = difference_between_arrays(actual, expected)
7
8
  @missing_items = difference_between_arrays(expected, actual)
8
9
  @extra_items.empty? & @missing_items.empty?
9
10
  end
10
11
 
11
12
  def failure_message_for_should
12
- message = "expected collection contained: #{safe_sort(expected).inspect}\n"
13
- message += "actual collection contained: #{safe_sort(actual).inspect}\n"
14
- message += "the missing elements were: #{safe_sort(@missing_items).inspect}\n" unless @missing_items.empty?
15
- message += "the extra elements were: #{safe_sort(@extra_items).inspect}\n" unless @extra_items.empty?
13
+ if actual.respond_to? :to_ary
14
+ message = "expected collection contained: #{safe_sort(expected).inspect}\n"
15
+ message += "actual collection contained: #{safe_sort(actual).inspect}\n"
16
+ message += "the missing elements were: #{safe_sort(@missing_items).inspect}\n" unless @missing_items.empty?
17
+ message += "the extra elements were: #{safe_sort(@extra_items).inspect}\n" unless @extra_items.empty?
18
+ else
19
+ message = "expected an array, actual collection was #{actual.inspect}"
20
+ end
21
+
16
22
  message
17
23
  end
18
24
 
@@ -31,8 +37,8 @@ module RSpec
31
37
  end
32
38
 
33
39
  def difference_between_arrays(array_1, array_2)
34
- difference = array_1.dup
35
- array_2.each do |element|
40
+ difference = array_1.to_ary.dup
41
+ array_2.to_ary.each do |element|
36
42
  if index = difference.index(element)
37
43
  difference.delete_at(index)
38
44
  end
@@ -13,7 +13,7 @@ module RSpec
13
13
  end
14
14
  end
15
15
 
16
- def matches?(given_proc)
16
+ def matches?(given_proc, negative_expectation = false)
17
17
  @raised_expected_error = false
18
18
  @with_expected_message = false
19
19
  @eval_block = false
@@ -29,7 +29,7 @@ module RSpec
29
29
  "http://eigenclass.org/hiki.rb?rcov-0.8.0"
30
30
  end
31
31
 
32
- unless negative_expectation?
32
+ unless negative_expectation
33
33
  eval_block if @raised_expected_error && @with_expected_message && @block
34
34
  end
35
35
  ensure
@@ -37,6 +37,10 @@ module RSpec
37
37
  end
38
38
  alias == matches?
39
39
 
40
+ def does_not_match?(given_proc)
41
+ !matches?(given_proc, :negative_expectation)
42
+ end
43
+
40
44
  def eval_block
41
45
  @eval_block = true
42
46
  begin
@@ -83,13 +87,19 @@ module RSpec
83
87
  end
84
88
  end
85
89
 
86
- def given_error
87
- @actual_error.nil? ? " but nothing was raised" : ", got #{@actual_error.inspect}"
90
+ def format_backtrace(backtrace)
91
+ formatter = Matchers.configuration.backtrace_formatter
92
+ formatter.format_backtrace(backtrace)
88
93
  end
89
94
 
90
- def negative_expectation?
91
- # YES - I'm a bad person... help me find a better way - ryand
92
- caller.first(3).find { |s| s =~ /should_not/ }
95
+ def given_error
96
+ return " but nothing was raised" unless @actual_error
97
+
98
+ backtrace = format_backtrace(@actual_error.backtrace)
99
+ [
100
+ ", got #{@actual_error.inspect} with backtrace:",
101
+ *backtrace
102
+ ].join("\n # ")
93
103
  end
94
104
  end
95
105
  end
@@ -83,7 +83,7 @@ module RSpec
83
83
 
84
84
  def matches?(block)
85
85
  @probe = YieldProbe.probe(block)
86
- @probe.yielded_once?(:yield_with_no_args) && @probe.single_yield_args.none?
86
+ @probe.yielded_once?(:yield_with_no_args) && @probe.single_yield_args.empty?
87
87
  end
88
88
 
89
89
  def failure_message_for_should
@@ -127,7 +127,7 @@ module RSpec
127
127
 
128
128
  def description
129
129
  desc = "yield with args"
130
- desc << "(" + @expected.map { |e| e.inspect }.join(", ") + ")" if @expected.any?
130
+ desc << "(" + @expected.map { |e| e.inspect }.join(", ") + ")" unless @expected.empty?
131
131
  desc
132
132
  end
133
133
 
@@ -152,9 +152,9 @@ module RSpec
152
152
  end
153
153
 
154
154
  def args_match?
155
- if @expected.none? # expect {...}.to yield_with_args
156
- @positive_args_failure = "yielded with no arguments" if @actual.none?
157
- return @actual.any?
155
+ if @expected.empty? # expect {...}.to yield_with_args
156
+ @positive_args_failure = "yielded with no arguments" if @actual.empty?
157
+ return !@actual.empty?
158
158
  end
159
159
 
160
160
  unless match = all_args_match?
@@ -39,6 +39,19 @@ module RSpec
39
39
  syntaxes
40
40
  end
41
41
 
42
+ # color config for expectations
43
+ # fallback if rspec core not available
44
+ if ::RSpec.respond_to?(:configuration)
45
+ def color?
46
+ ::RSpec.configuration.color_enabled?
47
+ end
48
+ else
49
+ attr_writer :color
50
+ def color?
51
+ @color
52
+ end
53
+ end
54
+
42
55
  # Adds `should` and `should_not` to the given classes
43
56
  # or modules. This can be used to ensure `should` works
44
57
  # properly on things like proxy objects (particular
@@ -51,6 +64,35 @@ module RSpec
51
64
  Expectations::Syntax.enable_should(mod)
52
65
  end
53
66
  end
67
+
68
+ # Sets or gets the backtrace formatter. The backtrace formatter should
69
+ # implement `#format_backtrace(Array<String>)`. This is used
70
+ # to format backtraces of errors handled by the `raise_error`
71
+ # matcher.
72
+ #
73
+ # If you are using rspec-core, rspec-core's backtrace formatting
74
+ # will be used (including respecting the presence or absence of
75
+ # the `--backtrace` option).
76
+ #
77
+ # @overload backtrace_formatter
78
+ # @return [#format_backtrace] the backtrace formatter
79
+ # @overload backtrace_formatter=
80
+ # @param value [#format_backtrace] sets the backtrace formatter
81
+ attr_writer :backtrace_formatter
82
+ def backtrace_formatter
83
+ @backtrace_formatter ||= if defined?(::RSpec::Core::BacktraceFormatter)
84
+ ::RSpec::Core::BacktraceFormatter
85
+ else
86
+ NullBacktraceFormatter
87
+ end
88
+ end
89
+
90
+ # @api private
91
+ NullBacktraceFormatter = Module.new do
92
+ def self.format_backtrace(backtrace)
93
+ backtrace
94
+ end
95
+ end
54
96
  end
55
97
 
56
98
  # The configuration object
@@ -13,9 +13,9 @@ module RSpec
13
13
  return nil if last_should.nil?
14
14
  "#{last_should.to_s.gsub('_',' ')} #{last_description}"
15
15
  end
16
-
16
+
17
17
  private
18
-
18
+
19
19
  def self.last_description
20
20
  last_matcher.respond_to?(:description) ? last_matcher.description : <<-MESSAGE
21
21
  When you call a matcher in an example without a String, like this:
@@ -33,4 +33,3 @@ MESSAGE
33
33
  end
34
34
  end
35
35
  end
36
-
@@ -4,8 +4,14 @@ require 'ostruct'
4
4
  module RSpec
5
5
  module Expectations
6
6
  describe Differ do
7
+ context "without --color" do
8
+
9
+ before { RSpec::Matchers.configuration.stub(:color? => false) }
10
+
7
11
  let(:differ) { RSpec::Expectations::Differ.new }
8
12
 
13
+ # color disabled context
14
+
9
15
  describe '#diff_as_string' do
10
16
  it "outputs unified diff of two strings" do
11
17
  expected="foo\nbar\nzap\nthis\nis\nsoo\nvery\nvery\nequal\ninsert\na\nline\n"
@@ -149,5 +155,23 @@ EOD
149
155
  end
150
156
  end
151
157
  end
158
+
159
+ context "with --color" do
160
+ before { RSpec::Matchers.configuration.stub(:color? => true) }
161
+
162
+ let(:differ) { RSpec::Expectations::Differ.new }
163
+
164
+ it "outputs colored diffs" do
165
+ expected = "foo bar baz"
166
+ actual = "foo bang baz"
167
+ expected_diff = "\n\e[34m@@ -1,2 +1,2 @@\n\e[0m\e[31m-foo bang baz\n\e[0m\e[32m+foo bar baz\n\e[0m"
168
+
169
+
170
+ diff = differ.diff_as_string(expected,actual)
171
+ diff.should == expected_diff
172
+ end
173
+ end
174
+
175
+ end
152
176
  end
153
177
  end
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  module ExampleExpectations
4
-
4
+
5
5
  class ArbitraryMatcher
6
6
  def initialize(*args, &block)
7
7
  if args.last.is_a? Hash
@@ -10,38 +10,38 @@ module ExampleExpectations
10
10
  @expected = block.call if block
11
11
  @block = block
12
12
  end
13
-
13
+
14
14
  def matches?(target)
15
15
  @target = target
16
16
  return @expected == target
17
17
  end
18
-
18
+
19
19
  def with(new_value)
20
20
  @expected = new_value
21
21
  self
22
22
  end
23
-
23
+
24
24
  def failure_message
25
25
  "expected #{@expected}, got #{@target}"
26
26
  end
27
-
27
+
28
28
  def negative_failure_message
29
29
  "expected not #{@expected}, got #{@target}"
30
30
  end
31
31
  end
32
-
32
+
33
33
  class PositiveOnlyMatcher < ArbitraryMatcher
34
34
  undef negative_failure_message rescue nil
35
35
  end
36
-
36
+
37
37
  def arbitrary_matcher(*args, &block)
38
38
  ArbitraryMatcher.new(*args, &block)
39
39
  end
40
-
40
+
41
41
  def positive_only_matcher(*args, &block)
42
42
  PositiveOnlyMatcher.new(*args, &block)
43
43
  end
44
-
44
+
45
45
  end
46
46
 
47
47
  module RSpec
@@ -54,23 +54,23 @@ module RSpec
54
54
  matcher.should_receive(:matches?).with(actual).and_return(true)
55
55
  RSpec::Expectations::PositiveExpectationHandler.handle_matcher(actual, matcher)
56
56
  end
57
-
57
+
58
58
  it "returns the match value" do
59
59
  matcher = mock("matcher")
60
60
  actual = Object.new
61
61
  matcher.should_receive(:matches?).with(actual).and_return(:this_value)
62
62
  RSpec::Expectations::PositiveExpectationHandler.handle_matcher(actual, matcher).should == :this_value
63
63
  end
64
-
64
+
65
65
  it "calls failure_message_for_should if the matcher implements it" do
66
66
  matcher = mock("matcher", :failure_message_for_should => "message", :matches? => false)
67
67
  actual = Object.new
68
-
68
+
69
69
  ::RSpec::Expectations.should_receive(:fail_with).with("message")
70
-
70
+
71
71
  RSpec::Expectations::PositiveExpectationHandler.handle_matcher(actual, matcher)
72
72
  end
73
-
73
+
74
74
  it "calls fail if matcher.diffable?" do
75
75
  matcher = mock("matcher",
76
76
  :diffable? => true,
@@ -80,28 +80,28 @@ module RSpec
80
80
  :actual => 2
81
81
  )
82
82
  actual = Object.new
83
-
83
+
84
84
  ::RSpec::Expectations.should_receive(:fail_with).with("message", 1, 2)
85
-
85
+
86
86
  RSpec::Expectations::PositiveExpectationHandler.handle_matcher(actual, matcher)
87
87
  end
88
-
88
+
89
89
  it "calls failure_message if the matcher does not implement failure_message_for_should" do
90
90
  matcher = mock("matcher", :failure_message => "message", :matches? => false)
91
91
  actual = Object.new
92
-
92
+
93
93
  ::RSpec::Expectations.should_receive(:fail_with).with("message")
94
-
94
+
95
95
  RSpec::Expectations::PositiveExpectationHandler.handle_matcher(actual, matcher)
96
-
96
+
97
97
  end
98
-
98
+
99
99
  it "appends the :or message in the options hash passed to should" do
100
100
  matcher = mock("matcher", :failure_message_for_should => "message", :matches? => false)
101
101
  actual = Object.new
102
-
102
+
103
103
  ::RSpec::Expectations.should_receive(:fail_with).with("custom")
104
-
104
+
105
105
  RSpec::Expectations::PositiveExpectationHandler.handle_matcher(actual, matcher, "custom")
106
106
  end
107
107
  end
@@ -123,7 +123,7 @@ module RSpec
123
123
  matcher.should_receive(:matches?).with(actual).and_return(false)
124
124
  RSpec::Expectations::NegativeExpectationHandler.handle_matcher(actual, matcher)
125
125
  end
126
-
126
+
127
127
  it "returns the match value" do
128
128
  matcher = mock("matcher")
129
129
  actual = Object.new
@@ -132,28 +132,28 @@ module RSpec
132
132
  RSpec::Expectations::NegativeExpectationHandler.handle_matcher(actual, matcher).should be_false
133
133
  end
134
134
 
135
-
135
+
136
136
  it "calls failure_message_for_should_not if the matcher implements it" do
137
137
  matcher = mock("matcher", :failure_message_for_should_not => "message", :matches? => true)
138
138
  actual = Object.new
139
-
139
+
140
140
  ::RSpec::Expectations.should_receive(:fail_with).with("message")
141
-
141
+
142
142
  RSpec::Expectations::NegativeExpectationHandler.handle_matcher(actual, matcher)
143
-
143
+
144
144
  end
145
-
145
+
146
146
  it "calls negative_failure_message if the matcher does not implement failure_message_for_should_not" do
147
147
  matcher = mock("matcher", :negative_failure_message => "message", :matches? => true)
148
148
  actual = Object.new
149
-
149
+
150
150
  ::RSpec::Expectations.should_receive(:fail_with).with("message")
151
-
151
+
152
152
  RSpec::Expectations::NegativeExpectationHandler.handle_matcher(actual, matcher)
153
-
153
+
154
154
  end
155
155
 
156
-
156
+
157
157
  it "calls fail if matcher.diffable?" do
158
158
  matcher = mock("matcher",
159
159
  :diffable? => true,
@@ -163,27 +163,27 @@ module RSpec
163
163
  :actual => 2
164
164
  )
165
165
  actual = Object.new
166
-
166
+
167
167
  ::RSpec::Expectations.should_receive(:fail_with).with("message", 1, 2)
168
-
168
+
169
169
  RSpec::Expectations::NegativeExpectationHandler.handle_matcher(actual, matcher)
170
170
  end
171
171
 
172
172
  it "appends the :or message in the options hash passed to should" do
173
173
  matcher = mock("matcher", :failure_message_for_should_not => "message", :matches? => true)
174
174
  actual = Object.new
175
-
175
+
176
176
  ::RSpec::Expectations.should_receive(:fail_with).with("custom")
177
-
177
+
178
178
  RSpec::Expectations::NegativeExpectationHandler.handle_matcher(actual, matcher, "custom")
179
179
  end
180
180
 
181
181
  end
182
182
  end
183
-
183
+
184
184
  describe PositiveExpectationHandler do
185
185
  include ExampleExpectations
186
-
186
+
187
187
  it "handles submitted args" do
188
188
  5.should arbitrary_matcher(:expected => 5)
189
189
  5.should arbitrary_matcher(:expected => "wrong").with(5)
@@ -200,7 +200,7 @@ module RSpec
200
200
  5.should arbitrary_matcher(:expected => 4) { 5 }
201
201
  5.should arbitrary_matcher(:expected => 4).with(5) { 3 }
202
202
  end
203
-
203
+
204
204
  end
205
205
  end
206
206
  end