rspec-core 3.0.0.beta2 → 3.0.0.rc1

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 (201) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/.yardopts +1 -0
  5. data/Changelog.md +297 -57
  6. data/README.md +16 -13
  7. data/lib/rspec/core.rb +55 -84
  8. data/lib/rspec/core/backport_random.rb +35 -3
  9. data/lib/rspec/core/backtrace_formatter.rb +4 -13
  10. data/lib/rspec/core/configuration.rb +330 -114
  11. data/lib/rspec/core/configuration_options.rb +38 -22
  12. data/lib/rspec/core/drb.rb +111 -0
  13. data/lib/rspec/core/dsl.rb +8 -2
  14. data/lib/rspec/core/example.rb +203 -94
  15. data/lib/rspec/core/example_group.rb +344 -316
  16. data/lib/rspec/core/filter_manager.rb +135 -90
  17. data/lib/rspec/core/flat_map.rb +1 -0
  18. data/lib/rspec/core/formatters.rb +50 -14
  19. data/lib/rspec/core/formatters/base_formatter.rb +32 -138
  20. data/lib/rspec/core/formatters/base_text_formatter.rb +32 -253
  21. data/lib/rspec/core/formatters/console_codes.rb +65 -0
  22. data/lib/rspec/core/formatters/deprecation_formatter.rb +24 -15
  23. data/lib/rspec/core/formatters/documentation_formatter.rb +7 -10
  24. data/lib/rspec/core/formatters/helpers.rb +15 -9
  25. data/lib/rspec/core/formatters/html_formatter.rb +17 -16
  26. data/lib/rspec/core/formatters/html_printer.rb +1 -0
  27. data/lib/rspec/core/formatters/json_formatter.rb +18 -20
  28. data/lib/rspec/core/formatters/profile_formatter.rb +67 -0
  29. data/lib/rspec/core/formatters/progress_formatter.rb +6 -7
  30. data/lib/rspec/core/formatters/snippet_extractor.rb +8 -6
  31. data/lib/rspec/core/hooks.rb +131 -125
  32. data/lib/rspec/core/memoized_helpers.rb +31 -26
  33. data/lib/rspec/core/metadata.rb +277 -184
  34. data/lib/rspec/core/metadata_filter.rb +86 -0
  35. data/lib/rspec/core/minitest_assertions_adapter.rb +28 -0
  36. data/lib/rspec/core/mocking_adapters/flexmock.rb +1 -1
  37. data/lib/rspec/core/mocking_adapters/mocha.rb +1 -1
  38. data/lib/rspec/core/mocking_adapters/null.rb +1 -1
  39. data/lib/rspec/core/mocking_adapters/rr.rb +2 -1
  40. data/lib/rspec/core/mocking_adapters/rspec.rb +1 -1
  41. data/lib/rspec/core/notifications.rb +435 -24
  42. data/lib/rspec/core/option_parser.rb +16 -25
  43. data/lib/rspec/core/ordering.rb +3 -1
  44. data/lib/rspec/core/pending.rb +57 -33
  45. data/lib/rspec/core/project_initializer.rb +2 -0
  46. data/lib/rspec/core/project_initializer/spec_helper.rb +5 -4
  47. data/lib/rspec/core/rake_task.rb +45 -20
  48. data/lib/rspec/core/reporter.rb +50 -22
  49. data/lib/rspec/core/ruby_project.rb +1 -0
  50. data/lib/rspec/core/runner.rb +93 -39
  51. data/lib/rspec/core/shared_context.rb +7 -5
  52. data/lib/rspec/core/shared_example_group.rb +85 -77
  53. data/lib/rspec/core/test_unit_assertions_adapter.rb +30 -0
  54. data/lib/rspec/core/version.rb +3 -1
  55. data/lib/rspec/core/warnings.rb +35 -17
  56. data/lib/rspec/core/world.rb +57 -5
  57. metadata +56 -369
  58. metadata.gz.sig +3 -3
  59. data/features/README.md +0 -13
  60. data/features/Upgrade.md +0 -352
  61. data/features/command_line/README.md +0 -25
  62. data/features/command_line/dry_run.feature +0 -29
  63. data/features/command_line/example_name_option.feature +0 -97
  64. data/features/command_line/exit_status.feature +0 -82
  65. data/features/command_line/fail_fast.feature +0 -26
  66. data/features/command_line/format_option.feature +0 -75
  67. data/features/command_line/init.feature +0 -57
  68. data/features/command_line/line_number_appended_to_path.feature +0 -140
  69. data/features/command_line/line_number_option.feature +0 -58
  70. data/features/command_line/order.feature +0 -25
  71. data/features/command_line/pattern_option.feature +0 -49
  72. data/features/command_line/rake_task.feature +0 -122
  73. data/features/command_line/randomization.feature +0 -63
  74. data/features/command_line/require_option.feature +0 -43
  75. data/features/command_line/ruby.feature +0 -23
  76. data/features/command_line/tag.feature +0 -98
  77. data/features/command_line/warnings_option.feature +0 -29
  78. data/features/configuration/alias_example_to.feature +0 -39
  79. data/features/configuration/backtrace_exclusion_patterns.feature +0 -105
  80. data/features/configuration/custom_settings.feature +0 -84
  81. data/features/configuration/default_path.feature +0 -38
  82. data/features/configuration/deprecation_stream.feature +0 -58
  83. data/features/configuration/enable_global_dsl.feature +0 -54
  84. data/features/configuration/fail_fast.feature +0 -77
  85. data/features/configuration/failure_exit_code.feature +0 -36
  86. data/features/configuration/order_and_seed.feature +0 -3
  87. data/features/configuration/output_stream.feature +0 -24
  88. data/features/configuration/overriding_global_ordering.feature +0 -93
  89. data/features/configuration/pattern.feature +0 -38
  90. data/features/configuration/profile.feature +0 -220
  91. data/features/configuration/read_options_from_file.feature +0 -90
  92. data/features/configuration/run_all_when_everything_filtered.feature +0 -76
  93. data/features/example_groups/aliasing.feature +0 -48
  94. data/features/example_groups/basic_structure.feature +0 -55
  95. data/features/example_groups/shared_context.feature +0 -74
  96. data/features/example_groups/shared_examples.feature +0 -286
  97. data/features/expectation_framework_integration/configure_expectation_framework.feature +0 -102
  98. data/features/filtering/exclusion_filters.feature +0 -135
  99. data/features/filtering/if_and_unless.feature +0 -138
  100. data/features/filtering/inclusion_filters.feature +0 -101
  101. data/features/formatters/configurable_colors.feature +0 -31
  102. data/features/formatters/custom_formatter.feature +0 -68
  103. data/features/formatters/json_formatter.feature +0 -30
  104. data/features/formatters/regression_tests.feature +0 -95
  105. data/features/formatters/text_formatter.feature +0 -46
  106. data/features/helper_methods/arbitrary_methods.feature +0 -40
  107. data/features/helper_methods/let.feature +0 -50
  108. data/features/helper_methods/modules.feature +0 -146
  109. data/features/hooks/around_hooks.feature +0 -344
  110. data/features/hooks/before_and_after_hooks.feature +0 -427
  111. data/features/hooks/filtering.feature +0 -232
  112. data/features/metadata/current_example.feature +0 -56
  113. data/features/metadata/described_class.feature +0 -17
  114. data/features/metadata/user_defined.feature +0 -100
  115. data/features/mock_framework_integration/use_any_framework.feature +0 -106
  116. data/features/mock_framework_integration/use_flexmock.feature +0 -94
  117. data/features/mock_framework_integration/use_mocha.feature +0 -95
  118. data/features/mock_framework_integration/use_rr.feature +0 -96
  119. data/features/mock_framework_integration/use_rspec.feature +0 -95
  120. data/features/pending_and_skipped_examples/README.md +0 -3
  121. data/features/pending_and_skipped_examples/pending_examples.feature +0 -118
  122. data/features/pending_and_skipped_examples/skipped_examples.feature +0 -106
  123. data/features/spec_files/arbitrary_file_suffix.feature +0 -13
  124. data/features/step_definitions/additional_cli_steps.rb +0 -83
  125. data/features/subject/explicit_subject.feature +0 -101
  126. data/features/subject/implicit_subject.feature +0 -63
  127. data/features/subject/one_liner_syntax.feature +0 -71
  128. data/features/support/env.rb +0 -21
  129. data/features/support/require_expect_syntax_in_aruba_specs.rb +0 -16
  130. data/features/support/rubinius.rb +0 -6
  131. data/lib/rspec/core/command_line.rb +0 -35
  132. data/lib/rspec/core/drb_command_line.rb +0 -26
  133. data/lib/rspec/core/drb_options.rb +0 -87
  134. data/lib/rspec/core/formatters/legacy_formatter.rb +0 -227
  135. data/lib/rspec/core/shared_example_group/collection.rb +0 -27
  136. data/spec/command_line/order_spec.rb +0 -211
  137. data/spec/rspec/core/backtrace_formatter_spec.rb +0 -230
  138. data/spec/rspec/core/command_line_spec.rb +0 -112
  139. data/spec/rspec/core/command_line_spec_output.txt +0 -0
  140. data/spec/rspec/core/configuration_options_spec.rb +0 -409
  141. data/spec/rspec/core/configuration_spec.rb +0 -1479
  142. data/spec/rspec/core/drb_command_line_spec.rb +0 -102
  143. data/spec/rspec/core/drb_options_spec.rb +0 -193
  144. data/spec/rspec/core/dsl_spec.rb +0 -88
  145. data/spec/rspec/core/example_group_spec.rb +0 -1533
  146. data/spec/rspec/core/example_spec.rb +0 -642
  147. data/spec/rspec/core/filter_manager_spec.rb +0 -229
  148. data/spec/rspec/core/formatters/base_formatter_spec.rb +0 -64
  149. data/spec/rspec/core/formatters/base_text_formatter_spec.rb +0 -303
  150. data/spec/rspec/core/formatters/deprecation_formatter_spec.rb +0 -208
  151. data/spec/rspec/core/formatters/documentation_formatter_spec.rb +0 -75
  152. data/spec/rspec/core/formatters/helpers_spec.rb +0 -104
  153. data/spec/rspec/core/formatters/html_formatted-2.1.0.html +0 -392
  154. data/spec/rspec/core/formatters/html_formatted.html +0 -397
  155. data/spec/rspec/core/formatters/html_formatter_spec.rb +0 -122
  156. data/spec/rspec/core/formatters/json_formatter_spec.rb +0 -206
  157. data/spec/rspec/core/formatters/legacy_formatter_spec.rb +0 -137
  158. data/spec/rspec/core/formatters/progress_formatter_spec.rb +0 -43
  159. data/spec/rspec/core/formatters/snippet_extractor_spec.rb +0 -26
  160. data/spec/rspec/core/formatters_spec.rb +0 -120
  161. data/spec/rspec/core/hooks_filtering_spec.rb +0 -227
  162. data/spec/rspec/core/hooks_spec.rb +0 -294
  163. data/spec/rspec/core/memoized_helpers_spec.rb +0 -495
  164. data/spec/rspec/core/metadata_spec.rb +0 -491
  165. data/spec/rspec/core/option_parser_spec.rb +0 -262
  166. data/spec/rspec/core/ordering_spec.rb +0 -102
  167. data/spec/rspec/core/pending_example_spec.rb +0 -117
  168. data/spec/rspec/core/pending_spec.rb +0 -8
  169. data/spec/rspec/core/project_initializer_spec.rb +0 -73
  170. data/spec/rspec/core/rake_task_spec.rb +0 -146
  171. data/spec/rspec/core/random_spec.rb +0 -47
  172. data/spec/rspec/core/reporter_spec.rb +0 -155
  173. data/spec/rspec/core/resources/a_bar.rb +0 -0
  174. data/spec/rspec/core/resources/a_foo.rb +0 -0
  175. data/spec/rspec/core/resources/a_spec.rb +0 -1
  176. data/spec/rspec/core/resources/custom_example_group_runner.rb +0 -14
  177. data/spec/rspec/core/resources/formatter_specs.rb +0 -58
  178. data/spec/rspec/core/resources/utf8_encoded.rb +0 -8
  179. data/spec/rspec/core/rspec_matchers_spec.rb +0 -45
  180. data/spec/rspec/core/ruby_project_spec.rb +0 -26
  181. data/spec/rspec/core/runner_spec.rb +0 -151
  182. data/spec/rspec/core/shared_context_spec.rb +0 -102
  183. data/spec/rspec/core/shared_example_group/collection_spec.rb +0 -57
  184. data/spec/rspec/core/shared_example_group_spec.rb +0 -114
  185. data/spec/rspec/core/warnings_spec.rb +0 -29
  186. data/spec/rspec/core/world_spec.rb +0 -142
  187. data/spec/rspec/core_spec.rb +0 -91
  188. data/spec/spec_helper.rb +0 -160
  189. data/spec/support/config_options_helper.rb +0 -13
  190. data/spec/support/formatter_support.rb +0 -83
  191. data/spec/support/helper_methods.rb +0 -26
  192. data/spec/support/isolate_load_path_mutation.rb +0 -5
  193. data/spec/support/isolated_directory.rb +0 -10
  194. data/spec/support/isolated_home_directory.rb +0 -16
  195. data/spec/support/legacy_formatter_using_sub_classing_example.rb +0 -87
  196. data/spec/support/matchers.rb +0 -85
  197. data/spec/support/mathn_integration_support.rb +0 -12
  198. data/spec/support/old_style_formatter_example.rb +0 -69
  199. data/spec/support/shared_example_groups.rb +0 -13
  200. data/spec/support/spec_files.rb +0 -44
  201. data/spec/support/stderr_splitter.rb +0 -36
