rspec 0.5.3 → 0.5.4

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 (100) hide show
  1. data/CHANGES +57 -32
  2. data/EXAMPLES.rd +0 -0
  3. data/Rakefile +22 -21
  4. data/bin/spec +9 -11
  5. data/doc/README +1 -3
  6. data/doc/plugin/syntax.rb +27 -5
  7. data/doc/src/core_team.page +22 -0
  8. data/doc/src/default.css +11 -11
  9. data/doc/src/default.template +0 -1
  10. data/doc/src/documentation/index.page +183 -8
  11. data/doc/src/documentation/meta.info +7 -7
  12. data/doc/src/documentation/mocks.page +168 -109
  13. data/doc/src/documentation/underscores.page +20 -0
  14. data/doc/src/examples.page +2 -1
  15. data/doc/src/images/David_and_Aslak.jpg +0 -0
  16. data/doc/src/images/Whats_That_Dude.jpg +0 -0
  17. data/doc/src/index.page +70 -3
  18. data/doc/src/meta.info +18 -11
  19. data/doc/src/tools/index.page +40 -134
  20. data/doc/src/tools/meta.info +9 -3
  21. data/doc/src/tools/rails.page +3 -1
  22. data/doc/src/tools/rake.page +20 -3
  23. data/doc/src/tools/rcov.page +19 -0
  24. data/doc/src/tools/spec.page +99 -0
  25. data/doc/src/tools/test2rspec.page +2 -4
  26. data/doc/src/tutorials/index.page +52 -0
  27. data/doc/src/tutorials/meta.info +31 -0
  28. data/doc/src/tutorials/notes.txt +252 -0
  29. data/doc/src/tutorials/stack.rb +11 -0
  30. data/doc/src/tutorials/stack_01.page +224 -0
  31. data/doc/src/tutorials/stack_02.page +180 -0
  32. data/doc/src/tutorials/stack_03.page +291 -0
  33. data/doc/src/tutorials/stack_04.page +203 -0
  34. data/doc/src/tutorials/stack_04.page.orig +123 -0
  35. data/doc/src/tutorials/stack_05.page +90 -0
  36. data/doc/src/tutorials/stack_05.page.orig +124 -0
  37. data/doc/src/tutorials/stack_06.page +359 -0
  38. data/doc/src/tutorials/stack_06.page.orig +359 -0
  39. data/doc/src/tutorials/stack_spec.rb +41 -0
  40. data/examples/airport_spec.rb +4 -4
  41. data/examples/{spec_framework_spec.rb → bdd_framework_spec.rb} +6 -7
  42. data/examples/mocking_spec.rb +0 -5
  43. data/examples/stack_spec.rb +6 -7
  44. data/examples/sugar_spec.rb +14 -0
  45. data/lib/spec/api.rb +5 -2
  46. data/lib/spec/api/helper/should_base.rb +17 -22
  47. data/lib/spec/api/helper/should_helper.rb +4 -3
  48. data/lib/spec/api/helper/should_negator.rb +3 -2
  49. data/lib/spec/api/mocks/argument_expectation.rb +104 -0
  50. data/lib/spec/api/{mock.rb → mocks/message_expectation.rb} +47 -96
  51. data/lib/spec/api/mocks/mock.rb +63 -0
  52. data/lib/spec/api/mocks/order_group.rb +21 -0
  53. data/lib/spec/api/sugar.rb +47 -0
  54. data/lib/spec/rake/rcov_verify.rb +45 -0
  55. data/lib/spec/rake/spectask.rb +41 -56
  56. data/lib/spec/runner.rb +4 -1
  57. data/lib/spec/runner/backtrace_tweaker.rb +24 -3
  58. data/lib/spec/runner/base_text_formatter.rb +28 -0
  59. data/lib/spec/runner/context.rb +21 -18
  60. data/lib/spec/runner/context_runner.rb +20 -31
  61. data/lib/spec/runner/execution_context.rb +3 -3
  62. data/lib/spec/runner/kernel_ext.rb +10 -1
  63. data/lib/spec/runner/option_parser.rb +32 -14
  64. data/lib/spec/runner/progress_bar_formatter.rb +21 -0
  65. data/lib/spec/runner/rdoc_formatter.rb +15 -5
  66. data/lib/spec/runner/reporter.rb +100 -0
  67. data/lib/spec/runner/specdoc_formatter.rb +20 -0
  68. data/lib/spec/runner/specification.rb +42 -22
  69. data/lib/spec/version.rb +1 -1
  70. data/test/rcov/rcov_testtask.rb +1 -0
  71. data/test/spec/api/duck_type_test.rb +4 -4
  72. data/test/spec/api/helper/raising_test.rb +37 -17
  73. data/test/spec/api/{mock_arg_constraints_test.rb → mocks/mock_arg_constraints_test.rb} +10 -4
  74. data/test/spec/api/mocks/mock_ordering_test.rb +62 -0
  75. data/test/spec/api/{mock_test.rb → mocks/mock_test.rb} +30 -7
  76. data/test/spec/api/mocks/null_object_test.rb +31 -0
  77. data/test/spec/api/sugar_test.rb +71 -0
  78. data/test/spec/runner/backtrace_tweaker_test.rb +52 -4
  79. data/test/spec/runner/context_runner_test.rb +41 -21
  80. data/test/spec/runner/context_test.rb +60 -32
  81. data/test/spec/runner/execution_context_test.rb +4 -3
  82. data/test/spec/runner/failure_dump_test.rb +92 -0
  83. data/test/spec/runner/kernel_ext_test.rb +1 -2
  84. data/test/spec/runner/option_parser_test.rb +48 -28
  85. data/test/spec/runner/progress_bar_formatter_test.rb +48 -0
  86. data/test/spec/runner/rdoc_formatter_test.rb +31 -4
  87. data/test/spec/runner/reporter_test.rb +103 -0
  88. data/test/spec/runner/specdoc_formatter_test.rb +50 -0
  89. data/test/spec/runner/specification_test.rb +49 -11
  90. data/test/test_helper.rb +1 -4
  91. metadata +46 -15
  92. data/doc/src/community.page +0 -7
  93. data/doc/src/documentation/api.page +0 -185
  94. data/doc/src/why_rspec.page +0 -7
  95. data/examples/empty_stack_spec.rb +0 -22
  96. data/examples/team_spec.rb +0 -30
  97. data/lib/spec/api/duck_type.rb +0 -16
  98. data/lib/spec/runner/simple_text_reporter.rb +0 -88
  99. data/test/rcov/rcov_verify.rb +0 -28
  100. data/test/spec/runner/simple_text_reporter_test.rb +0 -123
