rspec 0.7.2 → 0.7.5.1

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 (70) hide show
  1. data/CHANGES +72 -1
  2. data/EXAMPLES.rd +6 -0
  3. data/README +27 -6
  4. data/Rakefile +32 -81
  5. data/bin/drbspec +3 -0
  6. data/bin/spec +2 -3
  7. data/examples/file_accessor_spec.rb +1 -1
  8. data/examples/greeter_spec.rb +30 -0
  9. data/examples/helper_method_example.rb +1 -1
  10. data/examples/io_processor_spec.rb +1 -1
  11. data/examples/mocking_example.rb +1 -1
  12. data/examples/partial_mock_example.rb +1 -1
  13. data/examples/predicate_example.rb +1 -1
  14. data/examples/setup_teardown_example.rb +34 -0
  15. data/examples/spec_helper.rb +1 -0
  16. data/examples/stack_spec.rb +1 -1
  17. data/examples/stubbing_example.rb +1 -1
  18. data/examples/test_case_spec.rb +1 -1
  19. data/lib/spec/callback/callback_container.rb +60 -0
  20. data/lib/spec/callback/extensions/module.rb +24 -0
  21. data/lib/spec/callback/extensions/object.rb +33 -0
  22. data/lib/spec/callback.rb +3 -0
  23. data/lib/spec/expectations/diff.rb +10 -14
  24. data/lib/spec/expectations/extensions/numeric.rb +17 -3
  25. data/lib/spec/expectations/extensions/object.rb +145 -0
  26. data/lib/spec/expectations/extensions/proc.rb +57 -0
  27. data/lib/spec/expectations/extensions/string.rb +22 -0
  28. data/lib/spec/expectations/extensions.rb +2 -2
  29. data/lib/spec/expectations/message_builder.rb +13 -0
  30. data/lib/spec/expectations/should/base.rb +29 -10
  31. data/lib/spec/expectations/should/change.rb +69 -0
  32. data/lib/spec/expectations/should/have.rb +94 -37
  33. data/lib/spec/expectations/should/not.rb +6 -2
  34. data/lib/spec/expectations/should/should.rb +9 -5
  35. data/lib/spec/expectations/should.rb +1 -0
  36. data/lib/spec/expectations/sugar.rb +2 -2
  37. data/lib/spec/expectations.rb +28 -0
  38. data/lib/spec/mocks/error_generator.rb +23 -12
  39. data/lib/spec/mocks/message_expectation.rb +18 -15
  40. data/lib/spec/mocks/mock_handler.rb +10 -9
  41. data/lib/spec/mocks/mock_methods.rb +1 -1
  42. data/lib/spec/rake/spectask.rb +8 -2
  43. data/lib/spec/runner/backtrace_tweaker.rb +34 -25
  44. data/lib/spec/runner/context.rb +56 -7
  45. data/lib/spec/runner/context_eval.rb +33 -3
  46. data/lib/spec/runner/context_runner.rb +24 -11
  47. data/lib/spec/runner/drb_command_line.rb +21 -0
  48. data/lib/spec/runner/execution_context.rb +1 -0
  49. data/lib/spec/runner/extensions/kernel.rb +2 -0
  50. data/lib/spec/runner/extensions/object.rb +26 -18
  51. data/lib/spec/runner/formatter/base_text_formatter.rb +1 -1
  52. data/lib/spec/runner/formatter/html_formatter.rb +94 -74
  53. data/lib/spec/runner/heckle_runner.rb +55 -0
  54. data/lib/spec/runner/option_parser.rb +15 -3
  55. data/lib/spec/runner/reporter.rb +13 -8
  56. data/lib/spec/runner/specification.rb +67 -42
  57. data/lib/spec/runner.rb +1 -1
  58. data/lib/spec/version.rb +6 -5
  59. data/lib/spec.rb +1 -0
  60. metadata +20 -19
  61. data/lib/spec/expectations/extensions/inspect_for_expectation_not_met_error.rb +0 -14
  62. data/lib/spec/expectations/extensions/symbol.rb +0 -5
  63. data/vendor/selenium/README.txt +0 -23
  64. data/vendor/selenium/find_rspecs_home_page.rb +0 -23
  65. data/vendor/selenium/rspec_selenium.rb +0 -33
  66. data/vendor/selenium/start_browser_once.patch +0 -65
  67. data/vendor/watir/README.txt +0 -32
  68. data/vendor/watir/find_rspecs_home_page.rb +0 -21
  69. data/vendor/watir/find_rspecs_home_page.txt +0 -15
  70. data/vendor/watir/rspec_watir.rb +0 -45