@@ -6,6 +6,7 @@ require 'pathname'
6
6
 
7
7
  module RSpec
8
8
  module Core
9
+ # @private
9
10
  module RubyProject
10
11
  def add_to_load_path(*dirs)
11
12
  dirs.map {|dir| add_dir_to_load_path(File.join(root, dir))}
@@ -1,8 +1,15 @@
1
1
  module RSpec
2
2
  module Core
3
+ # Provides the main entry point to run a suite of RSpec examples.
3
4
  class Runner
4
5
 
5
- # Register an at_exit hook that runs the suite.
6
+ # Register an `at_exit` hook that runs the suite when the process exits.
7
+ #
8
+ # @note This is not generally needed. The `rspec` command takes care
9
+ # of running examples for you without involving an `at_exit`
10
+ # hook. This is only needed if you are running specs using
11
+ # the `ruby` command, and even then, the normal way to invoke
12
+ # this is by requiring `rspec/autorun`.
6
13
  def self.autorun
7
14
  if autorun_disabled?
8
15
  RSpec.deprecate("Requiring `rspec/autorun` when running RSpec via the `rspec` command")
@@ -24,26 +31,107 @@ module RSpec
24
31
  end
25
32
  @installed_at_exit = true
26
33
  end
27
- AT_EXIT_HOOK_BACKTRACE_LINE = "#{__FILE__}:#{__LINE__ - 2}:in `autorun'"
28
34
 