@@ -0,0 +1,41 @@
1
+ require 'stack'
2
+
3
+ context "A new stack" do
4
+ setup do
5
+ @stack = Stack.new
6
+ end
7
+
8
+ specify "should be empty" do
9
+ @stack.should_be_empty
10
+ end
11
+ end
12
+
13
+ context "An empty stack" do
14
+ setup do
15
+ @stack = Stack.new
16
+ end
17
+
18
+ specify "should keep its mouth shut when you send it 'push'" do
19
+ lambda { @stack.push Object.new }.should.not.raise
20
+ end
21
+ end
22
+
23
+ context "A stack with one item" do
24
+ setup do
25
+ @stack = Stack.new
26
+ @stack.push "one item"
27
+ end
28
+
29
+ specify "should not be empty" do
30
+ @stack.should_not_be_empty
31
+ end
32
+
33
+ specify "should return top when you send it 'top'" do
34
+ @stack.top.should_equal "one item"
35
+ end
36
+
37
+ specify "should not be empty after 'top'" do
38
+ @stack.top
39
+ @stack.should_not_be_empty
40
+ end
41
+ end
@@ -6,7 +6,7 @@ class Airport
6
6
  end
7
7
 
8
8
  def need?(thing)
9
- thing != :cables
9
+ false unless [:cables, :electricity].include? thing
10
10
  end