@@ -9,23 +9,19 @@ module Spec
9
9
  @@differ = differ
10
10
  end
11
11
 
12
- unless defined?(RSPEC_TESTING)
13
- alias old_default_message default_message
14
- def default_message(expectation, expected=:no_expectation_specified)
15
- result = old_default_message(expectation, expected)
16
-
17
- if expected != :no_expectation_specified
18
- if expected.is_a?(String)
19
- result << "\nDiff:" << @@differ.diff_as_string(@target.to_s, expected)
20
- elsif ! @target.is_a? Proc
21
- result << "\nDiff:" << @@differ.diff_as_object(@target,expected)
22
- end
12
+ alias old_default_message default_message
13
+ def default_message(expectation, expected=:no_expectation_specified)
14
+ result = old_default_message(expectation, expected)
15
+ if expected != :no_expectation_specified
16
+ if expected.is_a?(String)
17
+ result << "\nDiff:" << @@differ.diff_as_string(@target.to_s, expected) unless @@differ.nil?
18
+ elsif ! @target.is_a? Proc
19
+ result << "\nDiff:" << @@differ.diff_as_object(@target, expected) unless @@differ.nil?
23
20
  end
24
-
25
- result
26
21
  end
27
- end
28
22
 
23
+ result
24
+ end
29
25
  end
30
26
  end
31
27
  end
@@ -1,5 +1,19 @@
1
- class Numeric
2
- def close?(other, precision)
3
- (self - other).abs < precision
1
+ module Spec
2
+ module Expectations
3
+ module NumericExpectations
4
+ # Passes if receiver is less than +-delta away from other
5
+ def should_be_close(other, delta)
6
+ should.be._close_for_rspec(other, delta)
7
+ end
8
+
9
+ private
10
+ def _close_for_rspec?(other, delta)
11
+ (self - other).abs < delta
12
+ end
13
+ end
4
14
  end
15
+ end
16
+
17
+ class Numeric
18
+ include Spec::Expectations::NumericExpectations
5
19
  end
@@ -1,9 +1,154 @@
1
1
  module Spec
2
2
  module Expectations
3
+ # rspec adds all of these expectations to every Object (and,
4
+ # implicitly, every Class).
3
5
  module ObjectExpectations
6
+
7
+ # Supports the following expectations:
8
+ # receiver.should == expected #any value
9
+ # Passes if (receiver == expected)
10
+ #
11
+ # receiver.should =~ expected #a regexp
12
+ # Passes if (receiver =~ expected), where expected
13
+ # is a Regexp.
14
+ #
15
+ # NOTE that this does NOT support receiver.should != expected.
16
+ # Instead, use receiver.should_not == expected
4
17
  def should
5
18
  Should::Should.new self
6
19
  end