35
+ # Runs the suite of specs and exits the process with an appropriate exit code.
29
36
  def self.invoke
30
37
  disable_autorun!
31
38
  status = run(ARGV, $stderr, $stdout).to_i
32
39
  exit(status) if status != 0
33
40
  end
34
41
 
42
+ # Run a suite of RSpec examples. Does not exit.
43
+ #
44
+ # This is used internally by RSpec to run a suite, but is available
45
+ # for use by any other automation tool.
46
+ #
47
+ # If you want to run this multiple times in the same process, and you
48
+ # want files like `spec_helper.rb` to be reloaded, be sure to load `load`
49
+ # instead of `require`.
50
+ #
51
+ # @param args [Array] command-line-supported arguments
52
+ # @param err [IO] error stream
53
+ # @param out [IO] output stream
54
+ # @return [Fixnum] exit status code. 0 if all specs passed,
55
+ # or the configured failure exit code (1 by default) if specs
56
+ # failed.
57
+ def self.run(args, err=$stderr, out=$stdout)
58
+ trap_interrupt
59
+ options = ConfigurationOptions.new(args)
60
+
61
+ if options.options[:drb]
62
+ require 'rspec/core/drb'
63
+ begin
64
+ DRbRunner.new(options).run(err, out)
65
+ rescue DRb::DRbConnError
66
+ err.puts "No DRb server is running. Running in local process instead ..."
67
+ new(options).run(err, out)
68
+ end
69
+ else
70
+ new(options).run(err, out)
71
+ end
72
+ end
73
+
74
+ def initialize(options, configuration=RSpec.configuration, world=RSpec.world)
75
+ @options = options
76
+ @configuration = configuration
77
+ @world = world
78
+ end
79
+
80
+ # Configures and runs a spec suite.
81
+ #
82
+ # @param err [IO] error stream
83
+ # @param out [IO] output stream
84
+ def run(err, out)
85
+ setup(err, out)
86
+ run_specs(@world.ordered_example_groups)
87
+ end
88
+
89
+ # Wires together the various configuration objects and state holders.
90
+ #
91
+ # @param err [IO] error stream
92
+ # @param out [IO] output stream
93
+ def setup(err, out)
94
+ @configuration.error_stream = err
95
+ @configuration.output_stream = out if @configuration.output_stream == $stdout
96
+ @options.configure(@configuration)
97
+ @configuration.load_spec_files
98
+ @world.announce_filters
99
+ end
100
+
101
+ # Runs the provided example groups.
102
+ #
103
+ # @param example_groups [Array<RSpec::Core::ExampleGroup>] groups to run
104
+ # @return [Fixnum] exit status code. 0 if all specs passed,
105
+ # or the configured failure exit code (1 by default) if specs
106
+ # failed.
107
+ def run_specs(example_groups)
108
+ @configuration.reporter.report(@world.example_count(example_groups)) do |reporter|
109
+ begin
110
+ hook_context = SuiteHookContext.new
111
+ @configuration.hooks.run(:before, :suite, hook_context)
112
+ example_groups.map { |g| g.run(reporter) }.all? ? 0 : @configuration.failure_exit_code
113
+ ensure
114
+ @configuration.hooks.run(:after, :suite, hook_context)
115
+ end
116
+ end
117
+ end
118
+
119
+ # @private
35
120
  def self.disable_autorun!