11
11
  end
12
12
 
@@ -25,16 +25,16 @@ topic "Airport at home" do
25
25
  end
26
26
 
27
27
  fact "should always work" do
28
- @airport.should.be.working
28
+ @airport.should_be_working
29
29
  end
30
30
 
31
31
  must "not need cables" do
32
- @airport.should.not.need :cables
32
+ @airport.should_not_need :cables
33
33
  end
34
34
 
35
35
  must "not need electricity" do
36
36
  # This will fail...
37
- @airport.should.not.need :electricity
37
+ @airport.should_not_need :electricity
38
38
  end
39
39
 
40
40
  teardown do
@@ -1,28 +1,27 @@
1
1
  require File.dirname(__FILE__) + '/../lib/spec'
2
2
 
3
- class SpecFramework
3
+ class BddFramework
4
4
  def intuitive?
5
5
  true
6
6
  end
7
7
 
8
8
  def adopted_quickly?
9
- false
9
+ true
10
10
  end
11
11
  end
12
12
 
13
- context "Spec framework" do
13
+ context "BDD framework" do
14
14
 
15
15
  setup do
16
- @spec_framework = SpecFramework.new
16
+ @bdd_framework = BddFramework.new
17
17
  end
18
18
 
19
19
  specify "should be adopted quickly" do
20
- #this will fail
21
- @spec_framework.should.be.adopted_quickly
20
+ @bdd_framework.should_be_adopted_quickly
22
21
  end
23
22
 
24
23
  specify "should be intuitive" do
25
- @spec_framework.should.be.intuitive
24
+ @bdd_framework.should_be_intuitive
26
25
  end
27
26
 
28
27
  end
@@ -8,9 +8,4 @@ context "Mocker" do
8
8
  mock.poke
9
9
  end
10
10
 
11
- specify "should fail when expected message not received" do
12
- mock = mock("poke me")
13
- mock.should.receive(:poke)
14
- end
15
-
16
11
  end
@@ -8,11 +8,11 @@ context "An empty stack" do
8
8
  end
9
9
 
10
10
  specify "should accept an item when sent push" do
11
- lambda { @stack.push Object.new }.should.not.raise
11
+ lambda { @stack.push Object.new }.should_not_raise
12
12
  end
13
13
 
14
14
  specify "should complain when sent top" do
15
- lambda { @stack.top }.should.raise StackUnderflowError
15
+ lambda { @stack.top }.should_raise StackUnderflowError
16
16
  end
17
17
 
18
18
  specify "should complain when sent pop" do
@@ -21,7 +21,8 @@ context "An empty stack" do
21
21
 
22
22
  end
23
23
 
24
- context "A stack with one item" do
24
+ context "A stack with one item" do
25
+
25
26
  setup do
26
27
  @stack = Stack.new
27
28
  @stack.push 3
@@ -52,6 +53,7 @@ end
52
53
  end
53
54
 
54
55
  context "An almost full stack (with one item less than capacity)" do
56
+
55
57
  setup do
56
58
  @stack = Stack.new
57
59
  (1..9).each { |i| @stack.push i }
@@ -110,7 +112,4 @@ context "A full stack" do
110
112
  @stack.pop.should.be 9
111
113
  end
112
114
 
113
- end
114
-
115
-
116
-
115
+ end
@@ -0,0 +1,14 @@
1
+ require File.dirname(__FILE__) + '/../lib/spec'
2
+
3
+ context "Underscore sugar" do
4
+ specify "should be available for regular objects" do
5
+ 1.should_equal 1
6
+ lambda { 1.should_not_equal 1 }.should_raise
7
+ end
8
+
9
+ specify "should be available for mocks" do
10
+ sweetened = mock "sweetened"
11
+ sweetened.should_receive :salt
12
+ sweetened.salt
13
+ end
14
+ end
@@ -1,5 +1,8 @@
1
1
  require 'spec/api/exceptions'
