dchelimsky-rspec 1.1.12 → 1.1.99.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 (147) hide show
  1. data/History.txt +35 -0
  2. data/License.txt +1 -1
  3. data/Manifest.txt +22 -73
  4. data/README.txt +2 -2
  5. data/Rakefile +32 -7
  6. data/TODO.txt +9 -4
  7. data/bin/spec +1 -1
  8. data/cucumber.yml +2 -0
  9. data/examples/failing/spec_helper.rb +1 -1
  10. data/examples/passing/filtered_formatter.rb +18 -0
  11. data/examples/passing/filtered_formatter_example.rb +31 -0
  12. data/examples/passing/spec_helper.rb +1 -1
  13. data/examples/ruby1.9.compatibility/access_to_constants_spec.rb +17 -18
  14. data/features/before_and_after_blocks/before_and_after_blocks.feature +4 -4
  15. data/features/example_groups/autogenerated_docstrings.feature +2 -2
  16. data/features/example_groups/example_group_with_should_methods.feature +1 -1
  17. data/features/example_groups/nested_groups.feature +1 -1
  18. data/features/interop/examples_and_tests_together.feature +1 -1
  19. data/features/interop/test_but_not_test_unit.feature +1 -1
  20. data/features/interop/test_case_with_should_methods.feature +1 -1
  21. data/features/mock_framework_integration/use_flexmock.feature +22 -4
  22. data/features/mock_framework_integration/use_mocha.feature +27 -0
  23. data/features/mock_framework_integration/use_rr.feature +27 -0
  24. data/features/step_definitions/running_rspec.rb +5 -3
  25. data/features/support/env.rb +1 -1
  26. data/features-pending/cli/conditional_exclusion.feature +39 -0
  27. data/lib/{adapters → spec/adapters}/mock_frameworks/flexmock.rb +1 -0
  28. data/lib/{adapters → spec/adapters}/mock_frameworks/mocha.rb +1 -0
  29. data/lib/{adapters → spec/adapters}/mock_frameworks/rr.rb +1 -0
  30. data/lib/{adapters → spec/adapters}/mock_frameworks/rspec.rb +0 -1
  31. data/lib/spec/autorun.rb +3 -0
  32. data/lib/spec/example/before_and_after_hooks.rb +5 -20
  33. data/lib/spec/example/example_description.rb +15 -0
  34. data/lib/spec/example/example_group.rb +0 -15
  35. data/lib/spec/example/example_group_factory.rb +34 -46
  36. data/lib/spec/example/example_group_hierarchy.rb +53 -0
  37. data/lib/spec/example/example_group_methods.rb +96 -211
  38. data/lib/spec/example/example_methods.rb +62 -81
  39. data/lib/spec/example/module_reopening_fix.rb +23 -1
  40. data/lib/spec/example/predicate_matchers.rb +47 -0
  41. data/lib/spec/example/subject.rb +91 -0
  42. data/lib/spec/example.rb +4 -0
  43. data/lib/spec/expectations/extensions.rb +0 -1
  44. data/lib/spec/expectations/handler.rb +6 -1
  45. data/lib/spec/expectations.rb +1 -1
  46. data/lib/spec/interop/test/unit/testcase.rb +5 -22
  47. data/lib/spec/interop/test.rb +1 -0
  48. data/lib/spec/matchers/be.rb +2 -7
  49. data/lib/spec/matchers/be_close.rb +20 -5
  50. data/lib/spec/matchers/change.rb +5 -3
  51. data/lib/spec/matchers/eql.rb +24 -6
  52. data/lib/spec/matchers/equal.rb +24 -6
  53. data/lib/spec/matchers/exist.rb +21 -5
  54. data/lib/spec/matchers/generated_descriptions.rb +2 -2
  55. data/lib/spec/matchers/has.rb +28 -11
  56. data/lib/spec/matchers/match.rb +25 -7
  57. data/lib/spec/matchers/match_array.rb +1 -1
  58. data/lib/spec/matchers/method_missing.rb +2 -2
  59. data/lib/spec/matchers/operator_matcher.rb +12 -5
  60. data/lib/spec/matchers/raise_error.rb +1 -1
  61. data/lib/spec/matchers/respond_to.rb +1 -1
  62. data/lib/spec/matchers/satisfy.rb +5 -5
  63. data/lib/spec/matchers/throw_symbol.rb +1 -3
  64. data/lib/spec/mocks/argument_expectation.rb +1 -1
  65. data/lib/spec/mocks/argument_matchers.rb +233 -0
  66. data/lib/spec/mocks/error_generator.rb +2 -6
  67. data/lib/spec/mocks/message_expectation.rb +3 -11
  68. data/lib/spec/mocks/mock.rb +1 -1
  69. data/lib/spec/mocks/proxy.rb +5 -1
  70. data/lib/spec/runner/configuration.rb +3 -3
  71. data/lib/spec/runner/drb_command_line.rb +2 -1
  72. data/lib/spec/runner/example_group_runner.rb +2 -1
  73. data/lib/spec/runner/formatter/base_text_formatter.rb +28 -17
  74. data/lib/spec/runner/formatter/failing_example_groups_formatter.rb +3 -5
  75. data/lib/spec/runner/formatter/html_formatter.rb +2 -3
  76. data/lib/spec/runner/formatter/nested_text_formatter.rb +7 -25
  77. data/lib/spec/runner/formatter/progress_bar_formatter.rb +1 -1
  78. data/lib/spec/runner/formatter/specdoc_formatter.rb +1 -7
  79. data/lib/spec/runner/heckle_runner_unsupported.rb +1 -1
  80. data/lib/spec/runner/option_parser.rb +16 -19
  81. data/lib/spec/runner/options.rb +28 -26
  82. data/lib/spec/runner/reporter.rb +8 -9
  83. data/lib/spec/runner.rb +6 -28
  84. data/lib/spec/test/unit.rb +10 -0
  85. data/lib/spec/version.rb +2 -2
  86. data/{features/support → resources}/helpers/cmdline.rb +2 -2
  87. data/resources/rake/verify_rcov.rake +1 -1
  88. data/resources/spec/example_group_with_should_methods.rb +1 -1
  89. data/resources/spec/simple_spec.rb +1 -1
  90. data/resources/test/spec_and_test_together.rb +2 -3
  91. data/resources/test/spec_including_test_but_not_unit.rb +1 -1
  92. data/resources/test/test_case_with_should_methods.rb +2 -3
  93. data/rspec.gemspec +5 -5
  94. data/spec/spec/dsl/main_spec.rb +3 -3
  95. data/spec/spec/example/example_group_class_definition_spec.rb +11 -14
  96. data/spec/spec/example/example_group_factory_spec.rb +31 -44
  97. data/spec/spec/example/example_group_methods_spec.rb +86 -52
  98. data/spec/spec/example/example_group_spec.rb +16 -75
  99. data/spec/spec/example/example_matcher_spec.rb +10 -10
  100. data/spec/spec/example/example_methods_spec.rb +101 -241
  101. data/spec/spec/example/nested_example_group_spec.rb +2 -2
  102. data/spec/spec/example/pending_module_spec.rb +1 -1
  103. data/spec/spec/example/shared_example_group_spec.rb +2 -2
  104. data/spec/spec/interop/test/unit/resources/spec_that_fails.rb +2 -2
  105. data/spec/spec/interop/test/unit/resources/spec_that_passes.rb +2 -2
  106. data/spec/spec/interop/test/unit/resources/spec_with_errors.rb +2 -2
  107. data/spec/spec/interop/test/unit/resources/spec_with_options_hash.rb +2 -2
  108. data/spec/spec/interop/test/unit/resources/test_case_that_fails.rb +2 -2
  109. data/spec/spec/interop/test/unit/resources/test_case_that_passes.rb +2 -2
  110. data/spec/spec/interop/test/unit/resources/test_case_with_errors.rb +2 -2
  111. data/spec/spec/interop/test/unit/resources/testsuite_adapter_spec_with_test_unit.rb +2 -2
  112. data/spec/spec/matchers/change_spec.rb +8 -0
  113. data/spec/spec/matchers/exist_spec.rb +8 -4
  114. data/spec/spec/matchers/handler_spec.rb +8 -1
  115. data/spec/spec/matchers/matcher_methods_spec.rb +1 -1
  116. data/spec/spec/mocks/{bug_report_496.rb → bug_report_496_spec.rb} +0 -0
  117. data/spec/spec/mocks/failing_argument_matchers_spec.rb +95 -0
  118. data/spec/spec/mocks/nil_expectation_warning_spec.rb +1 -1
  119. data/spec/spec/mocks/passing_argument_matchers_spec.rb +145 -0
  120. data/spec/spec/runner/configuration_spec.rb +12 -12
  121. data/spec/spec/runner/formatter/base_text_formatter_spec.rb +72 -1
  122. data/spec/spec/runner/formatter/failing_example_groups_formatter_spec.rb +8 -8
  123. data/spec/spec/runner/formatter/failing_examples_formatter_spec.rb +4 -4
  124. data/spec/spec/runner/formatter/html_formatted-1.8.6.html +8 -8
  125. data/spec/spec/runner/formatter/html_formatted-1.8.7.html +38 -26
  126. data/spec/spec/runner/formatter/html_formatted-1.9.1.html +61 -53
  127. data/spec/spec/runner/formatter/html_formatter_spec.rb +100 -48
  128. data/spec/spec/runner/formatter/nested_text_formatter_spec.rb +20 -34
  129. data/spec/spec/runner/formatter/profile_formatter_spec.rb +1 -1
  130. data/spec/spec/runner/formatter/progress_bar_formatter_spec.rb +8 -6
  131. data/spec/spec/runner/formatter/specdoc_formatter_spec.rb +6 -6
  132. data/spec/spec/runner/formatter/text_mate_formatted-1.8.6.html +20 -20
  133. data/spec/spec/runner/formatter/text_mate_formatted-1.8.7.html +38 -26
  134. data/spec/spec/runner/formatter/{spec_mate_formatter_spec.rb → text_mate_formatter_spec.rb} +10 -8
  135. data/spec/spec/runner/heckle_runner_spec.rb +1 -1
  136. data/spec/spec/runner/option_parser_spec.rb +15 -13
  137. data/spec/spec/runner/options_spec.rb +34 -0
  138. data/spec/spec/runner/reporter_spec.rb +65 -61
  139. data/spec/spec/runner/spec_drb.opts +1 -0
  140. data/spec/spec/runner_spec.rb +7 -5
  141. data/spec/spec_helper.rb +23 -0
  142. metadata +25 -76
  143. data/examples/passing/legacy_spec.rb +0 -11
  144. data/features/support/helpers/story_helper.rb +0 -13
  145. data/lib/spec/expectations/extensions/string_and_symbol.rb +0 -17
  146. data/resources/spec/spec_with_flexmock.rb +0 -19
  147. data/spec/spec/spec_spec.rb +0 -21