36
121
  @autorun_disabled = true
37
122
  end
38
123
 
124
+ # @private
39
125
  def self.autorun_disabled?
40
126
  @autorun_disabled ||= false
41
127
  end
42
128
 
129
+ # @private
43
130
  def self.installed_at_exit?
44
131
  @installed_at_exit ||= false
45
132
  end
46
133
 
134
+ # @private
47
135
  def self.running_in_drb?
48
136
  begin
49
137
  if defined?(DRb) && DRb.current_server
@@ -60,48 +148,14 @@ module RSpec
60
148
  end
61
149
  end
62
150
 
151
+ # @private
63
152
  def self.trap_interrupt
64
153
  trap('INT') do
65
- exit!(1) if RSpec.wants_to_quit
66
- RSpec.wants_to_quit = true
154
+ exit!(1) if RSpec.world.wants_to_quit
155
+ RSpec.world.wants_to_quit = true
67
156
  STDERR.puts "\nExiting... Interrupt again to exit immediately."
68
157
  end
69
158
  end
70
-
71
- # Run a suite of RSpec examples.
72
- #
73
- # This is used internally by RSpec to run a suite, but is available
74
- # for use by any other automation tool.
75
- #
76
- # If you want to run this multiple times in the same process, and you
77
- # want files like spec_helper.rb to be reloaded, be sure to load `load`
78
- # instead of `require`.
79
- #
80
- # #### Parameters
81
- # * +args+ - an array of command-line-supported arguments
82
- # * +err+ - error stream (Default: $stderr)
83
- # * +out+ - output stream (Default: $stdout)
84
- #
85
- # #### Returns
86
- # * +Fixnum+ - exit status code (0/1)
87
- def self.run(args, err=$stderr, out=$stdout)
88
- trap_interrupt
89
- options = ConfigurationOptions.new(args)
90
-
91
- if options.options[:drb]
92
- require 'rspec/core/drb_command_line'
93
- begin
94
- DRbCommandLine.new(options).run(err, out)
95
- rescue DRb::DRbConnError
96
- err.puts "No DRb server is running. Running in local process instead ..."
97
- CommandLine.new(options).run(err, out)
98
- end
99
- else
100
- CommandLine.new(options).run(err, out)
101
- end
102
- ensure
103
- RSpec.reset
104
- end
105
159
  end