20
+
21
+ # Supports the following expectations:
22
+ # receiver.should_not == expected #any value
23
+ # Passes unless (receiver == expected)
24
+ #
25
+ # receiver.should_not =~ expected #a regexp
26
+ # Passes unless (receiver =~ expected), where expected
27
+ # is a Regexp.
28
+ def should_not
29
+ should.not
30
+ end
31
+
32
+ # Passes if receiver.equal?(expected)
33
+ def should_equal(expected)
34
+ should.equal(expected)
35
+ end
36
+
37
+ # Passes unless receiver.equal?(expected)
38
+ def should_not_equal(expected)
39
+ should.not.equal(expected)
40
+ end
41
+
42
+ # Passes if receiver.eql?(expected)
43
+ def should_eql(expected)
44
+ should.eql(expected)
45
+ end
46
+
47
+ # Passes unless receiver.eql?(expected)
48
+ def should_not_eql(expected)
49
+ should.not.eql(expected)
50
+ end
51
+
52
+ # Specify that the receiver should have a
53
+ # specified number of items in a named collection. For example:
54
+ #
55
+ # team.should_have(40).players
56
+ #
57
+ # Passes if team.players.size == 40.
58
+ #
59
+ # Works for collections with size() and/or length() methods.
60
+ def should_have(expected)
61
+ should.have(expected)
62
+ end
63
+ alias_method :should_have_exactly, :should_have
64
+
65
+ # Specify that the receiver should have at least a
66
+ # specified number of items in a named collection. For example:
67
+ #
68
+ # team.should_have_at_least(10).players
69
+ #
70
+ # Passes if team.players.size == 10 (or more)
71
+ #
72
+ # Fails if team.players.size == 9 (or less)
73
+ #
74
+ # Works for collections with size() and/or length() methods.
75
+ def should_have_at_least(expected)
76
+ should.have.at_least(expected)
77
+ end
78
+
79
+ # Specify that the receiver should have at most a
80
+ # specified number of items in a named collection. For example:
81
+ #
82
+ # team.should_have_at_most(10).players
83
+ #
84
+ # Passes if team.players.size == 10 (or less)
85
+ #
86
+ # Fails if team.players.size == 11 (or more)
87
+ #
88
+ # Works for collections with size() and/or length() methods.
89
+ def should_have_at_most(expected)
90
+ should.have.at_most(expected)
91
+ end
92
+
93
+ # Passes if receiver.include?(expected)
94
+ def should_include(expected)
95
+ should.include(expected)
96
+ end
97
+
98
+ # Passes unless receiver.include?(expected)
99
+ def should_not_include(expected)
100
+ should.not.include(expected)
101
+ end
102
+
103
+ def should_be(expected = :___no_arg)
104
+ should.be(expected)
105
+ end
106
+
107
+ def should_not_be(expected = :___no_arg)
108
+ should.not.be(expected)
109
+ end
110
+
111
+ # Passes if &block returns true
112
+ def should_satisfy(&block)
113
+ should.satisfy(&block)
114
+ end
115
+
116
+ # Passes unless &block returns true
117
+ def should_not_satisfy(&block)
118
+ should.not.satisfy(&block)
119
+ end
120
+
121
+ # Passes if receiver is an instance of expected_class
122
+ def should_be_an_instance_of(expected_class)
123
+ should.be.an_instance_of(expected_class)
124
+ end
125
+ alias_method :should_be_instance_of, :should_be_an_instance_of
126
+
127
+ # Passes unless receiver is an instance of expected_class
128
+ def should_not_be_an_instance_of(expected_class)
129
+ should.not.be.an_instance_of(expected_class)
130
+ end
131
+
132
+ # Passes if receiver is an instance of either expected_class
133
+ # or a subclass of expected_class
134
+ def should_be_a_kind_of(expected_class)
135
+ should.be.a_kind_of(expected_class)
136
+ end
137
+ alias_method :should_be_kind_of, :should_be_a_kind_of
138
+
139
+ # Passes unless receiver is an instance of either expected_class
140
+ # or a subclass of expected_class
141
+ def should_not_be_a_kind_of(expected_class)
142
+ should.not.be.a_kind_of(expected_class)
143
+ end
144
+
145
+ def should_respond_to(message)
146
+ should.respond_to(message)
147
+ end
148
+
149
+ def should_not_respond_to(message)
150
+ should.not.respond_to(message)
151
+ end
7
152
  end
8
153
  end
9
154
  end