@@ -1,6 +1,28 @@
1
1
  module Spec
2
2
  module Example
3
- # This is a fix for ...Something in Ruby 1.8.6??... (Someone fill in here please - Aslak)
3
+ # When you reopen a module that is included in another module that is included in a class,
4
+ # the new material you define does not make it to the class. This fixes that.
5
+ #
6
+ # == Example
7
+ #
8
+ # module M1; end
9
+ #
10
+ # module M2
11
+ # def foo; "FOO"; end
12
+ # end
13
+ #
14
+ # class C
15
+ # include M1
16
+ # end
17
+ #
18
+ # module M1
19
+ # include M2
20
+ # end
21
+ #
22
+ # c = C.new
23
+ # c.foo
24
+ # NoMethodError: undefined method `foo' for #<C:0x5e89a4>
25
+ # from (irb):12
4
26
  module ModuleReopeningFix
5
27
  def child_modules
6
28
  @child_modules ||= []
@@ -0,0 +1,47 @@
1
+ module Spec
2
+ module Example
3
+ module PredicateMatchers
4
+ # :call-seq:
5
+ # predicate_matchers[matcher_name] = method_on_object
6
+ # predicate_matchers[matcher_name] = [method1_on_object, method2_on_object]
7
+ #
8
+ # Dynamically generates a custom matcher that will match
9
+ # a predicate on your class. RSpec provides a couple of these
10
+ # out of the box:
11
+ #
12
+ # exist (for state expectations)
13
+ # File.should exist("path/to/file")
14
+ #
15
+ # an_instance_of (for mock argument matchers)
16
+ # mock.should_receive(:message).with(an_instance_of(String))
17
+ #
18
+ # == Examples
19
+ #
20
+ # class Fish
21
+ # def can_swim?
22
+ # true
23
+ # end
24
+ # end
25
+ #
26
+ # describe Fish do
27
+ # predicate_matchers[:swim] = :can_swim?
28
+ # it "should swim" do
29
+ # Fish.new.should swim
30
+ # end
31
+ # end
32
+ def predicate_matchers
33
+ @predicate_matchers ||= {}
34
+ end
35
+
36
+ def define_methods_from_predicate_matchers # :nodoc:
37
+ predicate_matchers.each_pair do |matcher_method, method_on_object|
38
+ define_method matcher_method do |*args|
39
+ eval("be_#{method_on_object.to_s.gsub('?','')}(*args)")
40
+ end
41
+ end
42
+ end
43
+
44
+ end
45
+ end
46
+ end
47
+
@@ -0,0 +1,91 @@
1
+ module Spec
2
+ module Example
3
+ module Subject
4
+ module ExampleGroupMethods
5
+ # Defines an explicit subject for an example group which can then be the
6
+ # implicit receiver (through delegation) of calls to +should+.
7
+ #
8
+ # == Examples
9
+ #
10
+ # describe CheckingAccount, "with $50" do
11
+ # subject { CheckingAccount.new(:amount => 50, :currency => :USD) }
12
+ # it { should have_a_balance_of(50, :USD) }
13
+ # it { should_not be_overdrawn }
14
+ # end
15
+ #
16
+ # See +ExampleMethods#should+ for more information about this approach.
17
+ def subject(&block)
18
+ if block.nil?
19
+ @_subject_block || (described_class ? lambda {described_class.new} : lambda {})
20
+ else
21
+ @_subject_block = block
22
+ end
23
+ end
24
+ end
25
+
26
+ module ExampleMethods
27
+ # Returns the subject defined in ExampleGroupMethods#subject. The
28
+ # subject block is only executed once per example, the result of which
29
+ # is cached and returned by any subsequent calls to +subject+.
30
+ #
31
+ # If a class is passed to +describe+ and no subject is explicitly
32
+ # declared in the example group, then +subject+ will return a new
33
+ # instance of that class.
34
+ #
35
+ # == Examples
36
+ #
37
+ # # explicit subject defined by the subject method
38
+ # describe Person do
39
+ # subject { Person.new(:birthdate => 19.years.ago) }
40
+ # it "should be eligible to vote" do
41
+ # subject.should be_eligible_to_vote
42
+ # end
43
+ # end
44
+ #
45
+ # # implicit subject => { Person.new }
46
+ # describe Person do
47
+ # it "should be eligible to vote" do
48
+ # subject.should be_eligible_to_vote
49
+ # end
50
+ # end
51
+ def subject
52
+ @subject ||= instance_eval(&self.class.subject)
53
+ end
54
+
55
+ # When +should+ is called with no explicit receiver, the call is
56
+ # delegated to the object returned by +subject+. Combined with
57
+ # an implicit subject (see +subject+), this supports very concise
58
+ # expressions.
59
+ #
60
+ # == Examples
61
+ #
62
+ # describe Person do
63
+ # it { should be_eligible_to_vote }
64
+ # end
65
+ def should(matcher=nil)
66
+ if matcher
67
+ subject.should(matcher)
68
+ else
69
+ subject.should
70
+ end
71
+ end
72
+
73
+ # Just like +should+, +should_not+ delegates to the subject (implicit or
74
+ # explicit) of the example group.
75
+ #
76
+ # == Examples
77
+ #
78
+ # describe Person do
79
+ # it { should_not be_eligible_to_vote }
80
+ # end
81
+ def should_not(matcher=nil)
82
+ if matcher
83
+ subject.should_not(matcher)
84
+ else
85
+ subject.should_not
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
data/lib/spec/example.rb CHANGED
@@ -173,9 +173,13 @@ module Spec
173
173
  end
