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,66 @@
|
|
|
1
|
+
module RSpec
|
|
2
|
+
module Mocks
|
|
3
|
+
|
|
4
|
+
# Figures out the valid arity range for a method. Surprisingly non-trivial.
|
|
5
|
+
class ArityCalculator
|
|
6
|
+
|
|
7
|
+
def initialize(method)
|
|
8
|
+
@method = method
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# @api private
|
|
12
|
+
def within_range?(actual)
|
|
13
|
+
min_arity <= actual && actual <= max_arity
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# @api private
|
|
17
|
+
def range_description
|
|
18
|
+
return min_arity.to_s if min_arity == max_arity
|
|
19
|
+
return "#{min_arity} or more" if max_arity == INFINITY
|
|
20
|
+
"#{min_arity} to #{max_arity}"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def method
|
|
26
|
+
@method
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# @api private
|
|
30
|
+
def self.supports_optional_and_splat_args?
|
|
31
|
+
Method.method_defined?(:parameters)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def min_arity
|
|
35
|
+
return method.arity if method.arity >= 0
|
|
36
|
+
# `~` inverts the one's complement and gives us the number of
|
|
37
|
+
# required arguments.
|
|
38
|
+
~method.arity
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
if supports_optional_and_splat_args?
|
|
42
|
+
def max_arity
|
|
43
|
+
params = method.parameters
|
|
44
|
+
if params.any? {|(type, _)| type == :rest }
|
|
45
|
+
# Method takes a splat argument
|
|
46
|
+
return INFINITY
|
|
47
|
+
else
|
|
48
|
+
params.count {|(type, _)| type != :block }
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
else
|
|
52
|
+
def max_arity
|
|
53
|
+
# On 1.8, Method#parameters does not exist. There is no way to
|
|
54
|
+
# distinguish between default and splat args, so there is no way to
|
|
55
|
+
# have it work correctly for both default and splat args, as far as I
|
|
56
|
+
# can tell. The best we can do is consider it INFINITY (to be
|
|
57
|
+
# tolerant of splat args).
|
|
58
|
+
method.arity < 0 ? INFINITY : method.arity
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
INFINITY = 1/0.0
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
module RSpec
|
|
2
|
+
module Mocks
|
|
3
|
+
# Provides configuration options for rspec-mocks.
|
|
4
|
+
class Configuration
|
|
5
|
+
|
|
6
|
+
def initialize
|
|
7
|
+
@yield_receiver_to_any_instance_implementation_blocks = true
|
|
8
|
+
@verify_doubled_constant_names = false
|
|
9
|
+
@transfer_nested_constants = false
|
|
10
|
+
@verify_partial_doubles = false
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def yield_receiver_to_any_instance_implementation_blocks?
|
|
14
|
+
@yield_receiver_to_any_instance_implementation_blocks
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def yield_receiver_to_any_instance_implementation_blocks=(arg)
|
|
18
|
+
@yield_receiver_to_any_instance_implementation_blocks = arg
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Adds `stub` and `should_receive` to the given
|
|
22
|
+
# modules or classes. This is usually only necessary
|
|
23
|
+
# if you application uses some proxy classes that
|
|
24
|
+
# "strip themselves down" to a bare minimum set of
|
|
25
|
+
# methods and remove `stub` and `should_receive` in
|
|
26
|
+
# the process.
|
|
27
|
+
#
|
|
28
|
+
# @example
|
|
29
|
+
#
|
|
30
|
+
# RSpec.configure do |rspec|
|
|
31
|
+
# rspec.mock_with :rspec do |mocks|
|
|
32
|
+
# mocks.add_stub_and_should_receive_to Delegator
|
|
33
|
+
# end
|
|
34
|
+
# end
|
|
35
|
+
#
|
|
36
|
+
def add_stub_and_should_receive_to(*modules)
|
|
37
|
+
modules.each do |mod|
|
|
38
|
+
Syntax.enable_should(mod)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def syntax=(values)
|
|
43
|
+
if Array(values).include?(:expect)
|
|
44
|
+
Syntax.enable_expect
|
|
45
|
+
else
|
|
46
|
+
Syntax.disable_expect
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
if Array(values).include?(:should)
|
|
50
|
+
Syntax.enable_should
|
|
51
|
+
else
|
|
52
|
+
Syntax.disable_should
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def syntax
|
|
57
|
+
syntaxes = []
|
|
58
|
+
syntaxes << :should if Syntax.should_enabled?
|
|
59
|
+
syntaxes << :expect if Syntax.expect_enabled?
|
|
60
|
+
syntaxes
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def verify_doubled_constant_names?
|
|
64
|
+
!!@verify_doubled_constant_names
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# When this is set to true, an error will be raised when
|
|
68
|
+
# `instance_double` or `class_double` is given the name of an undefined
|
|
69
|
+
# constant. You probably only want to set this when running your entire
|
|
70
|
+
# test suite, with all production code loaded. Setting this for an
|
|
71
|
+
# isolated unit test will prevent you from being able to isolate it!
|
|
72
|
+
def verify_doubled_constant_names=(val)
|
|
73
|
+
@verify_doubled_constant_names = val
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def transfer_nested_constants?
|
|
77
|
+
!!@transfer_nested_constants
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Sets the default for the `transfer_nested_constants` option when
|
|
81
|
+
# stubbing constants.
|
|
82
|
+
def transfer_nested_constants=(val)
|
|
83
|
+
@transfer_nested_constants = val
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# When set to true, partial mocks will be verified the same as object
|
|
87
|
+
# doubles. Any stubs will have their arity checked against the original
|
|
88
|
+
# method, and methods that do not exist cannot be stubbed.
|
|
89
|
+
def verify_partial_doubles=(val)
|
|
90
|
+
@verify_partial_doubles = !!val
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def verify_partial_doubles?
|
|
94
|
+
@verify_partial_doubles
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# @api private
|
|
98
|
+
# Resets the configured syntax to the default.
|
|
99
|
+
def reset_syntaxes_to_default
|
|
100
|
+
self.syntax = [:should, :expect]
|
|
101
|
+
RSpec::Mocks::Syntax.warn_about_should!
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def self.configuration
|
|
106
|
+
@configuration ||= Configuration.new
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
configuration.reset_syntaxes_to_default
|
|
110
|
+
end
|
|
111
|
+
end
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
module RSpec
|
|
2
|
+
module Mocks
|
|
3
|
+
# @private
|
|
4
|
+
class ErrorGenerator
|
|
5
|
+
attr_writer :opts
|
|
6
|
+
|
|
7
|
+
def initialize(target, name)
|
|
8
|
+
@target = target
|
|
9
|
+
@name = name
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# @private
|
|
13
|
+
def opts
|
|
14
|
+
@opts ||= {}
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# @private
|
|
18
|
+
def raise_unexpected_message_error(message, *args)
|
|
19
|
+
__raise "#{intro} received unexpected message :#{message}#{arg_message(*args)}"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# @private
|
|
23
|
+
def raise_unexpected_message_args_error(expectation, *args)
|
|
24
|
+
expected_args = format_args(*expectation.expected_args)
|
|
25
|
+
actual_args = format_received_args(*args)
|
|
26
|
+
__raise "#{intro} received #{expectation.message.inspect} with unexpected arguments\n expected: #{expected_args}\n got: #{actual_args}"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# @private
|
|
30
|
+
def raise_missing_default_stub_error(expectation, *args)
|
|
31
|
+
expected_args = format_args(*expectation.expected_args)
|
|
32
|
+
actual_args = format_received_args(*args)
|
|
33
|
+
__raise "#{intro} received #{expectation.message.inspect} with unexpected arguments\n expected: #{expected_args}\n got: #{actual_args}\n Please stub a default value first if message might be received with other args as well. \n"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# @private
|
|
37
|
+
def raise_similar_message_args_error(expectation, *args_for_multiple_calls)
|
|
38
|
+
expected_args = format_args(*expectation.expected_args)
|
|
39
|
+
actual_args = args_for_multiple_calls.collect {|a| format_received_args(*a)}.join(", ")
|
|
40
|
+
__raise "#{intro} received #{expectation.message.inspect} with unexpected arguments\n expected: #{expected_args}\n got: #{actual_args}"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# @private
|
|
44
|
+
def raise_expectation_error(message, expected_received_count, argument_list_matcher, actual_received_count, expectation_count_type, *args)
|
|
45
|
+
expected_part = expected_part_of_expectation_error(expected_received_count, expectation_count_type, argument_list_matcher)
|
|
46
|
+
received_part = received_part_of_expectation_error(actual_received_count, *args)
|
|
47
|
+
__raise "(#{intro}).#{message}#{format_args(*args)}\n #{expected_part}\n #{received_part}"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# @private
|
|
51
|
+
def raise_unimplemented_error(doubled_module, method_name)
|
|
52
|
+
__raise "%s does not implement:\n %s" % [
|
|
53
|
+
doubled_module.description,
|
|
54
|
+
method_name
|
|
55
|
+
]
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# @private
|
|
59
|
+
def raise_arity_error(calculator, actual)
|
|
60
|
+
__raise "Wrong number of arguments. Expected %s, got %s." % [
|
|
61
|
+
calculator.range_description,
|
|
62
|
+
actual
|
|
63
|
+
]
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# @private
|
|
67
|
+
def received_part_of_expectation_error(actual_received_count, *args)
|
|
68
|
+
"received: #{count_message(actual_received_count)}" +
|
|
69
|
+
method_call_args_description(args)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# @private
|
|
73
|
+
def expected_part_of_expectation_error(expected_received_count, expectation_count_type, argument_list_matcher)
|
|
74
|
+
"expected: #{count_message(expected_received_count, expectation_count_type)}" +
|
|
75
|
+
method_call_args_description(argument_list_matcher.expected_args)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# @private
|
|
79
|
+
def method_call_args_description(args)
|
|
80
|
+
case args.first
|
|
81
|
+
when ArgumentMatchers::AnyArgsMatcher
|
|
82
|
+
return " with any arguments"
|
|
83
|
+
when ArgumentMatchers::NoArgsMatcher
|
|
84
|
+
return " with no arguments"
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
if args.length > 0
|
|
88
|
+
" with arguments: #{args.inspect.gsub(/\A\[(.+)\]\z/, '(\1)')}"
|
|
89
|
+
else
|
|
90
|
+
""
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# @private
|
|
95
|
+
def describe_expectation(message, expected_received_count, actual_received_count, *args)
|
|
96
|
+
"have received #{message}#{format_args(*args)} #{count_message(expected_received_count)}"
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# @private
|
|
100
|
+
def raise_out_of_order_error(message)
|
|
101
|
+
__raise "#{intro} received :#{message} out of order"
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# @private
|
|
105
|
+
def raise_block_failed_error(message, detail)
|
|
106
|
+
__raise "#{intro} received :#{message} but passed block failed with: #{detail}"
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# @private
|
|
110
|
+
def raise_missing_block_error(args_to_yield)
|
|
111
|
+
__raise "#{intro} asked to yield |#{arg_list(*args_to_yield)}| but no block was passed"
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# @private
|
|
115
|
+
def raise_wrong_arity_error(args_to_yield, arity)
|
|
116
|
+
__raise "#{intro} yielded |#{arg_list(*args_to_yield)}| to block with arity of #{arity}"
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# @private
|
|
120
|
+
def raise_only_valid_on_a_partial_mock(method)
|
|
121
|
+
__raise "#{intro} is a pure mock object. `#{method}` is only " +
|
|
122
|
+
"available on a partial mock object."
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# @private
|
|
126
|
+
def raise_expectation_on_unstubbed_method(method)
|
|
127
|
+
__raise "#{intro} expected to have received #{method}, but that " +
|
|
128
|
+
"method has not been stubbed."
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# @private
|
|
132
|
+
def raise_expectation_on_mocked_method(method)
|
|
133
|
+
__raise "#{intro} expected to have received #{method}, but that " +
|
|
134
|
+
"method has been mocked instead of stubbed."
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def self.raise_double_negation_error(wrapped_expression)
|
|
138
|
+
raise "Isn't life confusing enough? You've already set a " +
|
|
139
|
+
"negative message expectation and now you are trying to " +
|
|
140
|
+
"negate it again with `never`. What does an expression like " +
|
|
141
|
+
"`#{wrapped_expression}.not_to receive(:msg).never` even mean?"
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
private
|
|
145
|
+
|
|
146
|
+
def intro
|
|
147
|
+
if @name
|
|
148
|
+
"Double #{@name.inspect}"
|
|
149
|
+
elsif TestDouble === @target
|
|
150
|
+
"Double"
|
|
151
|
+
elsif Class === @target
|
|
152
|
+
"<#{@target.inspect} (class)>"
|
|
153
|
+
elsif @target
|
|
154
|
+
@target
|
|
155
|
+
else
|
|
156
|
+
"nil"
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def __raise(message)
|
|
161
|
+
message = opts[:message] unless opts[:message].nil?
|
|
162
|
+
Kernel::raise(RSpec::Mocks::MockExpectationError, message)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def arg_message(*args)
|
|
166
|
+
" with " + format_args(*args)
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def format_args(*args)
|
|
170
|
+
args.empty? ? "(no args)" : "(" + arg_list(*args) + ")"
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def arg_list(*args)
|
|
174
|
+
args.collect {|arg| arg_has_valid_description(arg) ? arg.description : arg.inspect }.join(", ")
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def arg_has_valid_description(arg)
|
|
178
|
+
return false unless arg.respond_to?(:description)
|
|
179
|
+
|
|
180
|
+
!arg.description.nil? && !arg.description.empty?
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def format_received_args(*args)
|
|
184
|
+
args.empty? ? "(no args)" : "(" + received_arg_list(*args) + ")"
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def received_arg_list(*args)
|
|
188
|
+
args.collect(&:inspect).join(", ")
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def count_message(count, expectation_count_type=nil)
|
|
192
|
+
return "at least #{pretty_print(count.abs)}" if count < 0 || expectation_count_type == :at_least
|
|
193
|
+
return "at most #{pretty_print(count)}" if expectation_count_type == :at_most
|
|
194
|
+
return pretty_print(count)
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def pretty_print(count)
|
|
198
|
+
"#{count} time#{count == 1 ? '' : 's'}"
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
end
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
require 'rspec/mocks/object_reference'
|
|
2
|
+
|
|
3
|
+
module RSpec
|
|
4
|
+
module Mocks
|
|
5
|
+
module ExampleMethods
|
|
6
|
+
include RSpec::Mocks::ArgumentMatchers
|
|
7
|
+
|
|
8
|
+
# @overload double()
|
|
9
|
+
# @overload double(name)
|
|
10
|
+
# @overload double(stubs)
|
|
11
|
+
# @overload double(name, stubs)
|
|
12
|
+
# @param name [String/Symbol] (optional) used in
|
|
13
|
+
# clarify intent
|
|
14
|
+
# @param stubs (Hash) (optional) hash of message/return-value pairs
|
|
15
|
+
# @return (Mock)
|
|
16
|
+
#
|
|
17
|
+
# Constructs an instance of [RSpec::Mocks::Mock](RSpec::Mocks::Mock) configured
|
|
18
|
+
# with an optional name, used for reporting in failure messages, and an optional
|
|
19
|
+
# hash of message/return-value pairs.
|
|
20
|
+
#
|
|
21
|
+
# @example
|
|
22
|
+
#
|
|
23
|
+
# book = double("book", :title => "The RSpec Book")
|
|
24
|
+
# book.title #=> "The RSpec Book"
|
|
25
|
+
#
|
|
26
|
+
# card = double("card", :suit => "Spades", :rank => "A")
|
|
27
|
+
# card.suit #=> "Spades"
|
|
28
|
+
# card.rank #=> "A"
|
|
29
|
+
#
|
|
30
|
+
def double(*args)
|
|
31
|
+
declare_double(Mock, *args)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# @overload instance_double(doubled_class)
|
|
35
|
+
# @overload instance_double(doubled_class, stubs)
|
|
36
|
+
# @param doubled_class [String, Class]
|
|
37
|
+
# @param stubs [Hash] (optional) hash of message/return-value pairs
|
|
38
|
+
# @return InstanceVerifyingDouble
|
|
39
|
+
#
|
|
40
|
+
# Constructs a test double against a specific class. If the given class
|
|
41
|
+
# name has been loaded, only instance methods defined on the class are
|
|
42
|
+
# allowed to be stubbed. In all other ways it behaves like a
|
|
43
|
+
# [double](double).
|
|
44
|
+
def instance_double(doubled_class, *args)
|
|
45
|
+
ref = ObjectReference.for(doubled_class)
|
|
46
|
+
declare_verifying_double(InstanceVerifyingDouble, ref, *args)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# @overload class_double(doubled_class)
|
|
50
|
+
# @overload class_double(doubled_class, stubs)
|
|
51
|
+
# @param doubled_class [String, Module]
|
|
52
|
+
# @param stubs [Hash] (optional) hash of message/return-value pairs
|
|
53
|
+
# @return ClassVerifyingDouble
|
|
54
|
+
#
|
|
55
|
+
# Constructs a test double against a specific class. If the given class
|
|
56
|
+
# name has been loaded, only class methods defined on the class are
|
|
57
|
+
# allowed to be stubbed. In all other ways it behaves like a
|
|
58
|
+
# [double](double).
|
|
59
|
+
def class_double(doubled_class, *args)
|
|
60
|
+
ref = ObjectReference.for(doubled_class)
|
|
61
|
+
declare_verifying_double(ClassVerifyingDouble, ref, *args)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# @overload object_double(object_or_name)
|
|
65
|
+
# @overload object_double(object_or_name, stubs)
|
|
66
|
+
# @param object_or_name [String, Object]
|
|
67
|
+
# @param stubs [Hash] (optional) hash of message/return-value pairs
|
|
68
|
+
# @return ObjectVerifyingDouble
|
|
69
|
+
#
|
|
70
|
+
# Constructs a test double against a specific object. Only the methods
|
|
71
|
+
# the object responds to are allowed to be stubbed. If a String argument
|
|
72
|
+
# is provided, it is assumed to reference a constant object which is used
|
|
73
|
+
# for verification. In all other ways it behaves like a [double](double).
|
|
74
|
+
def object_double(object_or_name, *args)
|
|
75
|
+
ref = ObjectReference.for(object_or_name, :allow_direct_object_refs)
|
|
76
|
+
declare_verifying_double(ObjectVerifyingDouble, ref, *args)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Disables warning messages about expectations being set on nil.
|
|
80
|
+
#
|
|
81
|
+
# By default warning messages are issued when expectations are set on
|
|
82
|
+
# nil. This is to prevent false-positives and to catch potential bugs
|
|
83
|
+
# early on.
|
|
84
|
+
def allow_message_expectations_on_nil
|
|
85
|
+
RSpec::Mocks.space.proxy_for(nil).warn_about_expectations = false
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Stubs the named constant with the given value.
|
|
89
|
+
# Like method stubs, the constant will be restored
|
|
90
|
+
# to its original value (or lack of one, if it was
|
|
91
|
+
# undefined) when the example completes.
|
|
92
|
+
#
|
|
93
|
+
# @param constant_name [String] The fully qualified name of the constant. The current
|
|
94
|
+
# constant scoping at the point of call is not considered.
|
|
95
|
+
# @param value [Object] The value to make the constant refer to. When the
|
|
96
|
+
# example completes, the constant will be restored to its prior state.
|
|
97
|
+
# @param options [Hash] Stubbing options.
|
|
98
|
+
# @option options :transfer_nested_constants [Boolean, Array<Symbol>] Determines
|
|
99
|
+
# what nested constants, if any, will be transferred from the original value
|
|
100
|
+
# of the constant to the new value of the constant. This only works if both
|
|
101
|
+
# the original and new values are modules (or classes).
|
|
102
|
+
# @return [Object] the stubbed value of the constant
|
|
103
|
+
#
|
|
104
|
+
# @example
|
|
105
|
+
#
|
|
106
|
+
# stub_const("MyClass", Class.new) # => Replaces (or defines) MyClass with a new class object.
|
|
107
|
+
# stub_const("SomeModel::PER_PAGE", 5) # => Sets SomeModel::PER_PAGE to 5.
|
|
108
|
+
#
|
|
109
|
+
# class CardDeck
|
|
110
|
+
# SUITS = [:Spades, :Diamonds, :Clubs, :Hearts]
|
|
111
|
+
# NUM_CARDS = 52
|
|
112
|
+
# end
|
|
113
|
+
#
|
|
114
|
+
# stub_const("CardDeck", Class.new)
|
|
115
|
+
# CardDeck::SUITS # => uninitialized constant error
|
|
116
|
+
# CardDeck::NUM_CARDS # => uninitialized constant error
|
|
117
|
+
#
|
|
118
|
+
# stub_const("CardDeck", Class.new, :transfer_nested_constants => true)
|
|
119
|
+
# CardDeck::SUITS # => our suits array
|
|
120
|
+
# CardDeck::NUM_CARDS # => 52
|
|
121
|
+
#
|
|
122
|
+
# stub_const("CardDeck", Class.new, :transfer_nested_constants => [:SUITS])
|
|
123
|
+
# CardDeck::SUITS # => our suits array
|
|
124
|
+
# CardDeck::NUM_CARDS # => uninitialized constant error
|
|
125
|
+
def stub_const(constant_name, value, options = {})
|
|
126
|
+
ConstantMutator.stub(constant_name, value, options)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Hides the named constant with the given value. The constant will be
|
|
130
|
+
# undefined for the duration of the test.
|
|
131
|
+
#
|
|
132
|
+
# Like method stubs, the constant will be restored to its original value
|
|
133
|
+
# when the example completes.
|
|
134
|
+
#
|
|
135
|
+
# @param constant_name [String] The fully qualified name of the constant.
|
|
136
|
+
# The current constant scoping at the point of call is not considered.
|
|
137
|
+
#
|
|
138
|
+
# @example
|
|
139
|
+
#
|
|
140
|
+
# hide_const("MyClass") # => MyClass is now an undefined constant
|
|
141
|
+
def hide_const(constant_name)
|
|
142
|
+
ConstantMutator.hide(constant_name)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# Verifies that the given object received the expected message during the
|
|
146
|
+
# course of the test. The method must have previously been stubbed in
|
|
147
|
+
# order for messages to be verified.
|
|
148
|
+
#
|
|
149
|
+
# Stubbing and verifying messages received in this way implements the
|
|
150
|
+
# Test Spy pattern.
|
|
151
|
+
#
|
|
152
|
+
# @param method_name [Symbol] name of the method expected to have been
|
|
153
|
+
# called.
|
|
154
|
+
#
|
|
155
|
+
# @example
|
|
156
|
+
#
|
|
157
|
+
# invitation = double('invitation', accept: true)
|
|
158
|
+
# user.accept_invitation(invitation)
|
|
159
|
+
# expect(invitation).to have_received(:accept)
|
|
160
|
+
#
|
|
161
|
+
# # You can also use most message expectations:
|
|
162
|
+
# expect(invitation).to have_received(:accept).with(mailer).once
|
|
163
|
+
def have_received(method_name, &block)
|
|
164
|
+
Matchers::HaveReceived.new(method_name, &block)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def self.included(klass)
|
|
168
|
+
klass.class_exec do
|
|
169
|
+
# This gets mixed in so that if `RSpec::Matchers` is included in
|
|
170
|
+
# `klass` later, it's definition of `expect` will take precedence.
|
|
171
|
+
include ExpectHost unless method_defined?(:expect)
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
private
|
|
176
|
+
|
|
177
|
+
def declare_verifying_double(type, ref, *args)
|
|
178
|
+
if RSpec::Mocks.configuration.verify_doubled_constant_names? &&
|
|
179
|
+
!ref.defined?
|
|
180
|
+
|
|
181
|
+
raise NameError,
|
|
182
|
+
"#{ref.name} is not a defined constant. " +
|
|
183
|
+
"Perhaps you misspelt it? " +
|
|
184
|
+
"Disable check with verify_doubled_constant_names configuration option."
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
declare_double(type, ref, *args)
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def declare_double(type, *args)
|
|
191
|
+
args << {} unless Hash === args.last
|
|
192
|
+
type.new(*args)
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# This module exists to host the `expect` method for cases where
|
|
196
|
+
# rspec-mocks is used w/o rspec-expectations.
|
|
197
|
+
module ExpectHost
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
end
|