rspec-expectations 2.11.3 → 2.12.0

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 (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