106
160
  end
107
161
  end
@@ -7,7 +7,7 @@ module RSpec
7
7
  #
8
8
  # module LoggedInAsAdmin
9
9
  # extend RSpec::Core::SharedContext
10
- # before(:each) do
10
+ # before(:example) do
11
11
  # log_in_as :admin
12
12
  # end
13
13
  # end
@@ -17,25 +17,26 @@ module RSpec
17
17
  # # ...
18
18
  # end
19
19
  module SharedContext
20
- # @api private
20
+ # @private
21
21
  def included(group)
22
22
  __shared_context_recordings.each do |recording|
23
23
  recording.playback_onto(group)
24
24
  end
25
25
  end
26
26
 
27
- # @api private
27
+ # @private
28
28
  def __shared_context_recordings
29
29
  @__shared_context_recordings ||= []
30
30
  end
31
31
 
32
+ # @private
32
33
  Recording = Struct.new(:method_name, :args, :block) do
33
34
  def playback_onto(group)
34
35
  group.__send__(method_name, *args, &block)
35
36
  end
36
37
  end
37
38
 
38
- # @api private
39
+ # @private
39
40
  def self.record(methods)
40
41
  methods.each do |meth|
41
42
  define_method(meth) do |*args, &block|
@@ -44,10 +45,11 @@ module RSpec
44
45
  end
