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.
Files changed (176) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +3 -0
  3. data/.gitmodules +15 -0
  4. data/.travis.yml +13 -0
  5. data/.yardopts +5 -0
  6. data/CHANGELOG.md +25 -0
  7. data/Gemfile +8 -0
  8. data/README.md +147 -0
  9. data/Rakefile +26 -0
  10. data/config.ru +10 -0
  11. data/example/Gemfile +4 -0
  12. data/example/README.md +13 -0
  13. data/example/Rakefile +8 -0
  14. data/example/opal/user.rb +11 -0
  15. data/example/spec/user_spec.rb +15 -0
  16. data/lib/opal-rspec.rb +2 -0
  17. data/lib/opal/rspec.rb +20 -0
  18. data/lib/opal/rspec/rake_task.rb +63 -0
  19. data/lib/opal/rspec/version.rb +5 -0
  20. data/opal-rspec.gemspec +21 -0
  21. data/opal/opal-rspec.rb +1 -0
  22. data/opal/opal/rspec.rb +25 -0
  23. data/opal/opal/rspec/async.rb +289 -0
  24. data/opal/opal/rspec/browser_formatter.rb +188 -0
  25. data/opal/opal/rspec/fixes.rb +116 -0
  26. data/opal/opal/rspec/requires.rb +45 -0
  27. data/opal/opal/rspec/runner.rb +69 -0
  28. data/opal/opal/rspec/sprockets_runner.rb.erb +11 -0
  29. data/opal/opal/rspec/text_formatter.rb +74 -0
  30. data/spec/async_spec.rb +38 -0
  31. data/spec/example_spec.rb +163 -0
  32. data/spec/matchers_spec.rb +201 -0
  33. data/spec/mock_spec.rb +63 -0
  34. data/spec/named_subject_spec.rb +11 -0
  35. data/spec/should_syntax_spec.rb +17 -0
  36. data/vendor/spec_runner.js +50 -0
  37. data/vendor_lib/rspec-expectations.rb +1 -0
  38. data/vendor_lib/rspec.rb +3 -0
  39. data/vendor_lib/rspec/autorun.rb +2 -0
  40. data/vendor_lib/rspec/core.rb +203 -0
  41. data/vendor_lib/rspec/core/backport_random.rb +302 -0
  42. data/vendor_lib/rspec/core/backtrace_formatter.rb +65 -0
  43. data/vendor_lib/rspec/core/command_line.rb +36 -0
  44. data/vendor_lib/rspec/core/configuration.rb +1129 -0
  45. data/vendor_lib/rspec/core/configuration_options.rb +143 -0
  46. data/vendor_lib/rspec/core/drb_command_line.rb +26 -0
  47. data/vendor_lib/rspec/core/drb_options.rb +87 -0
  48. data/vendor_lib/rspec/core/dsl.rb +26 -0
  49. data/vendor_lib/rspec/core/example.rb +312 -0
  50. data/vendor_lib/rspec/core/example_group.rb +540 -0
  51. data/vendor_lib/rspec/core/filter_manager.rb +224 -0
  52. data/vendor_lib/rspec/core/flat_map.rb +17 -0
  53. data/vendor_lib/rspec/core/formatters.rb +54 -0
  54. data/vendor_lib/rspec/core/formatters/base_formatter.rb +291 -0
  55. data/vendor_lib/rspec/core/formatters/base_text_formatter.rb +307 -0
  56. data/vendor_lib/rspec/core/formatters/deprecation_formatter.rb +193 -0
  57. data/vendor_lib/rspec/core/formatters/documentation_formatter.rb +67 -0
  58. data/vendor_lib/rspec/core/formatters/helpers.rb +82 -0
  59. data/vendor_lib/rspec/core/formatters/html_formatter.rb +155 -0
  60. data/vendor_lib/rspec/core/formatters/html_printer.rb +408 -0
  61. data/vendor_lib/rspec/core/formatters/json_formatter.rb +99 -0
  62. data/vendor_lib/rspec/core/formatters/progress_formatter.rb +32 -0
  63. data/vendor_lib/rspec/core/formatters/snippet_extractor.rb +101 -0
  64. data/vendor_lib/rspec/core/hooks.rb +535 -0
  65. data/vendor_lib/rspec/core/memoized_helpers.rb +431 -0
  66. data/vendor_lib/rspec/core/metadata.rb +313 -0
  67. data/vendor_lib/rspec/core/mocking/with_absolutely_nothing.rb +11 -0
  68. data/vendor_lib/rspec/core/mocking/with_flexmock.rb +27 -0
  69. data/vendor_lib/rspec/core/mocking/with_mocha.rb +52 -0
  70. data/vendor_lib/rspec/core/mocking/with_rr.rb +27 -0
  71. data/vendor_lib/rspec/core/mocking/with_rspec.rb +27 -0
  72. data/vendor_lib/rspec/core/option_parser.rb +234 -0
  73. data/vendor_lib/rspec/core/ordering.rb +154 -0
  74. data/vendor_lib/rspec/core/pending.rb +110 -0
  75. data/vendor_lib/rspec/core/project_initializer.rb +88 -0
  76. data/vendor_lib/rspec/core/rake_task.rb +128 -0
  77. data/vendor_lib/rspec/core/reporter.rb +132 -0
  78. data/vendor_lib/rspec/core/ruby_project.rb +44 -0
  79. data/vendor_lib/rspec/core/runner.rb +97 -0
  80. data/vendor_lib/rspec/core/shared_context.rb +53 -0
  81. data/vendor_lib/rspec/core/shared_example_group.rb +146 -0
  82. data/vendor_lib/rspec/core/shared_example_group/collection.rb +27 -0
  83. data/vendor_lib/rspec/core/version.rb +7 -0
  84. data/vendor_lib/rspec/core/warnings.rb +22 -0
  85. data/vendor_lib/rspec/core/world.rb +131 -0
  86. data/vendor_lib/rspec/expectations.rb +75 -0
  87. data/vendor_lib/rspec/expectations/differ.rb +154 -0
  88. data/vendor_lib/rspec/expectations/errors.rb +9 -0
  89. data/vendor_lib/rspec/expectations/expectation_target.rb +87 -0
  90. data/vendor_lib/rspec/expectations/extensions.rb +1 -0
  91. data/vendor_lib/rspec/expectations/extensions/object.rb +29 -0
  92. data/vendor_lib/rspec/expectations/fail_with.rb +79 -0
  93. data/vendor_lib/rspec/expectations/handler.rb +68 -0
  94. data/vendor_lib/rspec/expectations/syntax.rb +182 -0
  95. data/vendor_lib/rspec/expectations/version.rb +8 -0
  96. data/vendor_lib/rspec/matchers.rb +633 -0
  97. data/vendor_lib/rspec/matchers/built_in.rb +39 -0
  98. data/vendor_lib/rspec/matchers/built_in/base_matcher.rb +68 -0
  99. data/vendor_lib/rspec/matchers/built_in/be.rb +213 -0
  100. data/vendor_lib/rspec/matchers/built_in/be_instance_of.rb +15 -0
  101. data/vendor_lib/rspec/matchers/built_in/be_kind_of.rb +11 -0
  102. data/vendor_lib/rspec/matchers/built_in/be_within.rb +55 -0
  103. data/vendor_lib/rspec/matchers/built_in/change.rb +141 -0
  104. data/vendor_lib/rspec/matchers/built_in/cover.rb +21 -0
  105. data/vendor_lib/rspec/matchers/built_in/eq.rb +22 -0
  106. data/vendor_lib/rspec/matchers/built_in/eql.rb +23 -0
  107. data/vendor_lib/rspec/matchers/built_in/equal.rb +48 -0
  108. data/vendor_lib/rspec/matchers/built_in/exist.rb +26 -0
  109. data/vendor_lib/rspec/matchers/built_in/has.rb +48 -0
  110. data/vendor_lib/rspec/matchers/built_in/include.rb +61 -0
  111. data/vendor_lib/rspec/matchers/built_in/match.rb +17 -0
  112. data/vendor_lib/rspec/matchers/built_in/match_array.rb +51 -0
  113. data/vendor_lib/rspec/matchers/built_in/raise_error.rb +154 -0
  114. data/vendor_lib/rspec/matchers/built_in/respond_to.rb +74 -0
  115. data/vendor_lib/rspec/matchers/built_in/satisfy.rb +30 -0
  116. data/vendor_lib/rspec/matchers/built_in/start_and_end_with.rb +48 -0
  117. data/vendor_lib/rspec/matchers/built_in/throw_symbol.rb +94 -0
  118. data/vendor_lib/rspec/matchers/built_in/yield.rb +297 -0
  119. data/vendor_lib/rspec/matchers/compatibility.rb +14 -0
  120. data/vendor_lib/rspec/matchers/configuration.rb +113 -0
  121. data/vendor_lib/rspec/matchers/dsl.rb +23 -0
  122. data/vendor_lib/rspec/matchers/generated_descriptions.rb +35 -0
  123. data/vendor_lib/rspec/matchers/matcher.rb +301 -0
  124. data/vendor_lib/rspec/matchers/method_missing.rb +12 -0
  125. data/vendor_lib/rspec/matchers/operator_matcher.rb +99 -0
  126. data/vendor_lib/rspec/matchers/pretty.rb +70 -0
  127. data/vendor_lib/rspec/matchers/test_unit_integration.rb +11 -0
  128. data/vendor_lib/rspec/mocks.rb +100 -0
  129. data/vendor_lib/rspec/mocks/any_instance/chain.rb +92 -0
  130. data/vendor_lib/rspec/mocks/any_instance/expectation_chain.rb +47 -0
  131. data/vendor_lib/rspec/mocks/any_instance/message_chains.rb +75 -0
  132. data/vendor_lib/rspec/mocks/any_instance/recorder.rb +200 -0
  133. data/vendor_lib/rspec/mocks/any_instance/stub_chain.rb +45 -0
  134. data/vendor_lib/rspec/mocks/any_instance/stub_chain_chain.rb +23 -0
  135. data/vendor_lib/rspec/mocks/argument_list_matcher.rb +104 -0
  136. data/vendor_lib/rspec/mocks/argument_matchers.rb +264 -0
  137. data/vendor_lib/rspec/mocks/arity_calculator.rb +66 -0
  138. data/vendor_lib/rspec/mocks/configuration.rb +111 -0
  139. data/vendor_lib/rspec/mocks/error_generator.rb +203 -0
  140. data/vendor_lib/rspec/mocks/errors.rb +12 -0
  141. data/vendor_lib/rspec/mocks/example_methods.rb +201 -0
  142. data/vendor_lib/rspec/mocks/extensions/marshal.rb +17 -0
  143. data/vendor_lib/rspec/mocks/framework.rb +36 -0
  144. data/vendor_lib/rspec/mocks/instance_method_stasher.rb +112 -0
  145. data/vendor_lib/rspec/mocks/matchers/have_received.rb +99 -0
  146. data/vendor_lib/rspec/mocks/matchers/receive.rb +112 -0
  147. data/vendor_lib/rspec/mocks/matchers/receive_messages.rb +72 -0
  148. data/vendor_lib/rspec/mocks/message_expectation.rb +643 -0
  149. data/vendor_lib/rspec/mocks/method_double.rb +209 -0
  150. data/vendor_lib/rspec/mocks/method_reference.rb +95 -0
  151. data/vendor_lib/rspec/mocks/mock.rb +7 -0
  152. data/vendor_lib/rspec/mocks/mutate_const.rb +406 -0
  153. data/vendor_lib/rspec/mocks/object_reference.rb +90 -0
  154. data/vendor_lib/rspec/mocks/order_group.rb +82 -0
  155. data/vendor_lib/rspec/mocks/proxy.rb +269 -0
  156. data/vendor_lib/rspec/mocks/proxy_for_nil.rb +37 -0
  157. data/vendor_lib/rspec/mocks/space.rb +95 -0
  158. data/vendor_lib/rspec/mocks/standalone.rb +3 -0
  159. data/vendor_lib/rspec/mocks/stub_chain.rb +51 -0
  160. data/vendor_lib/rspec/mocks/syntax.rb +374 -0
  161. data/vendor_lib/rspec/mocks/targets.rb +90 -0
  162. data/vendor_lib/rspec/mocks/test_double.rb +109 -0
  163. data/vendor_lib/rspec/mocks/verifying_double.rb +77 -0
  164. data/vendor_lib/rspec/mocks/verifying_message_expecation.rb +60 -0
  165. data/vendor_lib/rspec/mocks/verifying_proxy.rb +151 -0
  166. data/vendor_lib/rspec/mocks/version.rb +7 -0
  167. data/vendor_lib/rspec/support.rb +6 -0
  168. data/vendor_lib/rspec/support/caller_filter.rb +56 -0
  169. data/vendor_lib/rspec/support/spec.rb +14 -0
  170. data/vendor_lib/rspec/support/spec/deprecation_helpers.rb +29 -0
  171. data/vendor_lib/rspec/support/spec/in_sub_process.rb +40 -0
  172. data/vendor_lib/rspec/support/spec/stderr_splitter.rb +50 -0
  173. data/vendor_lib/rspec/support/version.rb +7 -0
  174. data/vendor_lib/rspec/support/warnings.rb +41 -0
  175. data/vendor_lib/rspec/version.rb +5 -0
  176. metadata +268 -0