2
- require 'spec/api/mock'
3
- require 'spec/api/duck_type'
2
+ require 'spec/api/mocks/argument_expectation'
3
+ require 'spec/api/mocks/order_group'
4
+ require 'spec/api/mocks/message_expectation'
5
+ require 'spec/api/mocks/mock'
4
6
  require 'spec/api/expectations'
5
7
  require 'spec/api/helper'
8
+ require 'spec/api/sugar'
@@ -1,38 +1,33 @@
1
+ class TrueClass; def inspect_for_expectation_not_met_error; "<true>" end end
2
+ class FalseClass; def inspect_for_expectation_not_met_error; "<false>" end end
3
+ class NilClass; def inspect_for_expectation_not_met_error; "nil" end end
4
+ class Class; def inspect_for_expectation_not_met_error; "<#{name}>" end end
5
+ class Proc; def inspect_for_expectation_not_met_error; "<Proc>" end end
6
+ class Array; def inspect_for_expectation_not_met_error; "#{inspect}" end end
7
+ class String; def inspect_for_expectation_not_met_error; "#{inspect}" end end
8
+ class Object
9
+ def inspect_for_expectation_not_met_error
10
+ return "#{self.class} #{inspect}" if inspect.include? "<"
11
+ return "#{self.class} <#{inspect}>" unless inspect.include? "<"
12
+ end
13
+ end
14
+
1
15
  module Spec
2
16
 
3
17
  class ShouldBase
4
18
 
5
19
  def default_message(expectation, expected=:no_expectation_specified)
6
- message = wrap(@target)
7
- message += " #{expectation}"
20
+ message = "#{@target.inspect_for_expectation_not_met_error} #{expectation}"
8
21
  if (expected != :no_expectation_specified)
9
- message += " " + wrap(expected)
22
+ message << " " << expected.inspect_for_expectation_not_met_error
10
23
  end
11
24
  message
12
25
  end
13
-
14
- def wrap(obj)
15
- if obj == true
16
- "<true>"
17
- elsif obj == false
18
- "<false>"
19
- elsif obj.nil?
20
- "nil"
21
- elsif obj.kind_of? Proc
22
- "<Proc>"
23
- elsif (obj.kind_of? Array) || (obj.kind_of? String)
24
- "#{obj.inspect}"
25
- elsif obj.inspect.include? "<"
26
- "#{obj.class} #{obj.inspect}"
27
- else
28
- "#{obj.class} <#{obj.inspect}>"
29
- end
30
- end
31
26
 
32
27
  def fail_with_message(message)
33
28
  Kernel::raise(Spec::Api::ExpectationNotMetError.new(message))
34
29
  end
35
-
30
+
36
31
  end
37
32
 
38
33
  end
@@ -64,11 +64,12 @@ module Spec
64
64
  def raise(exception=Exception)
65
65
  begin
66
66
  @target.call
67
- fail_with_message(default_message("should raise", exception.inspect))
68
67
  rescue exception
69
- rescue
70
- fail_with_message(default_message("should raise", exception.inspect))
68
+ return
69
+ rescue => e
70
+ fail_with_message("#{default_message("should raise", exception)} but raised #{e.inspect}")
71
71
  end
72
+ fail_with_message("#{default_message("should raise", exception)} but raised nothing")
72
73
  end
73
74
 
74
75
  def throw(symbol)
@@ -48,8 +48,9 @@ module Spec
48
48
  def raise(exception=Exception)
49
49
  begin
50
50
  @target.call
51
- rescue exception
52
- fail_with_message(default_message("should not raise", exception.inspect))
51
+ rescue exception => e
52
+ fail_with_message("#{default_message("should not raise", exception)}") if e.instance_of? exception
53
+ fail_with_message("#{default_message("should not raise", exception)} but raised #{e.inspect}") unless e.instance_of? exception
53
54
  rescue