45
46
  end
46
47
 
48
+ # @private
47
49
  record [:describe, :context] + Hooks.instance_methods(false) +
48
50
  MemoizedHelpers::ClassMethods.instance_methods(false)
49
51
  end
50
52
  end
51
-
53
+ # @private
52
54
  SharedContext = Core::SharedContext
53
55
  end
@@ -1,57 +1,77 @@
1
1
  module RSpec
2
2
  module Core
3
+ # Shared example groups let you define common context and/or common
4
+ # examples that you wish to use in multiple example groups.
5
+ #
6
+ # When defined, the shared group block is stored for later evaluation.
7
+ # It can later be included in an example group either explicitly
8
+ # (using `include_examples`, `include_context` or `it_behaves_like`)
9
+ # or implicitly (via matching metadata).
10
+ #
11
+ # Named shared example groups are scoped based on where they are
12
+ # defined. Shared groups defined in an example group are available
13
+ # for inclusion in that example group or any child example groups,
14
+ # but not in any parent or sibling example groups. Shared example
15
+ # groups defined at the top level can be included from any example group.
3
16
  module SharedExampleGroup
4
17
  # @overload shared_examples(name, &block)
5
- # @overload shared_examples(name, tags, &block)
18
+ # @param name [String, Symbol, Module] identifer to use when looking up this shared group
19
+ # @param block The block to be eval'd
20
+ # @overload shared_examples(name, metadata, &block)
21
+ # @param name [String, Symbol, Module] identifer to use when looking up this shared group
22
+ # @param metadata [Array<Symbol>, Hash] metadata to attach to this group; any example group
23
+ # with matching metadata will automatically include this shared example group.
24
+ # @param block The block to be eval'd
25
+ # @overload shared_examples(metadata, &block)
26
+ # @param metadata [Array<Symbol>, Hash] metadata to attach to this group; any example group
27
+ # with matching metadata will automatically include this shared example group.
28
+ # @param block The block to be eval'd
6
29
  #