174
174
 
175
175
  require 'timeout'
176
+ require 'spec/example/predicate_matchers'
177
+ require 'spec/example/example_description'
178
+ require 'spec/example/subject'
176
179
  require 'spec/example/before_and_after_hooks'
177
180
  require 'spec/example/pending'
178
181
  require 'spec/example/module_reopening_fix'
182
+ require 'spec/example/example_group_hierarchy'
179
183
  require 'spec/example/example_group_methods'
180
184
  require 'spec/example/example_methods'
181
185
  require 'spec/example/example_group'
@@ -1,2 +1 @@
1
1
  require 'spec/expectations/extensions/object'
2
- require 'spec/expectations/extensions/string_and_symbol'
@@ -22,7 +22,12 @@ module Spec
22
22
 
23
23
  return ::Spec::Matchers::NegativeOperatorMatcher.new(actual) if matcher.nil?
24
24
 
25
- match = matcher.matches?(actual, &block)
25
+ match = if matcher.respond_to?(:does_not_match?)
26
+ !matcher.does_not_match?(actual, &block)
27
+ else
28
+ matcher.matches?(actual, &block)
29
+ end
30
+
26
31
  ::Spec::Expectations.fail_with(matcher.negative_failure_message) if match
27
32
  match
28
33
  end
@@ -44,7 +44,7 @@ module Spec
44
44
  # <code>expected</code> and <code>target</code>, passes them
