opal-rspec-cj 0.4.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.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/.gitmodules +15 -0
- data/.travis.yml +13 -0
- data/.yardopts +5 -0
- data/CHANGELOG.md +25 -0
- data/Gemfile +8 -0
- data/README.md +147 -0
- data/Rakefile +26 -0
- data/config.ru +10 -0
- data/example/Gemfile +4 -0
- data/example/README.md +13 -0
- data/example/Rakefile +8 -0
- data/example/opal/user.rb +11 -0
- data/example/spec/user_spec.rb +15 -0
- data/lib/opal-rspec.rb +2 -0
- data/lib/opal/rspec.rb +20 -0
- data/lib/opal/rspec/rake_task.rb +63 -0
- data/lib/opal/rspec/version.rb +5 -0
- data/opal-rspec.gemspec +21 -0
- data/opal/opal-rspec.rb +1 -0
- data/opal/opal/rspec.rb +25 -0
- data/opal/opal/rspec/async.rb +289 -0
- data/opal/opal/rspec/browser_formatter.rb +188 -0
- data/opal/opal/rspec/fixes.rb +116 -0
- data/opal/opal/rspec/requires.rb +45 -0
- data/opal/opal/rspec/runner.rb +69 -0
- data/opal/opal/rspec/sprockets_runner.rb.erb +11 -0
- data/opal/opal/rspec/text_formatter.rb +74 -0
- data/spec/async_spec.rb +38 -0
- data/spec/example_spec.rb +163 -0
- data/spec/matchers_spec.rb +201 -0
- data/spec/mock_spec.rb +63 -0
- data/spec/named_subject_spec.rb +11 -0
- data/spec/should_syntax_spec.rb +17 -0
- data/vendor/spec_runner.js +50 -0
- data/vendor_lib/rspec-expectations.rb +1 -0
- data/vendor_lib/rspec.rb +3 -0
- data/vendor_lib/rspec/autorun.rb +2 -0
- data/vendor_lib/rspec/core.rb +203 -0
- data/vendor_lib/rspec/core/backport_random.rb +302 -0
- data/vendor_lib/rspec/core/backtrace_formatter.rb +65 -0
- data/vendor_lib/rspec/core/command_line.rb +36 -0
- data/vendor_lib/rspec/core/configuration.rb +1129 -0
- data/vendor_lib/rspec/core/configuration_options.rb +143 -0
- data/vendor_lib/rspec/core/drb_command_line.rb +26 -0
- data/vendor_lib/rspec/core/drb_options.rb +87 -0
- data/vendor_lib/rspec/core/dsl.rb +26 -0
- data/vendor_lib/rspec/core/example.rb +312 -0
- data/vendor_lib/rspec/core/example_group.rb +540 -0
- data/vendor_lib/rspec/core/filter_manager.rb +224 -0
- data/vendor_lib/rspec/core/flat_map.rb +17 -0
- data/vendor_lib/rspec/core/formatters.rb +54 -0
- data/vendor_lib/rspec/core/formatters/base_formatter.rb +291 -0
- data/vendor_lib/rspec/core/formatters/base_text_formatter.rb +307 -0
- data/vendor_lib/rspec/core/formatters/deprecation_formatter.rb +193 -0
- data/vendor_lib/rspec/core/formatters/documentation_formatter.rb +67 -0
- data/vendor_lib/rspec/core/formatters/helpers.rb +82 -0
- data/vendor_lib/rspec/core/formatters/html_formatter.rb +155 -0
- data/vendor_lib/rspec/core/formatters/html_printer.rb +408 -0
- data/vendor_lib/rspec/core/formatters/json_formatter.rb +99 -0
- data/vendor_lib/rspec/core/formatters/progress_formatter.rb +32 -0
- data/vendor_lib/rspec/core/formatters/snippet_extractor.rb +101 -0
- data/vendor_lib/rspec/core/hooks.rb +535 -0
- data/vendor_lib/rspec/core/memoized_helpers.rb +431 -0
- data/vendor_lib/rspec/core/metadata.rb +313 -0
- data/vendor_lib/rspec/core/mocking/with_absolutely_nothing.rb +11 -0
- data/vendor_lib/rspec/core/mocking/with_flexmock.rb +27 -0
- data/vendor_lib/rspec/core/mocking/with_mocha.rb +52 -0
- data/vendor_lib/rspec/core/mocking/with_rr.rb +27 -0
- data/vendor_lib/rspec/core/mocking/with_rspec.rb +27 -0
- data/vendor_lib/rspec/core/option_parser.rb +234 -0
- data/vendor_lib/rspec/core/ordering.rb +154 -0
- data/vendor_lib/rspec/core/pending.rb +110 -0
- data/vendor_lib/rspec/core/project_initializer.rb +88 -0
- data/vendor_lib/rspec/core/rake_task.rb +128 -0
- data/vendor_lib/rspec/core/reporter.rb +132 -0
- data/vendor_lib/rspec/core/ruby_project.rb +44 -0
- data/vendor_lib/rspec/core/runner.rb +97 -0
- data/vendor_lib/rspec/core/shared_context.rb +53 -0
- data/vendor_lib/rspec/core/shared_example_group.rb +146 -0
- data/vendor_lib/rspec/core/shared_example_group/collection.rb +27 -0
- data/vendor_lib/rspec/core/version.rb +7 -0
- data/vendor_lib/rspec/core/warnings.rb +22 -0
- data/vendor_lib/rspec/core/world.rb +131 -0
- data/vendor_lib/rspec/expectations.rb +75 -0
- data/vendor_lib/rspec/expectations/differ.rb +154 -0
- data/vendor_lib/rspec/expectations/errors.rb +9 -0
- data/vendor_lib/rspec/expectations/expectation_target.rb +87 -0
- data/vendor_lib/rspec/expectations/extensions.rb +1 -0
- data/vendor_lib/rspec/expectations/extensions/object.rb +29 -0
- data/vendor_lib/rspec/expectations/fail_with.rb +79 -0
- data/vendor_lib/rspec/expectations/handler.rb +68 -0
- data/vendor_lib/rspec/expectations/syntax.rb +182 -0
- data/vendor_lib/rspec/expectations/version.rb +8 -0
- data/vendor_lib/rspec/matchers.rb +633 -0
- data/vendor_lib/rspec/matchers/built_in.rb +39 -0
- data/vendor_lib/rspec/matchers/built_in/base_matcher.rb +68 -0
- data/vendor_lib/rspec/matchers/built_in/be.rb +213 -0
- data/vendor_lib/rspec/matchers/built_in/be_instance_of.rb +15 -0
- data/vendor_lib/rspec/matchers/built_in/be_kind_of.rb +11 -0
- data/vendor_lib/rspec/matchers/built_in/be_within.rb +55 -0
- data/vendor_lib/rspec/matchers/built_in/change.rb +141 -0
- data/vendor_lib/rspec/matchers/built_in/cover.rb +21 -0
- data/vendor_lib/rspec/matchers/built_in/eq.rb +22 -0
- data/vendor_lib/rspec/matchers/built_in/eql.rb +23 -0
- data/vendor_lib/rspec/matchers/built_in/equal.rb +48 -0
- data/vendor_lib/rspec/matchers/built_in/exist.rb +26 -0
- data/vendor_lib/rspec/matchers/built_in/has.rb +48 -0
- data/vendor_lib/rspec/matchers/built_in/include.rb +61 -0
- data/vendor_lib/rspec/matchers/built_in/match.rb +17 -0
- data/vendor_lib/rspec/matchers/built_in/match_array.rb +51 -0
- data/vendor_lib/rspec/matchers/built_in/raise_error.rb +154 -0
- data/vendor_lib/rspec/matchers/built_in/respond_to.rb +74 -0
- data/vendor_lib/rspec/matchers/built_in/satisfy.rb +30 -0
- data/vendor_lib/rspec/matchers/built_in/start_and_end_with.rb +48 -0
- data/vendor_lib/rspec/matchers/built_in/throw_symbol.rb +94 -0
- data/vendor_lib/rspec/matchers/built_in/yield.rb +297 -0
- data/vendor_lib/rspec/matchers/compatibility.rb +14 -0
- data/vendor_lib/rspec/matchers/configuration.rb +113 -0
- data/vendor_lib/rspec/matchers/dsl.rb +23 -0
- data/vendor_lib/rspec/matchers/generated_descriptions.rb +35 -0
- data/vendor_lib/rspec/matchers/matcher.rb +301 -0
- data/vendor_lib/rspec/matchers/method_missing.rb +12 -0
- data/vendor_lib/rspec/matchers/operator_matcher.rb +99 -0
- data/vendor_lib/rspec/matchers/pretty.rb +70 -0
- data/vendor_lib/rspec/matchers/test_unit_integration.rb +11 -0
- data/vendor_lib/rspec/mocks.rb +100 -0
- data/vendor_lib/rspec/mocks/any_instance/chain.rb +92 -0
- data/vendor_lib/rspec/mocks/any_instance/expectation_chain.rb +47 -0
- data/vendor_lib/rspec/mocks/any_instance/message_chains.rb +75 -0
- data/vendor_lib/rspec/mocks/any_instance/recorder.rb +200 -0
- data/vendor_lib/rspec/mocks/any_instance/stub_chain.rb +45 -0
- data/vendor_lib/rspec/mocks/any_instance/stub_chain_chain.rb +23 -0
- data/vendor_lib/rspec/mocks/argument_list_matcher.rb +104 -0
- data/vendor_lib/rspec/mocks/argument_matchers.rb +264 -0
- data/vendor_lib/rspec/mocks/arity_calculator.rb +66 -0
- data/vendor_lib/rspec/mocks/configuration.rb +111 -0
- data/vendor_lib/rspec/mocks/error_generator.rb +203 -0
- data/vendor_lib/rspec/mocks/errors.rb +12 -0
- data/vendor_lib/rspec/mocks/example_methods.rb +201 -0
- data/vendor_lib/rspec/mocks/extensions/marshal.rb +17 -0
- data/vendor_lib/rspec/mocks/framework.rb +36 -0
- data/vendor_lib/rspec/mocks/instance_method_stasher.rb +112 -0
- data/vendor_lib/rspec/mocks/matchers/have_received.rb +99 -0
- data/vendor_lib/rspec/mocks/matchers/receive.rb +112 -0
- data/vendor_lib/rspec/mocks/matchers/receive_messages.rb +72 -0
- data/vendor_lib/rspec/mocks/message_expectation.rb +643 -0
- data/vendor_lib/rspec/mocks/method_double.rb +209 -0
- data/vendor_lib/rspec/mocks/method_reference.rb +95 -0
- data/vendor_lib/rspec/mocks/mock.rb +7 -0
- data/vendor_lib/rspec/mocks/mutate_const.rb +406 -0
- data/vendor_lib/rspec/mocks/object_reference.rb +90 -0
- data/vendor_lib/rspec/mocks/order_group.rb +82 -0
- data/vendor_lib/rspec/mocks/proxy.rb +269 -0
- data/vendor_lib/rspec/mocks/proxy_for_nil.rb +37 -0
- data/vendor_lib/rspec/mocks/space.rb +95 -0
- data/vendor_lib/rspec/mocks/standalone.rb +3 -0
- data/vendor_lib/rspec/mocks/stub_chain.rb +51 -0
- data/vendor_lib/rspec/mocks/syntax.rb +374 -0
- data/vendor_lib/rspec/mocks/targets.rb +90 -0
- data/vendor_lib/rspec/mocks/test_double.rb +109 -0
- data/vendor_lib/rspec/mocks/verifying_double.rb +77 -0
- data/vendor_lib/rspec/mocks/verifying_message_expecation.rb +60 -0
- data/vendor_lib/rspec/mocks/verifying_proxy.rb +151 -0
- data/vendor_lib/rspec/mocks/version.rb +7 -0
- data/vendor_lib/rspec/support.rb +6 -0
- data/vendor_lib/rspec/support/caller_filter.rb +56 -0
- data/vendor_lib/rspec/support/spec.rb +14 -0
- data/vendor_lib/rspec/support/spec/deprecation_helpers.rb +29 -0
- data/vendor_lib/rspec/support/spec/in_sub_process.rb +40 -0
- data/vendor_lib/rspec/support/spec/stderr_splitter.rb +50 -0
- data/vendor_lib/rspec/support/version.rb +7 -0
- data/vendor_lib/rspec/support/warnings.rb +41 -0
- data/vendor_lib/rspec/version.rb +5 -0
- metadata +268 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
module RSpec
|
|
2
|
+
module Matchers
|
|
3
|
+
module BuiltIn
|
|
4
|
+
class RespondTo
|
|
5
|
+
def initialize(*names)
|
|
6
|
+
@names = names
|
|
7
|
+
@expected_arity = nil
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def matches?(actual)
|
|
11
|
+
find_failing_method_names(actual, :reject).empty?
|
|
12
|
+
end
|
|
13
|
+
alias == matches?
|
|
14
|
+
|
|
15
|
+
def does_not_match?(actual)
|
|
16
|
+
find_failing_method_names(actual, :select).empty?
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def failure_message_for_should
|
|
20
|
+
"expected #{@actual.inspect} to respond to #{@failing_method_names.collect {|name| name.inspect }.join(', ')}#{with_arity}"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def failure_message_for_should_not
|
|
24
|
+
failure_message_for_should.sub(/to respond to/, 'not to respond to')
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def description
|
|
28
|
+
"respond to #{pp_names}#{with_arity}"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def with(n)
|
|
32
|
+
@expected_arity = n
|
|
33
|
+
self
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def argument
|
|
37
|
+
self
|
|
38
|
+
end
|
|
39
|
+
alias :arguments :argument
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def find_failing_method_names(actual, filter_method)
|
|
44
|
+
@actual = actual
|
|
45
|
+
@failing_method_names = @names.__send__(filter_method) do |name|
|
|
46
|
+
@actual.respond_to?(name) && matches_arity?(actual, name)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def matches_arity?(actual, name)
|
|
51
|
+
return true unless @expected_arity
|
|
52
|
+
|
|
53
|
+
actual_arity = actual.method(name).arity
|
|
54
|
+
if actual_arity < 0
|
|
55
|
+
# ~ inverts the one's complement and gives us the number of required args
|
|
56
|
+
~actual_arity <= @expected_arity
|
|
57
|
+
else
|
|
58
|
+
actual_arity == @expected_arity
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def with_arity
|
|
63
|
+
@expected_arity.nil?? "" :
|
|
64
|
+
" with #{@expected_arity} argument#{@expected_arity == 1 ? '' : 's'}"
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def pp_names
|
|
68
|
+
# Ruby 1.9 returns the same thing for array.to_s as array.inspect, so just use array.inspect here
|
|
69
|
+
@names.length == 1 ? "##{@names.first}" : @names.inspect
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module RSpec
|
|
2
|
+
module Matchers
|
|
3
|
+
module BuiltIn
|
|
4
|
+
class Satisfy
|
|
5
|
+
def initialize(&block)
|
|
6
|
+
@block = block
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def matches?(actual, &block)
|
|
10
|
+
@block = block if block
|
|
11
|
+
@actual = actual
|
|
12
|
+
@block.call(actual)
|
|
13
|
+
end
|
|
14
|
+
alias == matches?
|
|
15
|
+
|
|
16
|
+
def failure_message_for_should
|
|
17
|
+
"expected #{@actual} to satisfy block"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def failure_message_for_should_not
|
|
21
|
+
"expected #{@actual} not to satisfy block"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def description
|
|
25
|
+
"satisfy block"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
module RSpec
|
|
2
|
+
module Matchers
|
|
3
|
+
module BuiltIn
|
|
4
|
+
class StartAndEndWith < BaseMatcher
|
|
5
|
+
def initialize(*expected)
|
|
6
|
+
@expected = expected.length == 1 ? expected.first : expected
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def matches?(actual)
|
|
10
|
+
@actual = actual.respond_to?(:[]) ? actual : (raise ArgumentError.new("#{actual.inspect} does not respond to :[]"))
|
|
11
|
+
begin
|
|
12
|
+
@expected.respond_to?(:length) ? subset_matches?(@expected, @actual) : element_matches?(@expected, @actual)
|
|
13
|
+
rescue ArgumentError
|
|
14
|
+
raise ArgumentError.new("#{actual.inspect} does not have ordered elements")
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def failure_message_for_should
|
|
19
|
+
"expected #{@actual.inspect} to #{self.class.name.split('::').last.sub(/With/,'').downcase} with #{@expected.inspect}"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def failure_message_for_should_not
|
|
23
|
+
"expected #{@actual.inspect} not to #{self.class.name.split('::').last.sub(/With/,'').downcase} with #{@expected.inspect}"
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
class StartWith < StartAndEndWith
|
|
28
|
+
def subset_matches?(expected, actual)
|
|
29
|
+
actual[0, expected.length] == expected
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def element_matches?(expected, actual)
|
|
33
|
+
@actual[0] == @expected
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
class EndWith < StartAndEndWith
|
|
38
|
+
def subset_matches?(expected, actual)
|
|
39
|
+
actual[-expected.length, expected.length] == expected
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def element_matches?(expected, actual)
|
|
43
|
+
actual[-1] == expected
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
module RSpec
|
|
2
|
+
module Matchers
|
|
3
|
+
module BuiltIn
|
|
4
|
+
class ThrowSymbol
|
|
5
|
+
def initialize(expected_symbol = nil, expected_arg=nil)
|
|
6
|
+
@expected_symbol = expected_symbol
|
|
7
|
+
@expected_arg = expected_arg
|
|
8
|
+
@caught_symbol = @caught_arg = nil
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def matches?(given_proc)
|
|
12
|
+
begin
|
|
13
|
+
if @expected_symbol.nil?
|
|
14
|
+
given_proc.call
|
|
15
|
+
else
|
|
16
|
+
@caught_arg = catch :proc_did_not_throw_anything do
|
|
17
|
+
catch @expected_symbol do
|
|
18
|
+
given_proc.call
|
|
19
|
+
throw :proc_did_not_throw_anything, :nothing_thrown
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
if @caught_arg == :nothing_thrown
|
|
24
|
+
@caught_arg = nil
|
|
25
|
+
else
|
|
26
|
+
@caught_symbol = @expected_symbol
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Ruby 1.8 uses NameError with `symbol'
|
|
31
|
+
# Ruby 1.9 uses ArgumentError with :symbol
|
|
32
|
+
rescue NameError, ArgumentError => e
|
|
33
|
+
unless e.message =~ /uncaught throw (`|\:)([a-zA-Z0-9_]*)(')?/
|
|
34
|
+
other_exception = e
|
|
35
|
+
raise
|
|
36
|
+
end
|
|
37
|
+
@caught_symbol = $2.to_sym
|
|
38
|
+
rescue => other_exception
|
|
39
|
+
raise
|
|
40
|
+
ensure
|
|
41
|
+
unless other_exception
|
|
42
|
+
if @expected_symbol.nil?
|
|
43
|
+
return !@caught_symbol.nil?
|
|
44
|
+
else
|
|
45
|
+
if @expected_arg.nil?
|
|
46
|
+
return @caught_symbol == @expected_symbol
|
|
47
|
+
else
|
|
48
|
+
return (@caught_symbol == @expected_symbol) & (@caught_arg == @expected_arg)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
alias == matches?
|
|
55
|
+
|
|
56
|
+
def failure_message_for_should
|
|
57
|
+
"expected #{expected} to be thrown, got #{caught}"
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def failure_message_for_should_not
|
|
61
|
+
"expected #{expected('no Symbol')}#{' not' if @expected_symbol} to be thrown, got #{caught}"
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def description
|
|
65
|
+
"throw #{expected}"
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
private
|
|
69
|
+
|
|
70
|
+
def expected(symbol_desc = 'a Symbol')
|
|
71
|
+
throw_description(@expected_symbol || symbol_desc, @expected_arg)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def caught
|
|
75
|
+
throw_description(@caught_symbol || 'nothing', @caught_arg)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def throw_description(symbol, arg)
|
|
79
|
+
symbol_description = symbol.is_a?(String) ? symbol : symbol.inspect
|
|
80
|
+
|
|
81
|
+
arg_description = if arg
|
|
82
|
+
" with #{arg.inspect}"
|
|
83
|
+
elsif @expected_arg && @caught_symbol == @expected_symbol
|
|
84
|
+
" with no argument"
|
|
85
|
+
else
|
|
86
|
+
""
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
symbol_description + arg_description
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
module RSpec
|
|
2
|
+
module Matchers
|
|
3
|
+
module BuiltIn
|
|
4
|
+
class YieldProbe
|
|
5
|
+
def self.probe(block)
|
|
6
|
+
probe = new
|
|
7
|
+
assert_valid_expect_block!(block)
|
|
8
|
+
block.call(probe)
|
|
9
|
+
probe.assert_used!
|
|
10
|
+
probe
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
attr_accessor :num_yields, :yielded_args
|
|
14
|
+
|
|
15
|
+
def initialize
|
|
16
|
+
@used = false
|
|
17
|
+
self.num_yields, self.yielded_args = 0, []
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def to_proc
|
|
21
|
+
@used = true
|
|
22
|
+
|
|
23
|
+
probe = self
|
|
24
|
+
Proc.new do |*args|
|
|
25
|
+
probe.num_yields += 1
|
|
26
|
+
probe.yielded_args << args
|
|
27
|
+
nil # to indicate the block does not return a meaningful value
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def single_yield_args
|
|
32
|
+
yielded_args.first
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def yielded_once?(matcher_name)
|
|
36
|
+
case num_yields
|
|
37
|
+
when 1 then true
|
|
38
|
+
when 0 then false
|
|
39
|
+
else
|
|
40
|
+
raise "The #{matcher_name} matcher is not designed to be used with a " +
|
|
41
|
+
"method that yields multiple times. Use the yield_successive_args " +
|
|
42
|
+
"matcher for that case."
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def successive_yield_args
|
|
47
|
+
yielded_args.map do |arg_array|
|
|
48
|
+
arg_array.size == 1 ? arg_array.first : arg_array
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def assert_used!
|
|
53
|
+
return if @used
|
|
54
|
+
raise "You must pass the argument yielded to your expect block on " +
|
|
55
|
+
"to the method-under-test as a block. It acts as a probe that " +
|
|
56
|
+
"allows the matcher to detect whether or not the method-under-test " +
|
|
57
|
+
"yields, and, if so, how many times, and what the yielded arguments " +
|
|
58
|
+
"are."
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def self.assert_valid_expect_block!(block)
|
|
62
|
+
return if block.arity == 1
|
|
63
|
+
raise "Your expect block must accept an argument to be used with this " +
|
|
64
|
+
"matcher. Pass the argument as a block on to the method you are testing."
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
class YieldControl < BaseMatcher
|
|
69
|
+
def initialize
|
|
70
|
+
@expectation_type = nil
|
|
71
|
+
@expected_yields_count = nil
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def matches?(block)
|
|
75
|
+
probe = YieldProbe.probe(block)
|
|
76
|
+
|
|
77
|
+
if @expectation_type
|
|
78
|
+
probe.num_yields.send(@expectation_type, @expected_yields_count)
|
|
79
|
+
else
|
|
80
|
+
probe.yielded_once?(:yield_control)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def once
|
|
85
|
+
exactly(1)
|
|
86
|
+
self
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def twice
|
|
90
|
+
exactly(2)
|
|
91
|
+
self
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def exactly(number)
|
|
95
|
+
set_expected_yields_count(:==, number)
|
|
96
|
+
self
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def at_most(number)
|
|
100
|
+
set_expected_yields_count(:<=, number)
|
|
101
|
+
self
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def at_least(number)
|
|
105
|
+
set_expected_yields_count(:>=, number)
|
|
106
|
+
self
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def times
|
|
110
|
+
self
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def failure_message_for_should
|
|
114
|
+
'expected given block to yield control'.tap do |failure_message|
|
|
115
|
+
failure_message << relativity_failure_message
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def failure_message_for_should_not
|
|
120
|
+
'expected given block not to yield control'.tap do |failure_message|
|
|
121
|
+
failure_message << relativity_failure_message
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
private
|
|
126
|
+
|
|
127
|
+
def set_expected_yields_count(relativity, n)
|
|
128
|
+
@expectation_type = relativity
|
|
129
|
+
@expected_yields_count = case n
|
|
130
|
+
when Numeric then n
|
|
131
|
+
when :once then 1
|
|
132
|
+
when :twice then 2
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def relativity_failure_message
|
|
137
|
+
return '' unless @expected_yields_count
|
|
138
|
+
" #{human_readable_expecation_type}#{human_readable_count}"
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def human_readable_expecation_type
|
|
142
|
+
case @expectation_type
|
|
143
|
+
when :<= then 'at most '
|
|
144
|
+
when :>= then 'at least '
|
|
145
|
+
else ''
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def human_readable_count
|
|
150
|
+
case @expected_yields_count
|
|
151
|
+
when 1 then "once"
|
|
152
|
+
when 2 then "twice"
|
|
153
|
+
else "#{@expected_yields_count} times"
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
class YieldWithNoArgs < BaseMatcher
|
|
159
|
+
|
|
160
|
+
def matches?(block)
|
|
161
|
+
@probe = YieldProbe.probe(block)
|
|
162
|
+
@probe.yielded_once?(:yield_with_no_args) && @probe.single_yield_args.empty?
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def failure_message_for_should
|
|
166
|
+
"expected given block to yield with no arguments, but #{failure_reason}"
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def failure_message_for_should_not
|
|
170
|
+
"expected given block not to yield with no arguments, but did"
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
private
|
|
174
|
+
|
|
175
|
+
def failure_reason
|
|
176
|
+
if @probe.num_yields.zero?
|
|
177
|
+
"did not yield"
|
|
178
|
+
else
|
|
179
|
+
"yielded with arguments: #{@probe.single_yield_args.inspect}"
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
class YieldWithArgs
|
|
185
|
+
def initialize(*args)
|
|
186
|
+
@expected = args
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def matches?(block)
|
|
190
|
+
@probe = YieldProbe.probe(block)
|
|
191
|
+
@actual = @probe.single_yield_args
|
|
192
|
+
@probe.yielded_once?(:yield_with_args) && args_match?
|
|
193
|
+
end
|
|
194
|
+
alias == matches?
|
|
195
|
+
|
|
196
|
+
def failure_message_for_should
|
|
197
|
+
"expected given block to yield with arguments, but #{positive_failure_reason}"
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def failure_message_for_should_not
|
|
201
|
+
"expected given block not to yield with arguments, but #{negative_failure_reason}"
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def description
|
|
205
|
+
desc = "yield with args"
|
|
206
|
+
desc << "(" + @expected.map { |e| e.inspect }.join(", ") + ")" unless @expected.empty?
|
|
207
|
+
desc
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
private
|
|
211
|
+
|
|
212
|
+
def positive_failure_reason
|
|
213
|
+
if @probe.num_yields.zero?
|
|
214
|
+
"did not yield"
|
|
215
|
+
else
|
|
216
|
+
@positive_args_failure
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def negative_failure_reason
|
|
221
|
+
if all_args_match?
|
|
222
|
+
"yielded with expected arguments" +
|
|
223
|
+
"\nexpected not: #{@expected.inspect}" +
|
|
224
|
+
"\n got: #{@actual.inspect} (compared using === and ==)"
|
|
225
|
+
else
|
|
226
|
+
"did"
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
def args_match?
|
|
231
|
+
if @expected.empty? # expect {...}.to yield_with_args
|
|
232
|
+
@positive_args_failure = "yielded with no arguments" if @actual.empty?
|
|
233
|
+
return !@actual.empty?
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
unless match = all_args_match?
|
|
237
|
+
@positive_args_failure = "yielded with unexpected arguments" +
|
|
238
|
+
"\nexpected: #{@expected.inspect}" +
|
|
239
|
+
"\n got: #{@actual.inspect} (compared using === and ==)"
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
match
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
def all_args_match?
|
|
246
|
+
return false if @expected.size != @actual.size
|
|
247
|
+
|
|
248
|
+
@expected.zip(@actual).all? do |expected, actual|
|
|
249
|
+
expected === actual || actual == expected
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
class YieldSuccessiveArgs
|
|
255
|
+
def initialize(*args)
|
|
256
|
+
@expected = args
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
def matches?(block)
|
|
260
|
+
@probe = YieldProbe.probe(block)
|
|
261
|
+
@actual = @probe.successive_yield_args
|
|
262
|
+
args_match?
|
|
263
|
+
end
|
|
264
|
+
alias == matches?
|
|
265
|
+
|
|
266
|
+
def failure_message_for_should
|
|
267
|
+
"expected given block to yield successively with arguments, but yielded with unexpected arguments" +
|
|
268
|
+
"\nexpected: #{@expected.inspect}" +
|
|
269
|
+
"\n got: #{@actual.inspect} (compared using === and ==)"
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
def failure_message_for_should_not
|
|
273
|
+
"expected given block not to yield successively with arguments, but yielded with expected arguments" +
|
|
274
|
+
"\nexpected not: #{@expected.inspect}" +
|
|
275
|
+
"\n got: #{@actual.inspect} (compared using === and ==)"
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
def description
|
|
279
|
+
desc = "yield successive args"
|
|
280
|
+
desc << "(" + @expected.map { |e| e.inspect }.join(", ") + ")"
|
|
281
|
+
desc
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
private
|
|
285
|
+
|
|
286
|
+
def args_match?
|
|
287
|
+
return false if @expected.size != @actual.size
|
|
288
|
+
|
|
289
|
+
@expected.zip(@actual).all? do |expected, actual|
|
|
290
|
+
expected === actual || actual == expected
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
|