7
- # Wraps the `block` in a module which can then be included in example
8
- # groups using `include_examples`, `include_context`, or
9
- # `it_behaves_like`.
10
- #
11
- # @param [String] name to match when looking up this shared group
12
- # @param block to be eval'd in a nested example group generated by `it_behaves_like`
30
+ # Stores the block for later use. The block will be evaluated
31
+ # in the context of an example group via `include_examples`,
32
+ # `include_context`, or `it_behaves_like`.
13
33
  #
14
34
  # @example
15
- #
16
35
  # shared_examples "auditable" do
17
36
  # it "stores an audit record on save!" do
18
- # lambda { auditable.save! }.should change(Audit, :count).by(1)
37
+ # expect { auditable.save! }.to change(Audit, :count).by(1)
19
38
  # end
20
39
  # end
21
40
  #
22
- # class Account do
41
+ # describe Account do
23
42
  # it_behaves_like "auditable" do
24
- # def auditable; Account.new; end
43
+ # let(:auditable) { Account.new }
25
44
  # end
26
45
  # end
27
46
  #
28
47
  # @see ExampleGroup.it_behaves_like
29
48
  # @see ExampleGroup.include_examples
30
49
  # @see ExampleGroup.include_context
31
- def shared_examples(*args, &block)
32
- SharedExampleGroup.registry.add_group(self, *args, &block)
33
- end
34
-
35
- alias_method :shared_context, :shared_examples
36
- alias_method :share_examples_for, :shared_examples
37
- alias_method :shared_examples_for, :shared_examples
50
+ def shared_examples(name, *args, &block)
51
+ top_level = self == ExampleGroup
52
+ if top_level && RSpec.thread_local_metadata[:in_example_group]
53
+ raise "Creating isolated shared examples from within a context is " +
54
+ "not allowed. Remove `RSpec.` prefix or move this to a " +
55
+ "top-level scope."
56
+ end
38
57
 
39
- def shared_example_groups
40
- SharedExampleGroup.registry.shared_example_groups_for('main', *ancestors[0..-1])
58
+ RSpec.world.shared_example_group_registry.add(self, name, *args, &block)
41
59
  end
60
+ alias shared_context shared_examples
61
+ alias shared_examples_for shared_examples
42
62
 
63
+ # @api private
64
+ #
65
+ # Shared examples top level DSL
43
66
  module TopLevelDSL
67
+ # @private
44
68
  def self.definitions
45
69
  proc do
46
- def shared_examples(*args, &block)
47
- SharedExampleGroup.registry.add_group('main', *args, &block)
48
- end
49
- alias :shared_context :shared_examples
50
- alias :share_examples_for :shared_examples
51
- alias :shared_examples_for :shared_examples
52
- def shared_example_groups
53
- SharedExampleGroup.registry.shared_example_groups_for('main')
70
+ def shared_examples(name, *args, &block)
71
+ RSpec.world.shared_example_group_registry.add(:main, name, *args, &block)
54
72
  end
73
+ alias shared_context shared_examples
74
+ alias shared_examples_for shared_examples
55
75
  end
56
76
  end
57
77
 
@@ -60,21 +80,25 @@ module RSpec
60
80
  @exposed_globally ||= false
61
81
  end
62
82
 
83
+ # @api private
84
+ #
85
+ # Adds the top level DSL methods to Module and the top level binding
63
86
  def self.expose_globally!
64
87
  return if exposed_globally?
65
88
  Core::DSL.change_global_dsl(&definitions)
66
89
  @exposed_globally = true
67
90
  end
68
91
 
92
+ # @api private
93
+ #
94
+ # Removes the top level DSL methods to Module and the top level binding
69
95
  def self.remove_globally!
70
96
  return unless exposed_globally?
71
97
 
72
98
  Core::DSL.change_global_dsl do
73
99
  undef shared_examples
74
100
  undef shared_context
75
- undef share_examples_for
76
101
  undef shared_examples_for
77
- undef shared_example_groups
78
102
  end
79
103
 
80
104
  @exposed_globally = false
@@ -82,60 +106,51 @@ module RSpec
82
106
 
83
107
  end
84
108
 
