rspec 1.1.4 → 1.1.5
Sign up to get free protection for your applications and to get access to all the features.
- data/{CHANGES → History.txt} +116 -64
- data/Manifest.txt +403 -0
- data/{MIT-LICENSE → README.txt} +43 -0
- data/Rakefile +39 -212
- data/{TODO → TODO.txt} +0 -0
- data/bin/autospec +4 -0
- data/bin/spec +1 -1
- data/examples/pure/yielding_example.rb +33 -0
- data/examples/stories/game-of-life/.loadpath +5 -0
- data/examples/stories/game-of-life/behaviour/everything.rb +1 -1
- data/examples/stories/game-of-life/behaviour/stories/CellsWithMoreThanThreeNeighboursDie.story +17 -17
- data/init.rb +9 -0
- data/lib/autotest/discover.rb +1 -1
- data/lib/autotest/rspec.rb +3 -29
- data/lib/spec.rb +10 -12
- data/lib/spec/adapters.rb +1 -0
- data/lib/spec/adapters/ruby_engine.rb +26 -0
- data/lib/spec/adapters/ruby_engine/mri.rb +8 -0
- data/lib/spec/adapters/ruby_engine/rubinius.rb +8 -0
- data/lib/spec/example/errors.rb +6 -0
- data/lib/spec/example/example_group_methods.rb +17 -14
- data/lib/spec/example/example_matcher.rb +2 -0
- data/lib/spec/example/example_methods.rb +4 -9
- data/lib/spec/example/module_inclusion_warnings.rb +2 -1
- data/lib/spec/expectations/extensions/object.rb +2 -2
- data/lib/spec/expectations/handler.rb +8 -16
- data/lib/spec/extensions/main.rb +2 -17
- data/lib/spec/matchers.rb +8 -2
- data/lib/spec/matchers/be.rb +0 -3
- data/lib/spec/matchers/change.rb +44 -40
- data/lib/spec/matchers/has.rb +1 -1
- data/lib/spec/matchers/have.rb +17 -12
- data/lib/spec/matchers/operator_matcher.rb +10 -4
- data/lib/spec/matchers/simple_matcher.rb +113 -10
- data/lib/spec/mocks.rb +1 -1
- data/lib/spec/mocks/argument_constraints.rb +185 -0
- data/lib/spec/mocks/argument_expectation.rb +35 -173
- data/lib/spec/mocks/framework.rb +1 -1
- data/lib/spec/mocks/message_expectation.rb +30 -5
- data/lib/spec/mocks/methods.rb +14 -2
- data/lib/spec/mocks/mock.rb +4 -0
- data/lib/spec/mocks/proxy.rb +46 -5
- data/lib/spec/mocks/spec_methods.rb +9 -1
- data/lib/spec/rake/spectask.rb +14 -22
- data/lib/spec/rake/verify_rcov.rb +3 -3
- data/lib/spec/runner.rb +18 -6
- data/lib/spec/runner/backtrace_tweaker.rb +6 -7
- data/lib/spec/runner/command_line.rb +6 -17
- data/lib/spec/runner/drb_command_line.rb +1 -1
- data/lib/spec/runner/formatter/base_formatter.rb +3 -1
- data/lib/spec/runner/formatter/base_text_formatter.rb +5 -9
- data/lib/spec/runner/formatter/html_formatter.rb +1 -1
- data/lib/spec/runner/formatter/nested_text_formatter.rb +1 -1
- data/lib/spec/runner/formatter/progress_bar_formatter.rb +2 -2
- data/lib/spec/runner/formatter/specdoc_formatter.rb +1 -1
- data/lib/spec/runner/formatter/story/html_formatter.rb +62 -16
- data/lib/spec/runner/formatter/story/plain_text_formatter.rb +68 -16
- data/lib/spec/runner/formatter/story/progress_bar_formatter.rb +42 -0
- data/lib/spec/runner/heckle_runner.rb +2 -2
- data/lib/spec/runner/option_parser.rb +2 -1
- data/lib/spec/runner/options.rb +18 -9
- data/lib/spec/runner/reporter.rb +24 -4
- data/lib/spec/runner/spec_parser.rb +1 -1
- data/lib/spec/story/runner.rb +1 -2
- data/lib/spec/story/runner/story_mediator.rb +14 -0
- data/lib/spec/story/runner/story_parser.rb +20 -0
- data/lib/spec/story/step.rb +40 -28
- data/lib/spec/story/step_mother.rb +2 -1
- data/lib/spec/story/world.rb +6 -2
- data/lib/spec/version.rb +13 -22
- data/rake_tasks/failing_examples_with_html.rake +1 -1
- data/rake_tasks/verify_rcov.rake +2 -2
- data/rspec.gemspec +33 -0
- data/spec/autotest/rspec_spec.rb +90 -141
- data/spec/spec/adapters/ruby_engine_spec.rb +16 -0
- data/spec/spec/example/base_formatter_spec.rb +112 -0
- data/spec/spec/example/example_group_factory_spec.rb +2 -2
- data/spec/spec/example/example_group_methods_spec.rb +55 -4
- data/spec/spec/example/example_group_spec.rb +4 -3
- data/spec/spec/example/example_methods_spec.rb +18 -14
- data/spec/spec/example/pending_module_spec.rb +38 -0
- data/spec/spec/example/shared_example_group_spec.rb +1 -1
- data/spec/spec/expectations/extensions/object_spec.rb +0 -12
- data/spec/spec/extensions/main_spec.rb +3 -8
- data/spec/spec/matchers/change_spec.rb +16 -6
- data/spec/spec/matchers/handler_spec.rb +58 -37
- data/spec/spec/matchers/has_spec.rb +10 -0
- data/spec/spec/matchers/have_spec.rb +105 -2
- data/spec/spec/matchers/operator_matcher_spec.rb +35 -2
- data/spec/spec/matchers/simple_matcher_spec.rb +64 -2
- data/spec/spec/mocks/any_number_of_times_spec.rb +7 -0
- data/spec/spec/mocks/bug_report_496.rb +17 -0
- data/spec/spec/mocks/failing_mock_argument_constraints_spec.rb +7 -1
- data/spec/spec/mocks/hash_including_matcher_spec.rb +45 -24
- data/spec/spec/mocks/mock_spec.rb +55 -10
- data/spec/spec/mocks/nil_expectation_warning_spec.rb +54 -0
- data/spec/spec/mocks/null_object_mock_spec.rb +14 -0
- data/spec/spec/mocks/options_hash_spec.rb +18 -28
- data/spec/spec/mocks/partial_mock_spec.rb +2 -0
- data/spec/spec/mocks/passing_mock_argument_constraints_spec.rb +20 -6
- data/spec/spec/mocks/stub_spec.rb +7 -0
- data/spec/spec/runner/command_line_spec.rb +5 -12
- data/spec/spec/runner/drb_command_line_spec.rb +13 -6
- data/spec/spec/runner/formatter/html_formatter_spec.rb +2 -1
- data/spec/spec/runner/formatter/nested_text_formatter_spec.rb +3 -3
- data/spec/spec/runner/formatter/progress_bar_formatter_spec.rb +20 -2
- data/spec/spec/runner/formatter/spec_mate_formatter_spec.rb +2 -1
- data/spec/spec/runner/formatter/specdoc_formatter_spec.rb +3 -3
- data/spec/spec/runner/formatter/story/html_formatter_spec.rb +76 -2
- data/spec/spec/runner/formatter/story/plain_text_formatter_spec.rb +161 -0
- data/spec/spec/runner/formatter/story/progress_bar_formatter_spec.rb +82 -0
- data/spec/spec/runner/heckle_runner_spec.rb +8 -8
- data/spec/spec/runner/option_parser_spec.rb +21 -6
- data/spec/spec/runner/output_one_time_fixture_runner.rb +1 -1
- data/spec/spec/runner/quiet_backtrace_tweaker_spec.rb +6 -0
- data/spec/spec/runner/reporter_spec.rb +51 -5
- data/spec/spec/runner/spec_parser_spec.rb +4 -4
- data/spec/spec/story/runner/plain_text_story_runner_spec.rb +2 -5
- data/spec/spec/story/runner/story_mediator_spec.rb +10 -0
- data/spec/spec/story/runner/story_parser_spec.rb +23 -6
- data/spec/spec/story/scenario_spec.rb +1 -3
- data/spec/spec/story/step_mother_spec.rb +12 -0
- data/spec/spec/story/step_spec.rb +57 -4
- data/spec/spec/story/story_spec.rb +1 -3
- data/spec/spec/story/world_spec.rb +1 -1
- data/spec/spec_helper.rb +21 -68
- data/stories/all.rb +1 -1
- data/stories/configuration/before_blocks.story +21 -0
- data/stories/configuration/stories.rb +7 -0
- data/stories/example_groups/stories.rb +3 -4
- data/stories/resources/spec/before_blocks_example.rb +32 -0
- data/stories/stories/multiline_steps.story +23 -0
- data/stories/stories/steps/multiline_steps.rb +13 -0
- data/stories/stories/stories.rb +6 -0
- data/story_server/prototype/javascripts/builder.js +136 -0
- data/story_server/prototype/javascripts/controls.js +972 -0
- data/story_server/prototype/javascripts/dragdrop.js +976 -0
- data/story_server/prototype/javascripts/effects.js +1117 -0
- data/story_server/prototype/javascripts/prototype.js +4140 -0
- data/story_server/prototype/javascripts/rspec.js +149 -0
- data/story_server/prototype/javascripts/scriptaculous.js +58 -0
- data/story_server/prototype/javascripts/slider.js +276 -0
- data/story_server/prototype/javascripts/sound.js +55 -0
- data/story_server/prototype/javascripts/unittest.js +568 -0
- data/story_server/prototype/lib/server.rb +24 -0
- data/story_server/prototype/stories.html +176 -0
- data/story_server/prototype/stylesheets/rspec.css +136 -0
- data/story_server/prototype/stylesheets/test.css +90 -0
- metadata +166 -166
- data/README +0 -36
- data/UPGRADE +0 -7
- data/bin/spec_translator +0 -8
- data/lib/spec/mocks/argument_constraint_matchers.rb +0 -31
- data/lib/spec/translator.rb +0 -114
- data/spec/spec/example/example_spec.rb +0 -53
- data/spec/spec/runner/execution_context_spec.rb +0 -37
- data/spec/spec/translator_spec.rb +0 -265
@@ -2,38 +2,29 @@ module Spec
|
|
2
2
|
module Expectations
|
3
3
|
class InvalidMatcherError < ArgumentError; end
|
4
4
|
|
5
|
-
module MatcherHandlerHelper
|
6
|
-
def describe_matcher(matcher)
|
7
|
-
matcher.respond_to?(:description) ? matcher.description : "[#{matcher.class.name} does not provide a description]"
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
5
|
class ExpectationMatcherHandler
|
12
6
|
class << self
|
13
|
-
include MatcherHandlerHelper
|
14
7
|
def handle_matcher(actual, matcher, &block)
|
15
|
-
|
16
|
-
|
17
|
-
end
|
8
|
+
::Spec::Matchers.last_should = "should"
|
9
|
+
return Spec::Matchers::PositiveOperatorMatcher.new(actual) if matcher.nil?
|
18
10
|
|
19
11
|
unless matcher.respond_to?(:matches?)
|
20
12
|
raise InvalidMatcherError, "Expected a matcher, got #{matcher.inspect}."
|
21
13
|
end
|
22
14
|
|
23
15
|
match = matcher.matches?(actual, &block)
|
24
|
-
::Spec::Matchers.
|
16
|
+
::Spec::Matchers.last_matcher = matcher
|
25
17
|
Spec::Expectations.fail_with(matcher.failure_message) unless match
|
18
|
+
match
|
26
19
|
end
|
27
20
|
end
|
28
21
|
end
|
29
22
|
|
30
23
|
class NegativeExpectationMatcherHandler
|
31
24
|
class << self
|
32
|
-
include MatcherHandlerHelper
|
33
25
|
def handle_matcher(actual, matcher, &block)
|
34
|
-
|
35
|
-
|
36
|
-
end
|
26
|
+
::Spec::Matchers.last_should = "should not"
|
27
|
+
return Spec::Matchers::NegativeOperatorMatcher.new(actual) if matcher.nil?
|
37
28
|
|
38
29
|
unless matcher.respond_to?(:matches?)
|
39
30
|
raise InvalidMatcherError, "Expected a matcher, got #{matcher.inspect}."
|
@@ -49,8 +40,9 @@ EOF
|
|
49
40
|
)
|
50
41
|
end
|
51
42
|
match = matcher.matches?(actual, &block)
|
52
|
-
::Spec::Matchers.
|
43
|
+
::Spec::Matchers.last_matcher = matcher
|
53
44
|
Spec::Expectations.fail_with(matcher.negative_failure_message) if match
|
45
|
+
match
|
54
46
|
end
|
55
47
|
end
|
56
48
|
end
|
data/lib/spec/extensions/main.rb
CHANGED
@@ -23,7 +23,7 @@ module Spec
|
|
23
23
|
raise ArgumentError if args.empty?
|
24
24
|
raise ArgumentError unless block
|
25
25
|
args << {} unless Hash === args.last
|
26
|
-
args.last[:spec_path] = caller(0)[1]
|
26
|
+
args.last[:spec_path] = File.expand_path(caller(0)[1])
|
27
27
|
Spec::Example::ExampleGroupFactory.create_example_group(*args, &block)
|
28
28
|
end
|
29
29
|
alias :context :describe
|
@@ -80,23 +80,8 @@ module Spec
|
|
80
80
|
raise NameError.new(e.message + "\nThe first argument to share_as must be a legal name for a constant\n")
|
81
81
|
end
|
82
82
|
end
|
83
|
-
|
84
|
-
private
|
85
|
-
|
86
|
-
def rspec_options
|
87
|
-
$rspec_options ||= begin; \
|
88
|
-
parser = ::Spec::Runner::OptionParser.new(STDERR, STDOUT); \
|
89
|
-
parser.order!(ARGV); \
|
90
|
-
$rspec_options = parser.options; \
|
91
|
-
end
|
92
|
-
$rspec_options
|
93
|
-
end
|
94
|
-
|
95
|
-
def init_rspec_options(options)
|
96
|
-
$rspec_options = options if $rspec_options.nil?
|
97
|
-
end
|
98
83
|
end
|
99
84
|
end
|
100
85
|
end
|
101
86
|
|
102
|
-
include Spec::Extensions::Main
|
87
|
+
include Spec::Extensions::Main
|
data/lib/spec/matchers.rb
CHANGED
@@ -134,10 +134,16 @@ module Spec
|
|
134
134
|
#
|
135
135
|
module Matchers
|
136
136
|
module ModuleMethods
|
137
|
-
attr_accessor :
|
137
|
+
attr_accessor :last_matcher, :last_should
|
138
138
|
|
139
139
|
def clear_generated_description
|
140
|
-
self.
|
140
|
+
self.last_matcher = nil
|
141
|
+
self.last_should = nil
|
142
|
+
end
|
143
|
+
|
144
|
+
def generated_description
|
145
|
+
last_should.nil? ? nil :
|
146
|
+
"#{last_should} #{last_matcher.respond_to?(:description) ? last_matcher.description : 'NO NAME'}"
|
141
147
|
end
|
142
148
|
end
|
143
149
|
|
data/lib/spec/matchers/be.rb
CHANGED
@@ -23,9 +23,6 @@ module Spec
|
|
23
23
|
rcov_error_report = "http://eigenclass.org/hiki.rb?rcov-0.8.0"
|
24
24
|
end
|
25
25
|
|
26
|
-
# This supports should_exist > target.exists? in the old world.
|
27
|
-
# We should consider deprecating that ability as in the new world
|
28
|
-
# you can't write "should exist" unless you have your own custom matcher.
|
29
26
|
begin
|
30
27
|
return @result = actual.__send__(present_tense_predicate, *@args)
|
31
28
|
rescue
|
data/lib/spec/matchers/change.rb
CHANGED
@@ -4,60 +4,60 @@ module Spec
|
|
4
4
|
#Based on patch from Wilson Bilkovich
|
5
5
|
class Change #:nodoc:
|
6
6
|
def initialize(receiver=nil, message=nil, &block)
|
7
|
-
@
|
8
|
-
@
|
9
|
-
|
7
|
+
@message = message || "result"
|
8
|
+
@value_proc = block || lambda {
|
9
|
+
receiver.__send__(message)
|
10
|
+
}
|
10
11
|
end
|
11
12
|
|
12
|
-
def matches?(
|
13
|
-
if
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
@
|
20
|
-
|
21
|
-
return false if @from && (@from != @before)
|
22
|
-
return false if @to && (@to != @after)
|
13
|
+
def matches?(event_proc)
|
14
|
+
raise_block_syntax_error if block_given?
|
15
|
+
|
16
|
+
@before = evaluate_value_proc
|
17
|
+
event_proc.call
|
18
|
+
@after = evaluate_value_proc
|
19
|
+
|
20
|
+
return false if @from unless @from == @before
|
21
|
+
return false if @to unless @to == @after
|
23
22
|
return (@before + @amount == @after) if @amount
|
24
23
|
return ((@after - @before) >= @minimum) if @minimum
|
25
24
|
return ((@after - @before) <= @maximum) if @maximum
|
26
25
|
return @before != @after
|
27
26
|
end
|
28
27
|
|
29
|
-
def
|
30
|
-
|
31
|
-
|
32
|
-
|
28
|
+
def raise_block_syntax_error
|
29
|
+
raise MatcherError.new(<<-MESSAGE
|
30
|
+
block passed to should or should_not change must use {} instead of do/end
|
31
|
+
MESSAGE
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
35
|
+
def evaluate_value_proc
|
36
|
+
@value_proc.call
|
33
37
|
end
|
34
38
|
|
35
39
|
def failure_message
|
36
40
|
if @to
|
37
|
-
"#{
|
41
|
+
"#{@message} should have been changed to #{@to.inspect}, but is now #{@after.inspect}"
|
38
42
|
elsif @from
|
39
|
-
"#{
|
43
|
+
"#{@message} should have initially been #{@from.inspect}, but was #{@before.inspect}"
|
40
44
|
elsif @amount
|
41
|
-
"#{
|
45
|
+
"#{@message} should have been changed by #{@amount.inspect}, but was changed by #{actual_delta.inspect}"
|
42
46
|
elsif @minimum
|
43
|
-
"#{
|
47
|
+
"#{@message} should have been changed by at least #{@minimum.inspect}, but was changed by #{actual_delta.inspect}"
|
44
48
|
elsif @maximum
|
45
|
-
"#{
|
49
|
+
"#{@message} should have been changed by at most #{@maximum.inspect}, but was changed by #{actual_delta.inspect}"
|
46
50
|
else
|
47
|
-
"#{
|
51
|
+
"#{@message} should have changed, but is still #{@before.inspect}"
|
48
52
|
end
|
49
53
|
end
|
50
54
|
|
51
|
-
def result
|
52
|
-
@message || "result"
|
53
|
-
end
|
54
|
-
|
55
55
|
def actual_delta
|
56
56
|
@after - @before
|
57
57
|
end
|
58
58
|
|
59
59
|
def negative_failure_message
|
60
|
-
"#{
|
60
|
+
"#{@message} should not have changed, but did change from #{@before.inspect} to #{@after.inspect}"
|
61
61
|
end
|
62
62
|
|
63
63
|
def by(amount)
|
@@ -125,20 +125,24 @@ EOF
|
|
125
125
|
# employee.develop_great_new_social_networking_app
|
126
126
|
# }.should change(employee, :title).from("Mail Clerk").to("CEO")
|
127
127
|
#
|
128
|
-
# Evaluates
|
129
|
-
#
|
128
|
+
# Evaluates <tt>receiver.message</tt> or <tt>block</tt> before and after
|
129
|
+
# it evaluates the c object (generated by the lambdas in the examples
|
130
|
+
# above).
|
131
|
+
#
|
132
|
+
# Then compares the values before and after the <tt>receiver.message</tt>
|
133
|
+
# and evaluates the difference compared to the expected difference.
|
130
134
|
#
|
131
|
-
#
|
132
|
-
#
|
135
|
+
# == WARNING
|
136
|
+
# <tt>should_not change</tt> only supports the form with no
|
137
|
+
# subsequent calls to <tt>by</tt>, <tt>by_at_least</tt>,
|
138
|
+
# <tt>by_at_most</tt>, <tt>to</tt> or <tt>from</tt>.
|
133
139
|
#
|
134
|
-
#
|
135
|
-
#
|
136
|
-
#
|
140
|
+
# blocks passed to <tt>should</tt> <tt>change</tt> and <tt>should_not</tt>
|
141
|
+
# <tt>change</tt> must use the <tt>{}</tt> form (<tt>do/end</tt> is not
|
142
|
+
# supported).
|
137
143
|
#
|
138
|
-
|
139
|
-
|
140
|
-
def change(target=nil, message=nil, &block)
|
141
|
-
Matchers::Change.new(target, message, &block)
|
144
|
+
def change(receiver=nil, message=nil, &block)
|
145
|
+
Matchers::Change.new(receiver, message, &block)
|
142
146
|
end
|
143
147
|
end
|
144
148
|
end
|
data/lib/spec/matchers/has.rb
CHANGED
data/lib/spec/matchers/have.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
module Spec
|
2
2
|
module Matchers
|
3
|
-
|
4
3
|
class Have #:nodoc:
|
5
4
|
def initialize(expected, relativity=:exactly)
|
6
5
|
@expected = (expected == :no ? 0 : expected)
|
@@ -15,23 +14,15 @@ module Spec
|
|
15
14
|
}
|
16
15
|
end
|
17
16
|
|
18
|
-
def method_missing(sym, *args, &block)
|
19
|
-
@collection_name = sym
|
20
|
-
@plural_collection_name = Inflector.pluralize(sym.to_s) if Object.const_defined?(:Inflector)
|
21
|
-
@args = args
|
22
|
-
@block = block
|
23
|
-
self
|
24
|
-
end
|
25
|
-
|
26
17
|
def matches?(collection_owner)
|
27
18
|
if collection_owner.respond_to?(@collection_name)
|
28
|
-
collection = collection_owner.
|
19
|
+
collection = collection_owner.__send__(@collection_name, *@args, &@block)
|
29
20
|
elsif (@plural_collection_name && collection_owner.respond_to?(@plural_collection_name))
|
30
|
-
collection = collection_owner.
|
21
|
+
collection = collection_owner.__send__(@plural_collection_name, *@args, &@block)
|
31
22
|
elsif (collection_owner.respond_to?(:length) || collection_owner.respond_to?(:size))
|
32
23
|
collection = collection_owner
|
33
24
|
else
|
34
|
-
collection_owner.
|
25
|
+
collection_owner.__send__(@collection_name, *@args, &@block)
|
35
26
|
end
|
36
27
|
@actual = collection.size if collection.respond_to?(:size)
|
37
28
|
@actual = collection.length if collection.respond_to?(:length)
|
@@ -75,8 +66,22 @@ EOF
|
|
75
66
|
"have #{relative_expectation} #{@collection_name}"
|
76
67
|
end
|
77
68
|
|
69
|
+
def respond_to?(sym)
|
70
|
+
@expected.respond_to?(sym) || super
|
71
|
+
end
|
72
|
+
|
78
73
|
private
|
79
74
|
|
75
|
+
def method_missing(sym, *args, &block)
|
76
|
+
@collection_name = sym
|
77
|
+
if inflector = (defined?(ActiveSupport::Inflector) ? ActiveSupport::Inflector : (defined?(Inflector) ? Inflector : nil))
|
78
|
+
@plural_collection_name = inflector.pluralize(sym.to_s)
|
79
|
+
end
|
80
|
+
@args = args
|
81
|
+
@block = block
|
82
|
+
self
|
83
|
+
end
|
84
|
+
|
80
85
|
def relative_expectation
|
81
86
|
"#{relativities[@relativity]}#{@expected}"
|
82
87
|
end
|
@@ -45,14 +45,19 @@ module Spec
|
|
45
45
|
def fail_with_message(message)
|
46
46
|
Spec::Expectations.fail_with(message, @expected, @target)
|
47
47
|
end
|
48
|
+
|
49
|
+
def description
|
50
|
+
"#{@operator} #{@expected.inspect}"
|
51
|
+
end
|
48
52
|
|
49
53
|
end
|
50
54
|
|
51
55
|
class PositiveOperatorMatcher < BaseOperatorMatcher #:nodoc:
|
52
56
|
|
53
57
|
def __delegate_method_missing_to_target(operator, expected)
|
54
|
-
|
55
|
-
|
58
|
+
@operator = operator
|
59
|
+
::Spec::Matchers.last_matcher = self
|
60
|
+
return true if @target.__send__(operator, expected)
|
56
61
|
return fail_with_message("expected: #{expected.inspect},\n got: #{@target.inspect} (using #{operator})") if ['==','===', '=~'].include?(operator)
|
57
62
|
return fail_with_message("expected: #{operator} #{expected.inspect},\n got: #{operator.gsub(/./, ' ')} #{@target.inspect}")
|
58
63
|
end
|
@@ -62,8 +67,9 @@ module Spec
|
|
62
67
|
class NegativeOperatorMatcher < BaseOperatorMatcher #:nodoc:
|
63
68
|
|
64
69
|
def __delegate_method_missing_to_target(operator, expected)
|
65
|
-
|
66
|
-
|
70
|
+
@operator = operator
|
71
|
+
::Spec::Matchers.last_matcher = self
|
72
|
+
return true unless @target.__send__(operator, expected)
|
67
73
|
return fail_with_message("expected not: #{operator} #{expected.inspect},\n got: #{operator.gsub(/./, ' ')} #{@target.inspect}")
|
68
74
|
end
|
69
75
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Spec
|
2
2
|
module Matchers
|
3
3
|
class SimpleMatcher
|
4
|
-
|
4
|
+
attr_writer :failure_message, :negative_failure_message, :description
|
5
5
|
|
6
6
|
def initialize(description, &match_block)
|
7
7
|
@description = description
|
@@ -10,20 +10,123 @@ module Spec
|
|
10
10
|
|
11
11
|
def matches?(actual)
|
12
12
|
@actual = actual
|
13
|
-
|
13
|
+
case @match_block.arity
|
14
|
+
when 2
|
15
|
+
@match_block.call(@actual, self)
|
16
|
+
else
|
17
|
+
@match_block.call(@actual)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def description
|
22
|
+
@description || explanation
|
14
23
|
end
|
15
24
|
|
16
|
-
def failure_message
|
17
|
-
|
25
|
+
def failure_message
|
26
|
+
@failure_message || (@description.nil? ? explanation : %[expected #{@description.inspect} but got #{@actual.inspect}])
|
18
27
|
end
|
19
|
-
|
20
|
-
def negative_failure_message
|
21
|
-
|
28
|
+
|
29
|
+
def negative_failure_message
|
30
|
+
@negative_failure_message || (@description.nil? ? explanation : %[expected not to get #{@description.inspect}, but got #{@actual.inspect}])
|
31
|
+
end
|
32
|
+
|
33
|
+
def explanation
|
34
|
+
"No description provided. See RDoc for simple_matcher()"
|
22
35
|
end
|
23
36
|
end
|
24
|
-
|
25
|
-
|
26
|
-
|
37
|
+
|
38
|
+
# simple_matcher makes it easy for you to create your own custom matchers
|
39
|
+
# in just a few lines of code when you don't need all the power of a
|
40
|
+
# completely custom matcher object.
|
41
|
+
#
|
42
|
+
# The <tt>description</tt> argument will appear as part of any failure
|
43
|
+
# message, and is also the source for auto-generated descriptions.
|
44
|
+
#
|
45
|
+
# The <tt>match_block</tt> can have an arity of 1 or 2. The first block
|
46
|
+
# argument will be the given value. The second, if the block accepts it
|
47
|
+
# will be the matcher itself, giving you access to set custom failure
|
48
|
+
# messages in favor of the defaults.
|
49
|
+
#
|
50
|
+
# The <tt>match_block</tt> should return a boolean: <tt>true</tt>
|
51
|
+
# indicates a match, which will pass if you use <tt>should</tt> and fail
|
52
|
+
# if you use <tt>should_not</tt>. false (or nil) indicates no match,
|
53
|
+
# which will do the reverse: fail if you use <tt>should</tt> and pass if
|
54
|
+
# you use <tt>should_not</tt>.
|
55
|
+
#
|
56
|
+
# An error in the <tt>match_block</tt> will bubble up, resulting in a
|
57
|
+
# failure.
|
58
|
+
#
|
59
|
+
# == Example with default messages
|
60
|
+
#
|
61
|
+
# def be_even
|
62
|
+
# simple_matcher("an even number") { |given| given % 2 == 0 }
|
63
|
+
# end
|
64
|
+
#
|
65
|
+
# describe 2 do
|
66
|
+
# it "should be even" do
|
67
|
+
# 2.should be_even
|
68
|
+
# end
|
69
|
+
# end
|
70
|
+
#
|
71
|
+
# Given an odd number, this example would produce an error message stating:
|
72
|
+
# expected "an even number", got 3.
|
73
|
+
#
|
74
|
+
# Unfortunately, if you're a fan of auto-generated descriptions, this will
|
75
|
+
# produce "should an even number." Not the most desirable result. You can
|
76
|
+
# control that using custom messages:
|
77
|
+
#
|
78
|
+
# == Example with custom messages
|
79
|
+
#
|
80
|
+
# def rhyme_with(expected)
|
81
|
+
# simple_matcher("rhyme with #{expected.inspect}") do |given, matcher|
|
82
|
+
# matcher.failure_message = "expected #{given.inspect} to rhyme with #{expected.inspect}"
|
83
|
+
# matcher.negative_failure_message = "expected #{given.inspect} not to rhyme with #{expected.inspect}"
|
84
|
+
# actual.rhymes_with? expected
|
85
|
+
# end
|
86
|
+
# end
|
87
|
+
#
|
88
|
+
# # OR
|
89
|
+
#
|
90
|
+
# def rhyme_with(expected)
|
91
|
+
# simple_matcher do |given, matcher|
|
92
|
+
# matcher.description = "rhyme with #{expected.inspect}"
|
93
|
+
# matcher.failure_message = "expected #{given.inspect} to rhyme with #{expected.inspect}"
|
94
|
+
# matcher.negative_failure_message = "expected #{given.inspect} not to rhyme with #{expected.inspect}"
|
95
|
+
# actual.rhymes_with? expected
|
96
|
+
# end
|
97
|
+
# end
|
98
|
+
#
|
99
|
+
# describe "pecan" do
|
100
|
+
# it "should rhyme with 'be gone'" do
|
101
|
+
# nut = "pecan"
|
102
|
+
# nut.extend Rhymer
|
103
|
+
# nut.should rhyme_with("be gone")
|
104
|
+
# end
|
105
|
+
# end
|
106
|
+
#
|
107
|
+
# The resulting messages would be:
|
108
|
+
# description: rhyme with "be gone"
|
109
|
+
# failure_message: expected "pecan" to rhyme with "be gone"
|
110
|
+
# negative failure_message: expected "pecan" not to rhyme with "be gone"
|
111
|
+
#
|
112
|
+
# == Wrapped Expectations
|
113
|
+
#
|
114
|
+
# Because errors will bubble up, it is possible to wrap other expectations
|
115
|
+
# in a SimpleMatcher.
|
116
|
+
#
|
117
|
+
# def be_even
|
118
|
+
# simple_matcher("an even number") { |given| (given % 2).should == 0 }
|
119
|
+
# end
|
120
|
+
#
|
121
|
+
# BE VERY CAREFUL when you do this. Only use wrapped expectations for
|
122
|
+
# matchers that will always be used in only the positive
|
123
|
+
# (<tt>should</tt>) or negative (<tt>should_not</tt>), but not both.
|
124
|
+
# The reason is that is you wrap a <tt>should</tt> and call the wrapper
|
125
|
+
# with <tt>should_not</tt>, the correct result (the <tt>should</tt>
|
126
|
+
# failing), will fail when you want it to pass.
|
127
|
+
#
|
128
|
+
def simple_matcher(description=nil, &match_block)
|
129
|
+
SimpleMatcher.new(description, &match_block)
|
27
130
|
end
|
28
131
|
end
|
29
132
|
end
|