@@ -0,0 +1,14 @@
1
+ RSpec::Matchers.constants.each do |c|
2
+ if Class === (klass = RSpec::Matchers.const_get(c))
3
+ if klass.public_instance_methods.any? {|m| ['failure_message_for_should',:failure_message_for_should].include?(m)}
4
+ klass.class_exec do
5
+ alias_method :failure_message, :failure_message_for_should
6
+ end
7
+ end
8
+ if klass.public_instance_methods.any? {|m| ['failure_message_for_should_not',:failure_message_for_should_not].include?(m)}
9
+ klass.class_exec do
10
+ alias_method :negative_failure_message, :failure_message_for_should_not
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,113 @@
1
+ require 'rspec/expectations/syntax'
2
+
3
+ module RSpec
4
+ module Matchers
5
+ # Provides configuration options for rspec-expectations.
6
+ class Configuration
7
+ # Configures the supported syntax.
8
+ # @param [Array<Symbol>, Symbol] values the syntaxes to enable
9
+ # @example
10
+ # RSpec.configure do |rspec|
11
+ # rspec.expect_with :rspec do |c|
12
+ # c.syntax = :should
13
+ # # or
14
+ # c.syntax = :expect
15
+ # # or
16
+ # c.syntax = [:should, :expect]
17
+ # end
18
+ # end
19
+ def syntax=(values)
20
+ if Array(values).include?(:expect)
21
+ Expectations::Syntax.enable_expect
22
+ else
23
+ Expectations::Syntax.disable_expect
24
+ end
25
+
26
+ if Array(values).include?(:should)
27
+ Expectations::Syntax.enable_should
28
+ else
29
+ Expectations::Syntax.disable_should
30
+ end
31
+ end
32
+
33
+ # The list of configured syntaxes.
34
+ # @return [Array<Symbol>] the list of configured syntaxes.
35
+ def syntax
36
+ syntaxes = []
37
+ syntaxes << :should if Expectations::Syntax.should_enabled?
38
+ syntaxes << :expect if Expectations::Syntax.expect_enabled?
39
+ syntaxes
40
+ end
41
+
42
+ # color config for expectations
43
+ # fallback if rspec core not available
44
+ if ::RSpec.respond_to?(:configuration)
45
+ def color?
46
+ ::RSpec.configuration.color_enabled?
47
+ end
48
+ else
49
+ attr_writer :color
50
+ def color?
51
+ @color
52
+ end
53
+ end
54
+
55
+ # Adds `should` and `should_not` to the given classes
56
+ # or modules. This can be used to ensure `should` works
57
+ # properly on things like proxy objects (particular
58
+ # `Delegator`-subclassed objects on 1.8).
59
+ #
60
+ # @param [Array<Module>] modules the list of classes or modules
61
+ # to add `should` and `should_not` to.
62
+ def add_should_and_should_not_to(*modules)
63
+ modules.each do |mod|
64
+ Expectations::Syntax.enable_should(mod)
65
+ end
66
+ end
67
+
68
+ # Sets or gets the backtrace formatter. The backtrace formatter should
69
+ # implement `#format_backtrace(Array<String>)`. This is used
70
+ # to format backtraces of errors handled by the `raise_error`
71
+ # matcher.
72
+ #
73
+ # If you are using rspec-core, rspec-core's backtrace formatting
74
+ # will be used (including respecting the presence or absence of
75
+ # the `--backtrace` option).
76
+ #
77
+ # @overload backtrace_formatter
78
+ # @return [#format_backtrace] the backtrace formatter
79
+ # @overload backtrace_formatter=
80
+ # @param value [#format_backtrace] sets the backtrace formatter
81
+ attr_writer :backtrace_formatter
82
+ def backtrace_formatter
83
+ @backtrace_formatter ||= if defined?(::RSpec::Core::BacktraceFormatter)
84
+ ::RSpec::Core::BacktraceFormatter
85
+ else
86
+ NullBacktraceFormatter
87
+ end
88
+ end
89
+
90
+ def reset_syntaxes_to_default
91
+ self.syntax = [:should, :expect]
92
+ RSpec::Expectations::Syntax.warn_about_should!
93
+ end
94
+
95
+ # @api private
96
+ NullBacktraceFormatter = Module.new do
97
+ def self.format_backtrace(backtrace)
98
+ backtrace
99
+ end
100
+ end
101
+ end
102
+
103
+ # The configuration object
104
+ # @return [RSpec::Matchers::Configuration] the configuration object
105
+ def self.configuration
106
+ @configuration ||= Configuration.new
107
+ end
108
+
109
+ # set default syntax
110
+ configuration.reset_syntaxes_to_default
111
+ end
112
+ end
113
+
@@ -0,0 +1,23 @@
1
+ module RSpec
2
+ module Matchers
3
+ module DSL
4
+ # Defines a custom matcher.
5
+ # @see RSpec::Matchers
6
+ def define(name, &declarations)
7
+ define_method name do |*expected|
8
+ matcher = RSpec::Matchers::DSL::Matcher.new(name, declarations, *expected)
9
+ matcher.matcher_execution_context = @matcher_execution_context ||= self
10
+ matcher
11
+ end
12
+ end
13
+
14
+ alias_method :matcher, :define
15
+
16
+ if RSpec.respond_to?(:configure)
17
+ RSpec.configure {|c| c.extend self}
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ RSpec::Matchers.extend RSpec::Matchers::DSL
@@ -0,0 +1,35 @@
1
+ module RSpec
2
+ module Matchers
3
+ class << self
4
+ attr_accessor :last_matcher, :last_should
5
+ end
6
+
7
+ def self.clear_generated_description
8
+ self.last_matcher = nil
9
+ self.last_should = nil
10
+ end
11
+
12
+ def self.generated_description
13
+ return nil if last_should.nil?
14
+ "#{last_should.to_s.gsub('_',' ')} #{last_description}"
15
+ end
16
+
17
+ private
18
+
19
+ def self.last_description
20
+ last_matcher.respond_to?(:description) ? last_matcher.description : <<-MESSAGE
21
+ When you call a matcher in an example without a String, like this:
22
+
23
+ specify { object.should matcher }
24
+
25
+ or this:
26
+
27
+ it { should matcher }
28
+
29
+ RSpec expects the matcher to have a #description method. You should either
30
+ add a String to the example this matcher is being used in, or give it a
31
+ description method. Then you won't have to suffer this lengthy warning again.
32
+ MESSAGE
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,301 @@
1
+ require 'set'
2
+
3
+ module RSpec
4
+ module Matchers
5
+ module DSL
6
+ # Contains the methods that are available from within the
7
+ # `RSpec::Matchers.define` DSL for creating custom matchers.
8
+ module Macros
9
+ # Stores the block that is used to determine whether this matcher passes
10
+ # or fails. The block should return a boolean value. When the matcher is
11
+ # passed to `expect(...).to` and the block returns `true`, then the expectation
12
+ # passes. Similarly, when the matcher is passed to `expect(...).not_to` and the
13
+ # block returns `false`, then the expectation passes.
14
+ #
15
+ # Use `match_for_should` when used in conjunction with
16
+ # `match_for_should_not`.
17
+ #
18
+ # @example
19
+ #
20
+ # RSpec::Matchers.define :be_even do
21
+ # match do |actual|
22
+ # actual.even?
23
+ # end
24
+ # end
25
+ #
26
+ # expect(4).to be_even # passes
27
+ # expect(3).not_to be_even # passes
28
+ # expect(3).to be_even # fails
29
+ # expect(4).not_to be_even # fails
30
+ #
31
+ # @yield [Object] actual the actual value (i.e. the value wrapped by `expect`)
32
+ def match(&match_block)
33
+ define_user_override(:matches?, match_block) do |actual|
34
+ begin
35
+ @actual = actual
36
+ super(*actual_arg_for(match_block))
37
+ rescue RSpec::Expectations::ExpectationNotMetError
38
+ false
39
+ end
40
+ end
41
+ end
42
+ alias match_for_should match
43
+
44
+ # Use this to define the block for a negative expectation (`expect(...).not_to`)
45
+ # when the positive and negative forms require different handling. This
46
+ # is rarely necessary, but can be helpful, for example, when specifying
47
+ # asynchronous processes that require different timeouts.
48
+ #
49
+ # @yield [Object] actual the actual value (i.e. the value wrapped by `expect`)
50
+ def match_for_should_not(&match_block)
51
+ define_user_override(:does_not_match?, match_block) do |actual|
52
+ @actual = actual
53
+ super(*actual_arg_for(match_block))
54
+ end
55
+ end
56
+
57
+ # Use this instead of `match` when the block will raise an exception
58
+ # rather than returning false to indicate a failure.
59
+ #
60
+ # @example
61
+ #
62
+ # RSpec::Matchers.define :accept_as_valid do |candidate_address|
63
+ # match_unless_raises ValidationException do |validator|
64
+ # validator.validate(candidate_address)
65
+ # end
66
+ # end
67
+ #
68
+ # expect(email_validator).to accept_as_valid("person@company.com")
69
+ #
70
+ # @yield [Object] actual the actual object (i.e. the value wrapped by `expect`)
71
+ def match_unless_raises(expected_exception=Exception, &match_block)
72
+ define_user_override(:matches?, match_block) do |actual|
73
+ @actual = actual
74
+ begin
75
+ super(*actual_arg_for(match_block))
76
+ rescue expected_exception => @rescued_exception
77
+ false
78
+ else
79
+ true
80
+ end
81
+ end
82
+ end
83
+
84
+ # Customizes the failure messsage to use when this matcher is
85
+ # asked to positively match. Only use this when the message
86
+ # generated by default doesn't suit your needs.
87
+ #
88
+ # @example
89
+ #
90
+ # RSpec::Matchers.define :have_strength do |expected|
91
+ # match { your_match_logic }
92
+ #
93
+ # failure_message_for_should do |actual|
94
+ # "Expected strength of #{expected}, but had #{actual.strength}"
95
+ # end
96
+ # end
97
+ #
98
+ # @yield [Object] actual the actual object (i.e. the value wrapped by `expect`)
99
+ def failure_message_for_should(&definition)
100
+ define_user_override(__method__, definition)
101
+ end
102
+
103
+ # Customize the failure messsage to use when this matcher is asked
104
+ # to negatively match. Only use this when the message generated by
105
+ # default doesn't suit your needs.
106
+ #
107
+ # @example
108
+ #
109
+ # RSpec::Matchers.define :have_strength do |expected|
110
+ # match { your_match_logic }
111
+ #
112
+ # failure_message_for_should_not do |actual|
113
+ # "Expected not to have strength of #{expected}, but did"
114
+ # end
115
+ # end
116
+ #
117
+ # @yield [Object] actual the actual object (i.e. the value wrapped by `expect`)
118
+ def failure_message_for_should_not(&definition)
119
+ define_user_override(__method__, definition)
120
+ end
121
+
122
+ # Customize the description to use for one-liners. Only use this when
123
+ # the description generated by default doesn't suit your needs.
124
+ #
125
+ # @example
126
+ #
127
+ # RSpec::Matchers.define :qualify_for do |expected|
128
+ # match { your_match_logic }
129
+ #
130
+ # description do
131
+ # "qualify for #{expected}"
132
+ # end
133
+ # end
134
+ #
135
+ # @yield [Object] actual the actual object (i.e. the value wrapped by `expect`)
136
+ def description(&definition)
137
+ define_user_override(__method__, definition)
138
+ end
139
+
140
+ # Tells the matcher to diff the actual and expected values in the failure
141
+ # message.
142
+ def diffable
143
+ define_method(:diffable?) { true }
144
+ end
145
+
146
+ # Convenience for defining methods on this matcher to create a fluent
147
+ # interface. The trick about fluent interfaces is that each method must
148
+ # return self in order to chain methods together. `chain` handles that
149
+ # for you.
150
+ #
151
+ # @example
152
+ #
153
+ # RSpec::Matchers.define :have_errors_on do |key|
154
+ # chain :with do |message|
155
+ # @message = message
156
+ # end
157
+ #
158
+ # match do |actual|
159
+ # actual.errors[key] == @message
160
+ # end
161
+ # end
162
+ #
163
+ # expect(minor).to have_errors_on(:age).with("Not old enough to participate")
164
+ def chain(name, &definition)
165
+ define_user_override(name, definition) do |*args, &block|
166
+ super(*args, &block)
167
+ self
168
+ end
169
+ end
170
+
171
+ private
172
+
173
+ # Does the following:
174
+ #
175
+ # - Defines the named method usign a user-provided block
176
+ # in @user_method_defs, which is included as an ancestor
177
+ # in the singleton class in which we eval the `define` block.
178
+ # - Defines an overriden definition for the same method
179
+ # usign the provided `our_def` block.
180
+ # - Provides a default `our_def` block for the common case
181
+ # of needing to call the user's definition with `@actual`
182
+ # as an arg, but only if their block's arity can handle it.
183
+ #
184
+ # This compiles the user block into an actual method, allowing
185
+ # them to use normal method constructs like `return`
186
+ # (e.g. for a early guard statement), while allowing us to define
187
+ # an override that can provide the wrapped handling
188
+ # (e.g. assigning `@actual`, rescueing errors, etc) and
189
+ # can `super` to the user's definition.
190
+ def define_user_override(method_name, user_def, &our_def)
191
+ @user_method_defs.__send__(:define_method, method_name, &user_def)
192
+ our_def ||= lambda { super(*actual_arg_for(user_def)) }
193
+ define_method(method_name, &our_def)
194
+ end
195
+ end
196
+
197
+ # Defines default implementations of the matcher
198
+ # protocol methods for custom matchers. You can
199
+ # override any of these using the {RSpec::Matchers::DSL::Macros Macros} methods
200
+ # from within an `RSpec::Matchers.define` block.
201
+ module DefaultImplementations
202
+ # @api private
203
+ # Used internally by objects returns by `should` and `should_not`.
204
+ def diffable?
205
+ false
206
+ end
207
+
208
+ # The default description.
209
+ def description
210
+ "#{name_to_sentence}#{expected_to_sentence}"
211
+ end
212
+
213
+ # The default failure message for positive expectations.
214
+ def failure_message_for_should
215
+ "expected #{actual.inspect} to #{name_to_sentence}#{expected_to_sentence}"
216
+ end
217
+
218
+ # The default failure message for negative expectations.
219
+ def failure_message_for_should_not
220
+ "expected #{actual.inspect} not to #{name_to_sentence}#{expected_to_sentence}"
221
+ end
222
+ end
223
+
224
+ # The class used for custom matchers. The block passed to
225
+ # `RSpec::Matchers.define` will be evaluated in the context
226
+ # of the singleton class of an instance, and will have the
227
+ # {RSpec::Matchers::DSL::Macros Macros} methods available.
228
+ class Matcher
229
+ # Provides default implementations for the matcher protocol methods.
230
+ include DefaultImplementations
231
+
232
+ # Allows expectation expressions to be used in the match block.
233
+ include RSpec::Matchers
234
+
235
+ # Converts matcher name and expected args to an English expresion.
236
+ include RSpec::Matchers::Pretty
237
+
238
+ # Makes the macro methods available to an `RSpec::Matchers.define` block.
239
+ extend Macros
240
+
241
+ attr_reader :expected, :actual, :rescued_exception
242
+ attr_accessor :matcher_execution_context
243
+
244
+ # @api private
245
+ def initialize(name, declarations, *expected)
246
+ @name = name
247
+ @actual = nil
248
+ @expected = expected
249
+
250
+ class << self
251
+ # See `Macros#define_user_override` above, for an explanation.
252
+ include(@user_method_defs = Module.new)
253
+ self
254
+ end.class_exec(*expected, &declarations)
255
+ end
256
+
257
+ # Adds the name (rather than a cryptic hex number)
258
+ # so we can identify an instance of
259
+ # the matcher in error messages (e.g. for `NoMethodError`)
260
+ def inspect
261
+ "#<#{self.class.name} #{name}>"
262
+ end
263
+
264
+ if RUBY_VERSION.to_f >= 1.9
265
+ # Indicates that this matcher responds to messages
266
+ # from the `matcher_execution_context` as well.
267
+ # Also, supports getting a method object for such methods.
268
+ def respond_to_missing?(method, include_private=false)
269
+ super || matcher_execution_context.respond_to?(method, include_private)
270
+ end
271
+ else # for 1.8.7
272
+ # Indicates that this matcher responds to messages
273
+ # from the `matcher_execution_context` as well.
274
+ def respond_to?(method, include_private=false)
275
+ super || matcher_execution_context.respond_to?(method, include_private)
276
+ end
277
+ end
278
+
279
+ private
280
+
281
+ def actual_arg_for(block)
282
+ block.arity.zero? ? [] : [@actual]
283
+ end
284
+
285
+ # Takes care of forwarding unhandled messages to the
286
+ # `matcher_execution_context` (typically the current
287
+ # running `RSpec::Core::Example`). This is needed by
288
+ # rspec-rails so that it can define matchers that wrap
289
+ # Rails' test helper methods, but it's also a useful
290
+ # feature in its own right.
291
+ def method_missing(method, *args, &block)
292
+ if matcher_execution_context.respond_to?(method)
293
+ matcher_execution_context.__send__ method, *args, &block
294
+ else
295
+ super(method, *args, &block)
296
+ end
297
+ end
298
+ end
299
+ end
300
+ end
301
+ end