85
- def self.registry
86
- @registry ||= Registry.new
87
- end
88
-
89
109
  # @private
90
- #
91
- # Used internally to manage the shared example groups and
92
- # constants. We want to limit the number of methods we add
93
- # to objects we don't own (main and Module) so this allows
94
- # us to have helper methods that don't get added to those
95
- # objects.
96
110
  class Registry
97
- def add_group(source, *args, &block)
98
- ensure_block_has_source_location(block, CallerFilter.first_non_rspec_line)
99
-
100
- if key? args.first
101
- key = args.shift
102
- warn_if_key_taken source, key, block
103
- add_shared_example_group source, key, block
111
+ def add(context, name, *metadata_args, &block)
112
+ ensure_block_has_source_location(block) { CallerFilter.first_non_rspec_line }
113
+
114
+ if valid_name?(name)
115
+ warn_if_key_taken context, name, block
116
+ shared_example_groups[context][name] = block
117
+ else
118
+ metadata_args.unshift name
104
119
  end
105
120
 
106
- unless args.empty?
121
+ unless metadata_args.empty?
107
122
  mod = Module.new
108
123
  (class << mod; self; end).__send__(:define_method, :included) do |host|
109
- host.class_eval(&block)
124
+ host.class_exec(&block)
110
125
  end
111
- RSpec.configuration.include mod, *args
126
+ RSpec.configuration.include mod, *metadata_args
112
127
  end
113
128
  end
114
129
 
115
- def shared_example_groups_for(*sources)
116
- Collection.new(sources, shared_example_groups)
117
- end
118
-
119
- def shared_example_groups
120
- @shared_example_groups ||= Hash.new { |hash, key| hash[key] = Hash.new }
121
- end
130
+ def find(lookup_contexts, name)
131
+ lookup_contexts.each do |context|
132
+ found = shared_example_groups[context][name]
133
+ return found if found
134
+ end
122
135
 
123
- def clear
124
- shared_example_groups.clear
136
+ shared_example_groups[:main][name]
125
137
  end
126
138
 
127
139
  private
128
140
 
129
- def add_shared_example_group(source, key, block)
130
- shared_example_groups[source][key] = block
141
+ def shared_example_groups
142
+ @shared_example_groups ||= Hash.new { |hash, context| hash[context] = {} }
131
143
  end
132
144
 
133
- def key?(candidate)
134
- [String, Symbol, Module].any? { |cls| cls === candidate }
145
+ def valid_name?(candidate)
146
+ case candidate
147
+ when String, Symbol, Module then true
148
+ else false
149
+ end
135
150
  end
136
151
 
137
- def warn_if_key_taken(source, key, new_block)
138
- return unless existing_block = example_block_for(source, key)
152
+ def warn_if_key_taken(context, key, new_block)
153
+ return unless existing_block = shared_example_groups[context][key]
139
154
 
140
155
  RSpec.warn_with <<-WARNING.gsub(/^ +\|/, ''), :call_site => nil
141
156
  |WARNING: Shared example group '#{key}' has been previously defined at:
@@ -150,24 +165,17 @@ module RSpec
150
165
  block.source_location.join ":"
151
166
  end
152
167
 
153
- def example_block_for(source, key)
154
- shared_example_groups[source][key]
155
- end
156
-
157
168
  if Proc.method_defined?(:source_location)
158
- def ensure_block_has_source_location(block, caller_line); end
169
+ def ensure_block_has_source_location(block); end
159
170
  else # for 1.8.7
160
- def ensure_block_has_source_location(block, caller_line)
161
- block.extend Module.new {
162
- define_method :source_location do
163
- caller_line.split(':')
164
- end
165
- }
171
+ def ensure_block_has_source_location(block)
172
+ source_location = yield.split(':')
173
+ block.extend Module.new { define_method(:source_location) { source_location } }
166
174
  end
167
175
  end
168
176
  end
169
177
  end
170
178
  end
171
179
 
172
- instance_eval(&Core::SharedExampleGroup::TopLevelDSL.definitions)
180
+ instance_exec(&Core::SharedExampleGroup::TopLevelDSL.definitions)
173
181
  end