45
45
  # to the differ to append a diff message to the failure message.
46
46
  def self.fail_with(message, expected=nil, target=nil) # :nodoc:
47
- if Array === message && message.length == 3
47
+ if (Array === message) & (message.length == 3)
48
48
  message, expected, target = message[0], message[1], message[2]
49
49
  end
50
50
  unless (differ.nil? || expected.nil? || target.nil?)
@@ -5,8 +5,7 @@ module Test
5
5
  # This extension of the standard Test::Unit::TestCase makes RSpec
6
6
  # available from within, so that you can do things like:
7
7
  #
8
- # require 'test/unit'
9
- # require 'spec'
8
+ # require 'spec/test/unit'
10
9
  #
11
10
  # class MyTest < Test::Unit::TestCase
12
11
  # it "should work with Test::Unit assertions" do
@@ -41,33 +40,17 @@ module Test
41
40
  before(:each) {setup}
42
41
  after(:each) {teardown}
43
42
 
44
- def initialize(defined_description, options={}, &implementation)
45
- @_defined_description = defined_description
46
-
47
- # TODO - examples fail in rspec-rails if we remove "|| pending_implementation"
48
- # - find a way to fail without it in rspec's code examples
49
- @_implementation = implementation || pending_implementation
50
-
51
- @_result = ::Test::Unit::TestResult.new
52
- # @method_name is important to set here because it complies with Test::Unit's interface.
43
+ def initialize(description, options={}, &implementation)
44
+ super
53
45
  # Some Test::Unit extensions depend on @method_name being present.