@@ -0,0 +1,57 @@
1
+ module Spec
2
+ module Expectations
3
+ module ProcExpectations
4
+ # Given a receiver and a message (Symbol), specifies that the result
5
+ # of sending that message that receiver should change after
6
+ # executing the proc.
7
+ #
8
+ # lambda { @team.add player }.should_change(@team.players, :size)
9
+ # lambda { @team.add player }.should_change(@team.players, :size).by(1)
10
+ # lambda { @team.add player }.should_change(@team.players, :size).to(23)
11
+ # lambda { @team.add player }.should_change(@team.players, :size).from(22).to(23)
12
+ #
13
+ # You can use a block instead of a message and receiver.
14
+ #
15
+ # lambda { @team.add player }.should_change{@team.players.size}
16
+ # lambda { @team.add player }.should_change{@team.players.size}.by(1)
17
+ # lambda { @team.add player }.should_change{@team.players.size}.to(23)
18
+ # lambda { @team.add player }.should_change{@team.players.size}.from(22).to(23)
19
+ def should_change(receiver=nil, message=nil, &block)
20
+ should.change(receiver, message, &block)
21
+ end
22
+
23
+ # Given a receiver and a message (Symbol), specifies that the result
24
+ # of sending that message that receiver should NOT change after
25
+ # executing the proc.
26
+ #
27
+ # lambda { @team.add player }.should_not_change(@team.players, :size)
28
+ #
29
+ # You can use a block instead of a message and receiver.
30
+ #
31
+ # lambda { @team.add player }.should_not_change{@team.players.size}
32
+ def should_not_change(receiver, message)
33
+ should.not.change(receiver, message)
34
+ end
35
+
36
+ def should_raise(exception=Exception, message=nil)
37
+ should.raise(exception, message)
38
+ end
39
+
40
+ def should_not_raise(exception=Exception, message=nil)
41
+ should.not.raise(exception, message)
42
+ end
43
+
44
+ def should_throw(symbol)
45
+ should.throw(symbol)
46
+ end
47
+
48
+ def should_not_throw(symbol=:___this_is_a_symbol_that_will_likely_never_occur___)
49
+ should.not.throw(symbol)
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ class Proc
56
+ include Spec::Expectations::ProcExpectations
57
+ end
@@ -0,0 +1,22 @@
1
+ module Spec
2
+ module Expectations
3
+ # rspec adds all of these expectations to every String object.
4
+ module StringExpectations
5
+
6
+ # Passes if receiver =~ expression
7
+ def should_match(expression)
8
+ should.match(expression)
9
+ end
10
+
11
+ # Passes unless receiver =~ expression
12
+ def should_not_match(expression)
13
+ should.not.match(expression)
14
+ end
15
+
16
+ end
17
+ end
18
+ end
19
+
20
+ class String
21
+ include Spec::Expectations::StringExpectations
22
+ end
@@ -1,4 +1,4 @@
1
1
  require 'spec/expectations/extensions/object'
2
+ require 'spec/expectations/extensions/proc'
2
3
  require 'spec/expectations/extensions/numeric'
3
- require 'spec/expectations/extensions/symbol'
4
- require 'spec/expectations/extensions/inspect_for_expectation_not_met_error'
4
+ require 'spec/expectations/extensions/string'
@@ -0,0 +1,13 @@
1
+ module Spec
2
+ module Expectations
3
+ # TODO - DAC - This is mid-refactoring right now - I'd like to get ALL failure messages
4
+ # for rspec and rspec_on_rails generated by this class so that we can
5
+ # make any enhancements, improvements in one place. Right now it's pretty
6
+ # scattered.
7
+ class MessageBuilder
8
+ def build_message(actual, expectation, expected)
9
+ "#{actual.inspect} #{expectation} #{expected.inspect}"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -2,26 +2,44 @@ module Spec
2
2
  module Expectations
3
3
  module Should
4
4
  class Base
5
+
6
+ def <(expected)
7
+ __delegate_method_missing_to_target "<", "<", expected
8
+ end
9
+
10
+ def <=(expected)
11
+ __delegate_method_missing_to_target "<=", "<=", expected
12
+ end
13
+
14
+ def ==(expected)
15
+ __delegate_method_missing_to_target "==", "==", expected
16
+ end
17
+
18
+ def =~(expected)
19
+ __delegate_method_missing_to_target "=~", "=~", expected
20
+ end
21
+
22
+ def >=(expected)
23
+ __delegate_method_missing_to_target ">=", ">=", expected
24
+ end
25
+
26
+ def >(expected)
27
+ __delegate_method_missing_to_target ">", ">", expected
28
+ end
5
29
 