54
55
  true
55
56
  end
@@ -0,0 +1,104 @@
1
+ module Spec
2
+ module Api
3
+
4
+ class LiteralArgConstraint
5
+ def initialize(literal)
6
+ @literal_value = literal
7
+ end
8
+
9
+ def matches?(value)
10
+ @literal_value == value
11
+ end
12
+ end
13
+
14
+ class AnyArgConstraint
15
+ def initialize(ignore)
16
+ end
17
+
18
+ def matches?(value)
19
+ true
20
+ end
21
+ end
22
+
23
+ class NumericArgConstraint
24
+ def initialize(ignore)
25
+ end
26
+
27
+ def matches?(value)
28
+ value.is_a?(Numeric)
29
+ end
30
+ end
31
+
32
+ class BooleanArgConstraint
33
+ def initialize(ignore)
34
+ end
35
+
36
+ def matches?(value)
37
+ return true if value.is_a?(TrueClass)
38
+ return true if value.is_a?(FalseClass)
39
+ false
40
+ end
41
+ end
42
+
43
+ class StringArgConstraint
44
+ def initialize(ignore)
45
+ end
46
+
47
+ def matches?(value)
48
+ value.is_a?(String)
49
+ end
50
+ end
51
+
52
+ class DuckTypeArgConstraint
53
+ def initialize(*methods_to_respond_do)
54
+ @methods_to_respond_do = methods_to_respond_do
55
+ end
56
+
57
+ def matches?(value)
58
+ @methods_to_respond_do.all? { |sym| value.respond_to?(sym) }
59
+ end
60
+ end
61
+
62
+ class ArgumentExpectation
63
+
64
+ @@constraint_classes = Hash.new { |hash, key| LiteralArgConstraint}
65
+ @@constraint_classes[:anything] = AnyArgConstraint
66
+ @@constraint_classes[:numeric] = NumericArgConstraint
67
+ @@constraint_classes[:boolean] = BooleanArgConstraint
68
+ @@constraint_classes[:string] = StringArgConstraint
69
+
70
+ def initialize(args)
71
+ if args == [:any_args] then @expected_params = nil
72
+ elsif args == [:no_args] then @expected_params = []
73
+ else @expected_params = process_arg_constraints(args)
74
+ end
75
+ end
76
+
77
+ def process_arg_constraints(constraints)
78
+ constraints.collect do |constraint|
79
+ convert_constraint(constraint)
80
+ end
81
+ end
82
+
83
+ def convert_constraint(constraint)
84
+ return @@constraint_classes[constraint].new(constraint) if constraint.is_a?(Symbol)
85
+ return constraint if constraint.is_a?(DuckTypeArgConstraint)
86
+ return LiteralArgConstraint.new(constraint)
87
+ end
88
+
89
+ def check_args(args)
90
+ return true if @expected_params.nil?
91
+ return true if @expected_params == args
92
+ return constraints_match?(args)
93
+ end
94
+
95
+ def constraints_match?(args)
96
+ return false if args.length != @expected_params.length
97
+ @expected_params.each_index { |i| return false unless @expected_params[i].matches?(args[i]) }
98
+ return true
99
+ end
100
+
101
+ end
102
+
103
+ end
104
+ end
@@ -1,65 +1,10 @@
1
1
  module Spec
2
2
  module Api