54
- @method_name = @_defined_description
55
-
56
- # TODO - this is necessary to run single examples in rspec-rails, but I haven't
57
- # found a good way to write a failing example just within rspec core
58
- @_backtrace = caller
46
+ @method_name = description
47
+ @_result = ::Test::Unit::TestResult.new
59
48
  end
60
49
 
61
50
  def run(ignore_this_argument=nil)
62
51
  super()
63
52
  end
64
53
 
65
- private
66
-
67
- def pending_implementation
68
- error = Spec::Example::NotYetImplementedError.new(caller)
69
- lambda { raise(error) }
70
- end
71
54
  end
72
55
  end
73
56
  end
@@ -1,3 +1,4 @@
1
+ require 'spec'
1
2
  require 'test/unit'
2
3
  require 'test/unit/testresult'
3
4
 
@@ -60,12 +60,7 @@ it reads really poorly.
60
60
 
61
61
  private
62
62
  def match_or_compare(actual)
63
- case @expected
64
- when TrueClass
65
- @actual
66
- else
67
- @actual.__send__(comparison_method, @expected)
68
- end
63
+ TrueClass === @expected ? @actual : @actual.__send__(comparison_method, @expected)
69
64
  end
70
65
 
71
66
  def comparison_method
@@ -87,7 +82,7 @@ it reads really poorly.
87
82
  def parse_expected(expected)
88
83
  ["be_an_","be_a_","be_"].each do |prefix|
89
84
  handling_predicate!
90
- if expected.starts_with?(prefix)
85
+ if expected.to_s =~ /^#{prefix}/
91
86
  set_prefix(prefix)
92
87
  expected = expected.to_s.sub(prefix,"")
93
88
  [true, false, nil].each do |val|
@@ -1,5 +1,24 @@
1
1
  module Spec
2
2
  module Matchers