6
- instance_methods.each { |m| undef_method m unless m =~ /^(__|\w)/ }
7
-
8
- def default_message(expectation, expected=:no_expectation_specified)
9
- message = "#{@target.inspect_for_expectation_not_met_error} #{expectation}"
10
- if (expected != :no_expectation_specified)
11
- message << " " << expected.inspect_for_expectation_not_met_error
12
- end
13
- message
30
+ def default_message(expectation, expected=nil)
31
+ Spec::Expectations.build_message(@target, expectation, expected)
14
32
  end
15
33
 
16
34
  def fail_with_message(message)
17
- Kernel::raise(Spec::Expectations::ExpectationNotMetError.new(message))
35
+ Spec::Expectations.fail_with(message)
18
36
  end
19
37
 
20
38
  def find_supported_sym(original_sym)
21
39
  ["#{original_sym}?", "#{original_sym}s?"].each do |alternate_sym|
22
40
  return alternate_sym.to_s if @target.respond_to?(alternate_sym.to_s)
23
41
  end
24
- return original_sym.supported_by_rspec? ? original_sym : "#{original_sym}?"
42
+ return ["<","<=",">=",">","==","=~"].include?(original_sym) ? original_sym : "#{original_sym}?"
25
43
  end
26
44
 
27
45
  def method_missing(original_sym, *args, &block)
@@ -29,6 +47,7 @@ module Spec
29
47
  return Not.new(@target).__send__(original_sym.to_s[4..-1].to_sym, *args, &block)
30
48
  end
31
49
  if original_sym.to_s =~ /^be_/
50
+ @be_seen = true
32
51
  return __send__(original_sym.to_s[3..-1].to_sym, *args, &block)
33
52
  end
34
53
  if original_sym.to_s =~ /^have_/
@@ -0,0 +1,69 @@
1
+ module Spec
2
+ module Expectations
3
+ module Should
4
+ class Change < Base
5
+
6
+ def initialize(target, receiver=nil, message=nil, &block)
7
+ @block = block
8
+ @target = target
9
+ @receiver = receiver
10
+ @message = message
11
+ execute_change
12
+ evaluate_change
13
+ end
14
+
15
+ def execute_change
16
+ @before_change = @block.nil? ? @receiver.send(@message) : @block.call
17
+ @target.call
18
+ @after_change = @block.nil? ? @receiver.send(@message) : @block.call
19
+ end
20
+
21
+ def message
22
+ @message.nil? ? 'result' : @message
23
+ end
24
+
25
+ def evaluate_change
26
+ if @before_change == @after_change
27
+ fail_with_message "#{message} should have changed, but is still #{@after_change.inspect}"
28
+ end
29
+ end
30
+
31
+ def from(value)
32
+ if @before_change != value
33
+ fail_with_message "#{message} should have initially been #{value.inspect}, but was #{@before_change.inspect}"
34
+ end
35
+ self
36
+ end
37
+
38
+ def to(value)
39
+ if @after_change != value
40
+ fail_with_message "#{message} should have been changed to #{value.inspect}, but is now #{@after_change.inspect}"
41
+ end
42
+ self
43
+ end
44
+
45
+ def by(expected_delta)
46
+ if actual_delta != expected_delta
47
+ fail_with_message "#{message} should have been changed by #{expected_delta}, but was changed by #{actual_delta}"
48
+ end
49
+ self
50
+ end
51
+
52
+ private
53
+ def actual_delta
54
+ @after_change - @before_change
55
+ end
56
+ end
57
+
58
+ class NotChange < Change
59
+ def evaluate_change
60
+ if @before_change != @after_change
61
+ fail_with_message "#{@message} should not have changed, but is now #{@after_change.inspect}"
62
+ end
63
+ end
64
+ end
65
+
66
+ end
67
+ end
68
+ end
69
+
@@ -1,23 +1,46 @@
1
1
  module Spec
2
2
  module Expectations
3
3
  module Should