3
- class Mock
4
-
5
- DEFAULT_OPTIONS = {
6
- :null_object => false
7
- }
8
- # Creates a new mock with a +name+ (that will be used in error messages only)
9
- # Options:
10
- # * <tt>:null_object</tt> - if true, the mock object acts as a forgiving null object allowing any message to be sent to it.
11
- def initialize(name, options={})
12
- @name = name
13
- @options = DEFAULT_OPTIONS.dup.merge(options)
14
- @expectations = []
15
- end
16
-
17
- def should
18
- self
19
- end
20
-
21
- def receive(sym, &block)
22
- expected_from = caller(1)[0]
23
- expectation = MessageExpectation.new(@name, expected_from, sym, block_given? ? block : nil)
24
- @expectations << expectation
25
- expectation
26
- end
27
-
28
- def __verify
29
- @expectations.each do |expectation|
30
- expectation.verify_messages_received
31
- end
32
- end
33
-
34
- def method_missing(sym, *args, &block)
35
- # TODO: use find_expectation(sym, args) which will lookup based on sym, args and strict mode.
36
- if expectation = find_matching_expectation(sym, *args)
37
- expectation.verify_message(args, block)
38
- else
39
- begin
40
- # act as null object if method is missing and we ignore them. return value too!
41
- @options[:null_object] ? self : super(sym, *args, &block)
42
- rescue NoMethodError
43
-
44
- arg_message = args.collect{|arg| "<#{arg}:#{arg.class.name}>"}.join(", ")
45
-
46
- Kernel::raise Spec::Api::MockExpectationError, "Mock '#{@name}' received unexpected message '#{sym.to_s}' with [#{arg_message}]"
47
- end
48
- end
49
- end
50
-
51
- private
52
-
53
- def find_matching_expectation(sym, *args)
54
- expectation = @expectations.find {|expectation| expectation.matches(sym, args)}
55
- end
56
-
57
- end
58
3
 
59
4
  # Represents the expection of the reception of a message
60
5
  class MessageExpectation
61
-
62
- def initialize(mock_name, expected_from, sym, block)
6
+
7
+ def initialize(mock_name, expectation_ordering, expected_from, sym, block)
63
8
  @mock_name = mock_name
64
9
  @expected_from = expected_from
65
10
  @sym = sym
@@ -67,33 +12,21 @@ module Spec
67
12
  @block = proc {}
68
13
  @received_count = 0
69
14
  @expected_received_count = 1
70
- @expected_params = nil
15
+ @args_expectation = ArgumentExpectation.new([:any_args])
71
16
  @consecutive = false
72
17
  @exception_to_raise = nil
73
18
  @symbol_to_throw = nil
74
19
  @any_seen = false
75
20
  @at_seen = false
76
21
  @and_seen = false
22
+ @ordering = expectation_ordering
23
+ @ordered = false
77
24
  end
78
25
 
79
26
  def matches(sym, args)
80
- @sym == sym and (@expected_params.nil? or @expected_params == args or constraints_match?(args))
81
- end
82
-
83
- def constraints_match?(args)
84
- return true if @expected_params.length == 1 and @expected_params[0] == :any_args
85
- return false if args.length != @expected_params.length
86
- @expected_params.each_index do |i|
87
- next if @expected_params[i] == :anything
88
- next if @expected_params[i] == :numeric and args[i].is_a?Numeric
89
- next if @expected_params[i] == :boolean and args[i].is_a?TrueClass or args[i].is_a?FalseClass
90
- next if @expected_params[i] == :string and args[i].is_a?String
91
- next if @expected_params[i].is_a? DuckType and @expected_params[i].walks_like? args[i]
92
- return false unless args[i] == @expected_params[i]
93
- end
94
- return true
27
+ @sym == sym and @args_expectation.check_args(args)
95
28
  end
96
-
29
+
97
30
  def make_count_message(count)
98
31
  return "at least #{pretty_print(count.abs)}" if count < 0
99
32
  return pretty_print(count) if count > 0
@@ -105,53 +38,63 @@ module Spec
105
38
  return "twice" if count == 2
106
39
  return "#{count} times"
107
40
  end
108
-
41
+
109
42
  # This method is called at the end of a spec, after teardown.
110
43
  def verify_messages_received
111
44
  # TODO: this doesn't provide good enough error messages to fix the error.
112
45
  # Error msg should tell exactly what went wrong. (AH).