3
+
4
+ class BeClose
5
+ def initialize(expected, delta)
6
+ @expected, @delta = expected, delta
7
+ end
8
+
9
+ def matches?(actual)
10
+ @actual = actual
11
+ (@actual - @expected).abs < @delta
12
+ end
13
+
14
+ def failure_message
15
+ "expected #{@expected} +/- (< #{@delta}), got #{@actual}"
16
+ end
17
+
18
+ def description
19
+ "be close to #{@expected} (within +- #{@delta})"
20
+ end
21
+ end
3
22
 
4
23
  # :call-seq:
5
24
  # should be_close(expected, delta)
@@ -11,11 +30,7 @@ module Spec
11
30
  #
12
31
  # result.should be_close(3.0, 0.5)
13
32
  def be_close(expected, delta)
14
- simple_matcher do |actual, matcher|
15
- matcher.failure_message = "expected #{expected} +/- (< #{delta}), got #{actual}"
16
- matcher.description = "be close to #{expected} (within +- #{delta})"
17
- (actual - expected).abs < delta
18
- end
33
+ BeClose.new(expected, delta)
19
34
  end
20
35
  end
21
36
  end
@@ -5,9 +5,7 @@ module Spec
5
5
  class Change #:nodoc:
6
6
  def initialize(receiver=nil, message=nil, &block)
7
7
  @message = message || "result"
8
- @value_proc = block || lambda {
9
- receiver.__send__(message)
10
- }
8
+ @value_proc = block || lambda {receiver.__send__(message)}
11
9
  end
12
10
 
13
11
  def matches?(event_proc)
@@ -84,6 +82,10 @@ MESSAGE
84
82
  @from = from
85
83
  self
86
84
  end
85
+
86
+ def description
87
+ "change ##{@message}"
88
+ end
87
89
  end
88
90
 
89
91
  # :call-seq:
@@ -1,5 +1,28 @@
1
1
  module Spec
2
2
  module Matchers
3
+ class Eql
4
+ def initialize(expected)
5
+ @expected = expected
6
+ end
7
+
8
+ def matches?(actual)
9
+ @actual = actual
10
+ @actual.eql?(@expected)
11
+ end
12
+
13
+ def failure_message
14
+ return "expected #{@expected.inspect}, got #{@actual.inspect} (using .eql?)", @expected, @actual
15
+ end
16
+
17
+ def negative_failure_message
18
+ return "expected #{@actual.inspect} not to equal #{@expected.inspect} (using .eql?)", @expected, @actual
19
+ end
20
+
21
+ def description
22
+ "eql #{@expected.inspect}"
23
+ end
24
+ end
25
+
3
26
 
4
27
  # :call-seq:
5
28
  # should eql(expected)
@@ -14,12 +37,7 @@ module Spec
14
37
  # 5.should eql(5)
15
38
  # 5.should_not eql(3)
16
39
  def eql(expected)
17
- simple_matcher do |actual, matcher|
18
- matcher.failure_message = "expected #{expected.inspect}, got #{actual.inspect} (using .eql?)", expected, actual
19
- matcher.negative_failure_message = "expected #{actual.inspect} not to equal #{expected.inspect} (using .eql?)", expected, actual
20
- matcher.description = "eql #{expected.inspect}"
21
- actual.eql?(expected)
22
- end
40
+ Eql.new(expected)
23
41
  end
24
42
  end
25
43
  end
@@ -1,5 +1,28 @@
1
1
  module Spec
2
2
  module Matchers
3
+
4
+ class Equal
5
+ def initialize(expected)
6
+ @expected = expected
7
+ end
8
+
9
+ def matches?(actual)
10
+ @actual = actual
11
+ @actual.equal?(@expected)
12
+ end
13
+
14
+ def failure_message
15
+ return "expected #{@expected.inspect}, got #{@actual.inspect} (using .equal?)", @expected, @actual
16
+ end
17
+
18
+ def negative_failure_message
19
+ return "expected #{@actual.inspect} not to equal #{@expected.inspect} (using .equal?)", @expected, @actual
20
+ end
21
+
22
+ def description
23
+ "equal #{@expected.inspect}"
24
+ end
25
+ end
3
26
 
4
27
  # :call-seq:
5
28
  # should equal(expected)
@@ -14,12 +37,7 @@ module Spec
14
37
  # 5.should equal(5) #Fixnums are equal
15
38
  # "5".should_not equal("5") #Strings that look the same are not the same object
16
39
  def equal(expected)