4
- class Have < Base
5
-
6
- def initialize(target, relativity=:exactly, expected=nil, negate=false)
4
+ class Have
5
+ def initialize(target, relativity=:exactly, expected=nil)
6
+ @target = target
7
+ init_collection_handler(target, relativity, expected)
8
+ init_item_handler(target)
9
+ end
10
+
11
+ def init_collection_handler(target, relativity, expected)
12
+ @collection_handler = CollectionHandler.new(target, relativity, expected)
13
+ end
14
+
15
+ def init_item_handler(target)
16
+ @item_handler = PositiveItemHandler.new(target)
17
+ end
18
+
19
+ def method_missing(sym, *args)
20
+ if @collection_handler.wants_to_handle(sym)
21
+ @collection_handler.handle_message(sym, *args)
22
+ elsif @item_handler.wants_to_handle(sym)
23
+ @item_handler.handle_message(sym, *args)
24
+ else
25
+ raise NoMethodError.new("#{@target.inspect} does not respond to `#{sym}' or `has_#{sym}?'")
26
+ end
27
+ end
28
+ end
29
+
30
+ class NotHave < Have
31
+ def init_item_handler(target)
32
+ @item_handler = NegativeItemHandler.new(target)
33
+ end
34
+ end
35
+
36
+ class CollectionHandler
37
+ def initialize(target, relativity=:exactly, expected=nil)
7
38
  @target = target
8
39
  @expected = expected == :no ? 0 : expected
9
40
  @at_least = (relativity == :at_least)
10
41
  @at_most = (relativity == :at_most)
11
- @negate = negate
12
- end
13
-
14
- def exactly(expected_number=nil)
15
- @at_least = false
16
- @at_most = false
17
- @expected = expected_number == :no ? 0 : expected_number
18
- self
19
42
  end
20
-
43
+
21
44
  def at_least(expected_number=nil)
22
45
  @at_least = true
23
46
  @at_most = false
@@ -34,45 +57,79 @@ module Spec
34
57
 
35
58
  def method_missing(sym, *args)
36
59
  if @target.respond_to?(sym)
37
- fail_with_message(build_message(sym, args)) unless as_specified?(sym, args)
38
- elsif @target.respond_to?("has_#{sym}?")
39
- if @negate
40
- return unless @target.send("has_#{sym}?", *args)
41
- fail_with_message msg(sym, args, "should not have")
42
- else
43
- return if @target.send("has_#{sym}?", *args)
44
- fail_with_message msg(sym, args, "should have")
45
- end
46
- else
47
- raise NoMethodError.new("#{@target.inspect} does not respond to `#{sym}' or `has_#{sym}?'")
60
+ handle_message(sym, *args)
48
61
  end
49
62
  end
50
-
51
- def msg(sym, args, text)
52
- "#{@target.inspect_for_expectation_not_met_error} #{text} #{sym}: #{args.collect{|arg| arg.inspect_for_expectation_not_met_error}.join(', ')}"
63
+
64
+ def wants_to_handle(sym)
65
+ respond_to?(sym) || @target.respond_to?(sym)
53
66
  end
54
-
55
- def actual_size(collection)
56
- return collection.length if collection.respond_to? :length
57
- return collection.size if collection.respond_to? :size
67
+
68
+ def handle_message(sym, *args)
69
+ return at_least(args[0]) if sym == :at_least
70
+ return at_most(args[0]) if sym == :at_most
71
+ Spec::Expectations.fail_with(build_message(sym, args)) unless as_specified?(sym, args)
58
72
  end
59
-
73
+
60
74
  def build_message(sym, args)
61
- message = "#{@target.inspect_for_expectation_not_met_error} should have"
75
+ message = "#{@target.inspect} should have"
62
76
  message += " at least" if @at_least
63
77
  message += " at most" if @at_most
64
- message += " #{@expected} #{sym} (has #{actual_size(collection(sym, args))})"
78
+ message += " #{@expected} #{sym} (has #{actual_size_of(collection(sym, args))})"
65
79
  end
66
-
80
+
67
81
  def as_specified?(sym, args)
68
- return actual_size(collection(sym, args)) >= @expected if @at_least
69
- return actual_size(collection(sym, args)) <= @expected if @at_most
70
- return actual_size(collection(sym, args)) == @expected
82
+ return actual_size_of(collection(sym, args)) >= @expected if @at_least
83
+ return actual_size_of(collection(sym, args)) <= @expected if @at_most
84
+ return actual_size_of(collection(sym, args)) == @expected
71
85
  end