113
-
46
+
114
47
  return if @expected_received_count == :any
115
48
  return if (@expected_received_count < 0) && (@received_count >= @expected_received_count.abs)
116
49
  return if @expected_received_count == @received_count
117
50
 
118
- expected_signature = nil
119
- if @expected_params.nil?
120
- expected_signature = @sym
121
- else
122
- params = @expected_params.collect{|param| "<#{param}:#{param.class.name}>"}.join(", ")
123
- expected_signature = "#{@sym}(#{params})"
124
- end
125
-
126
51
  count_message = make_count_message(@expected_received_count)
127
52
 
128
- message = "Mock '#{@mock_name}' expected #{expected_signature} #{count_message}, but received it #{@received_count} times"
53
+ message = "Mock '#{@mock_name}' expected '#{@sym}' #{count_message}, but received it #{@received_count} times"
129
54
  begin
130
- Kernel::raise Spec::Api::MockExpectationError, message
55
+ Kernel::raise(Spec::Api::MockExpectationError, message)
131
56
  rescue => error
132
57
  error.backtrace.insert(0, @expected_from)
133
58
  Kernel::raise error
134
59
  end
135
60
  end
136
61
 
62
+ def handle_order_constraint
63
+ return unless @ordered
64
+ return @ordering.consume(@self) if @ordering.ready_for?(self)
65
+ message = "Mock '#{@mock_name}' received '#{@sym}' out of order"
66
+ Kernel::raise(Spec::Api::MockExpectationError, message)
67
+ end
68
+
137
69
  # This method is called when a method is invoked on a mock
138
70
  def verify_message(args, block)
71
+
72
+ handle_order_constraint
73
+
139
74
  unless @method_block.nil?
140
75
  begin
141
76
  result = @method_block.call(*args)
142
77
  rescue Spec::Api::ExpectationNotMetError => detail
143
- Kernel::raise Spec::Api::MockExpectationError, "Call expectation violated with: " + $!
78
+ Kernel::raise Spec::Api::MockExpectationError, "Call expectation violated with: " + detail
144
79
  end
145
80
  @received_count += 1
146
81
  return result
147
82
  end
148
83
 
149
- args << block unless block.nil?
150
- @received_count += 1
151
-
152
84
  Kernel::raise @exception_to_raise.new unless @exception_to_raise.nil?
153
85
  Kernel::throw @symbol_to_throw unless @symbol_to_throw.nil?
154
-
86
+ unless @args_to_yield.nil?
87
+ if block.nil?
88
+ Kernel::raise Spec::Api::MockExpectationError, "Expected block to be passed"
89
+ end
90
+ if @args_to_yield.length != block.arity
91
+ Kernel::raise Spec::Api::MockExpectationError, "Wrong arity of passed block. Expected #{@args_to_yield.size}"
92
+ end
93
+ block.call @args_to_yield
94
+ end
95
+
96
+ args << block unless block.nil?
97
+ @received_count += 1
155
98
  value = @block.call(*args)
156
99
 
157
100
  return value unless @consecutive
@@ -160,11 +103,7 @@ module Spec
160
103
  end
161
104
 
162
105
  def with(*args)
163
- if args == [:any_args] then @expected_params = nil
164
- elsif args == [:no_args] then @expected_params = []
165
- else @expected_params = args
166
- end
167
-
106
+ @args_expectation = ArgumentExpectation.new(args)
168
107
  self
169
108
  end
170
109
 
@@ -249,6 +188,18 @@ module Spec
249
188
  @and_seen = false
250
189
  @symbol_to_throw = symbol
251
190
  end
191
+
192
+ def ordered
193
+ @ordering.register(self)
194
+ @ordered = true
195
+ self
196
+ end
197
+
198
+ def yield(*args)
199
+ return self unless @and_seen
200
+ @and_seen = false
201
+ @args_to_yield = args
202
+ end
252
203
 
253
204
  end
254
205
  end