17
- simple_matcher do |actual, matcher|
18
- matcher.failure_message = "expected #{expected.inspect}, got #{actual.inspect} (using .equal?)", expected, actual
19
- matcher.negative_failure_message = "expected #{actual.inspect} not to equal #{expected.inspect} (using .equal?)", expected, actual
20
- matcher.description = "equal #{expected.inspect}"
21
- actual.equal?(expected)
22
- end
40
+ Equal.new(expected)
23
41
  end
24
42
  end
25
43
  end
@@ -1,16 +1,32 @@
1
1
  module Spec
2
2
  module Matchers
3
+
4
+ class Exist
5
+ def matches?(actual)
6
+ @actual = actual
7
+ actual.exist?
8
+ end
9
+
10
+ def failure_message
11
+ "expected #{@actual.inspect} to exist, but it doesn't."
12
+ end
13
+
14
+ def negative_failure_message
15
+ "expected #{@actual.inspect} to not exist, but it does."
16
+ end
17
+
18
+ def description
19
+ "exists"
20
+ end
21
+ end
22
+
3
23
  # :call-seq:
4
24
  # should exist
5
25
  # should_not exist
6
26
  #
7
27
  # Passes if actual.exist?
8
28
  def exist
9
- simple_matcher do |actual, matcher|
10
- matcher.failure_message = "expected #{actual.inspect} to exist, but it doesn't."
11
- matcher.negative_failure_message = "expected #{actual.inspect} to not exist, but it does."
12
- actual.exist?
13
- end
29
+ Exist.new
14
30
  end
15
31
  end
16
32
  end
@@ -38,11 +38,11 @@ or this:
38
38
 
39
39
  it { should matcher }
40
40
 
41
- the runner expects the matcher to have a #describe method. You should either
41
+ the runner expects the matcher to have a #description method. You should either
42
42
  add a String to the example this matcher is being used in, or give it a
43
43
  description method. Then you won't have to suffer this lengthy warning again.
44
44
  MESSAGE
45
45
  end
46
46
  end
47
47
  end
48
-
48
+
@@ -1,18 +1,35 @@
1
1
  module Spec
2
2
  module Matchers
3
- def has(sym, *args) # :nodoc:
4
- simple_matcher do |actual, matcher|
5
- matcher.failure_message = "expected ##{predicate(sym)}(#{args[0].inspect}) to return true, got false"
6
- matcher.negative_failure_message = "expected ##{predicate(sym)}(#{args[0].inspect}) to return false, got true"
7
- matcher.description = "have key #{args[0].inspect}"
8
- actual.__send__(predicate(sym), *args)
3
+
4
+ class Has
5
+
6
+ def initialize(expected, *args)
7
+ @expected, @args = expected, args
9
8
  end
10
- end
9
+
10
+ def matches?(actual)
11
+ actual.__send__(predicate(@expected), *@args)
12
+ end
13
+
14
+ def failure_message
15
+ "expected ##{predicate(@expected)}(#{@args[0].inspect}) to return true, got false"
16
+ end
17
+
18
+ def negative_failure_message
19
+ "expected ##{predicate(@expected)}(#{@args[0].inspect}) to return false, got true"
20
+ end
21
+
22
+ def description
23
+ "have key #{@args[0].inspect}"
24
+ end
25
+
26
+ private
11
27
 
12
- private
13
- def predicate(sym)
14
- "#{sym.to_s.sub("have_","has_")}?".to_sym
28
+ def predicate(sym)
29
+ "#{sym.to_s.sub("have_","has_")}?".to_sym
30
+ end
31
+
15
32
  end
16
-
33
+
17
34
  end
18
35
  end
@@ -1,5 +1,28 @@
1
1
  module Spec
2
2
  module Matchers
3
+ class Match
4
+ def initialize(expected)
5
+ @expected = expected
6
+ end
7
+
8
+ def matches?(actual)
9
+ @actual = actual
10
+ actual =~ @expected
11
+ end
12
+
13
+ def failure_message
14
+ return "expected #{@actual.inspect} to match #{@expected.inspect}", @expected, @actual
15
+ end
16
+
17
+ def negative_failure_message
18
+ return "expected #{@actual.inspect} not to match #{@expected.inspect}", @expected, @actual
19
+ end
20
+
21
+ def description
22
+ "match #{@expected.inspect}"
23
+ end
24
+ end
25
+
3
26
 
4
27
  # :call-seq:
5
28
  # should match(regexp)