72
86
 
73
87
  def collection(sym, args)
74
88
  @target.send(sym, *args)
75
89
  end
90
+
91
+ def actual_size_of(collection)
92
+ return collection.length if collection.respond_to? :length
93
+ return collection.size if collection.respond_to? :size
94
+ end
95
+ end
96
+
97
+ class ItemHandler
98
+ def wants_to_handle(sym)
99
+ @target.respond_to?("has_#{sym}?")
100
+ end
101
+
102
+ def initialize(target)
103
+ @target = target
104
+ end
105
+
106
+ def build_message(sym, args)
107
+ "#{@target.inspect} #{item_expectation} #{sym}: #{args.collect{|arg| arg.inspect}.join(', ')}"
108
+ end
109
+
110
+ def fail_with(message)
111
+ Spec::Expectations.fail_with(message)
112
+ end
113
+ end
114
+
115
+ class PositiveItemHandler < ItemHandler
116
+ def handle_message(sym, *args)
117
+ fail_with(build_message(sym, args)) unless @target.send("has_#{sym}?", *args)
118
+ end
119
+
120
+ def item_expectation
121
+ "should have"
122
+ end
123
+ end
124
+
125
+ class NegativeItemHandler < ItemHandler
126
+ def handle_message(sym, *args)
127
+ fail_with(build_message(sym, args)) if @target.send("has_#{sym}?", *args)
128
+ end
129
+
130
+ def item_expectation
131
+ "should not have"
132
+ end
76
133
  end
77
134
  end
78
135
  end
@@ -9,7 +9,11 @@ module Spec
9
9
  end
10
10
 
11
11
  def have(expected_number=nil)
12
- Have.new(@target, :exactly, expected_number, true)
12
+ NotHave.new(@target, :exactly, expected_number)
13
+ end
14
+
15
+ def change(receiver, message)
16
+ NotChange.new(@target, receiver, message)
13
17
  end
14
18
 
15
19
  def satisfy
@@ -64,7 +68,7 @@ module Spec
64
68
 
65
69
  def __delegate_method_missing_to_target original_sym, actual_sym, *args
66
70
  return unless @target.__send__(actual_sym, *args)
67
- fail_with_message(default_message("should not#{@be_seen ? ' be' : ''} #{original_sym}" + (args.empty? ? '' : (' ' + args.join(', ')))))
71
+ fail_with_message(default_message("should not#{@be_seen ? ' be' : ''} #{original_sym}" + (args.empty? ? '' : ' ' + args[0].inspect)))
68
72
  end
69
73
  end
70
74
  end
@@ -1,17 +1,21 @@
1
1
  module Spec
2
2
  module Expectations
3
- module Should
3
+ module Should # :nodoc:
4
4
  class Should < Base
5
5
 
6
6
  def initialize(target)
7
7
  @target = target
8
8
  @be_seen = false
9
9
  end
10
-
10
+
11
11
  def have(expected_number=nil)
12
12
  Have.new(@target, :exactly, expected_number)
13
13
  end
14
14
 
15
+ def change(receiver=nil, message=nil, &block)
16
+ Change.new(@target, receiver, message, &block)
17
+ end
18
+
15
19
  def not
16
20
  Not.new(@target)
17
21
  end
@@ -55,9 +59,9 @@ module Spec
55
59
  rescue exception => e
56
60
  unless message.nil?
57
61
  if message.is_a?(Regexp)
58
- e.message.should_match message
62
+ e.message.should =~ message
59
63
  else
60
- e.message.should_eql message
64
+ e.message.should == message
61
65
  end
62
66
  end
63
67
  return
@@ -80,4 +84,4 @@ module Spec
80
84
  end
81
85
  end
82
86
  end
83
- end
87
+ end
@@ -2,3 +2,4 @@ require 'spec/expectations/should/base'
2
2
  require 'spec/expectations/should/have'
3
3
  require 'spec/expectations/should/not'
4
4
  require 'spec/expectations/should/should'
5
+ require 'spec/expectations/should/change'