@@ -10,13 +33,8 @@ module Spec
10
33
  # == Examples
11
34
  #
12
35
  # email.should match(/^([^\s]+)((?:[-a-z0-9]+\.)+[a-z]{2,})$/i)
13
- def match(regexp)
14
- simple_matcher do |actual, matcher|
15
- matcher.failure_message = "expected #{actual.inspect} to match #{regexp.inspect}", regexp, actual
16
- matcher.negative_failure_message = "expected #{actual.inspect} not to match #{regexp.inspect}", regexp, actual
17
- matcher.description = "match #{regexp.inspect}"
18
- actual =~ regexp
19
- end
36
+ def match(expected)
37
+ Match.new(expected)
20
38
  end
21
39
  end
22
40
  end
@@ -11,7 +11,7 @@ module Spec
11
11
  @actual = actual
12
12
  @extra_items = difference_between_arrays(@actual, @expected)
13
13
  @missing_items = difference_between_arrays(@expected, @actual)
14
- @extra_items.empty? && @missing_items.empty?
14
+ @extra_items.empty? & @missing_items.empty?
15
15
  end
16
16
 
17
17
  def failure_message
@@ -1,8 +1,8 @@
1
1
  module Spec
2
2
  module Matchers
3
3
  def method_missing(sym, *args, &block) # :nodoc:
4
- return Matchers::Be.new(sym, *args) if sym.starts_with?("be_")
5
- return has(sym, *args) if sym.starts_with?("have_")
4
+ return Matchers::Be.new(sym, *args) if sym.to_s =~ /^be_/
5
+ return Matchers::Has.new(sym, *args) if sym.to_s =~ /^have_/
6
6
  super
7
7
  end
8
8
  end
@@ -4,15 +4,16 @@ module Spec
4
4
  class OperatorMatcher
5
5
  class << self
6
6
  def registry
7
- @registry ||= Hash.new {|h,k| h[k] = {}}
7
+ @registry ||= {}
8
8
  end
9
9
 
10
10
  def register(klass, operator, matcher)
11
+ registry[klass] ||= {}
11
12
  registry[klass][operator] = matcher
12
13
  end
13
14
 
14
15
  def get(klass, operator)
15
- registry[klass][operator]
16
+ registry[klass] && registry[klass][operator]
16
17
  end
17
18
  end
18
19
 
@@ -25,9 +26,7 @@ module Spec
25
26
  if matcher = OperatorMatcher.get(@actual.class, operator)
26
27
  @actual.send(::Spec::Matchers.last_should, matcher.new(expected))
27
28
  else
28
- ::Spec::Matchers.last_matcher = self
29
- @operator, @expected = operator, expected
30
- __delegate_operator(@actual, operator, expected)
29
+ eval_match(@actual, operator, expected)
31
30
  end
32
31
  end
33
32
  end
@@ -43,6 +42,14 @@ module Spec
43
42
  def description
44
43
  "#{@operator} #{@expected.inspect}"
45
44
  end
45
+
46
+ private
47
+
48
+ def eval_match(actual, operator, expected)
49
+ ::Spec::Matchers.last_matcher = self
50
+ @operator, @expected = operator, expected
51
+ __delegate_operator(actual, operator, expected)
52
+ end
46
53
 
47
54
  end
48
55
 
@@ -31,7 +31,7 @@ module Spec
31
31
  eval_block if @raised_expected_error && @with_expected_message && @block
32
32
  end
33
33
  ensure
34
- return (@raised_expected_error && @with_expected_message) ? (@eval_block ? @eval_block_passed : true) : false
34
+ return (@raised_expected_error & @with_expected_message) ? (@eval_block ? @eval_block_passed : true) : false
35
35
  end
36
36
 
37
37
  def eval_block
@@ -25,7 +25,6 @@ module Spec
25
25
  end
26
26
 
27
27
  def description
28
- # Ruby 1.9 returns the same thing for array.to_s as array.inspect, so just use array.inspect here
29
28
  "respond to #{pp_names}#{with_arity}"
30
29
  end
31
30
 
@@ -51,6 +50,7 @@ module Spec
51
50
  end
52
51
 
53
52
  def pp_names
53
+ # Ruby 1.9 returns the same thing for array.to_s as array.inspect, so just use array.inspect here
54
54
  @names.length == 1 ? "##{@names.first}" : @names.inspect
55
55
  end
56
56
  end