rspec-core 3.5.0.beta1 → 3.5.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 764d595de1ccd035e52340a849aa668815e8dae7
4
- data.tar.gz: f7e933e063ee39c7813b9a9618f19b74174ab569
3
+ metadata.gz: ae10092df64000bc49a31c63ea1e6fb90f8bed34
4
+ data.tar.gz: 34f6ffdfff90d32dbb96fde2fd9a45e1280bfaeb
5
5
  SHA512:
6
- metadata.gz: e18131d908d6c1ab5329e13005261cc07aaabade69dfd9ccb09078ec6c2f7efb43231f229168b9eab2ea2ccdde573c55f42cf7beca42e9e2f8cf107e58873944
7
- data.tar.gz: 8e38f681409c92781111082573df67e2e138670f1e063a24088eb92102943818eef279e33bef02cac8c38aa73d9228a105f4bcfd39963409ddf51e90ccb4af91
6
+ metadata.gz: d58b487bff47a2a7d54c86a91e50ec8dadd2f4c5a5a842557cdaa6a2a575dd1409f612a41161ef1862eb15a71b8d9c60bfb3acfc5aec471e0a7fec14467b53d9
7
+ data.tar.gz: 7e6f624e87c70244933bc521d67d6bed2b3b455556a57aaca8bda715d07a738920414ae179bf432054222507323f002fc2e30a344c999125606672c6dbdccd4f
@@ -1,4 +1,4 @@
1
- __m�^�=ĽYi��¦���i8����E�F/���Ұ">�獈-�7 �okac�8<�Ȁ�\�niNhr�8̤�*F��I���=
2
- �R_Il��Mb*�63Ou�@~.)�D�Ynv_��,nzV��e�}km[����D��� ɫ<��!�G��[���d|:3.��G�e����>�
3
- �u<u8x��j��;�� O8������ �h�H��R�t��#�U� #�|�'~Q�G^c-gS�� iR;�'��D8Q�8����t{�d��g+�<���A�V��?�V
4
- ����?Gh]vX�間��E���$�8��ņ�C���̍z��<�X��P����vTlI��]��VV��M49^�ĝ��;�c]��?�}��u��tV���L+{��T���^潏�Bķ��Ľv�)7;II,��Z�ɤ�3A��
1
+ CS+�0������>;���{t�>զ�Y�`�$Qh5��-���"�{�C�5h�:��*�m��L��^���&�����]�fR4�҄��������g�J܊��S�;b�$6�����hu�F
2
+ 9t����6)KR�$l4Ƈ�O(��+���-B�* ���bE���n��;U�پJX�r`�7jY�+z%?ϸ�&��)��^��i؏]F�R��e?�_��~� �ݽ6�^lki��cK�U����
3
+ s���*Z
4
+ ��0����@�+��uD-�K(-i4N ,ؚJ�b� �2>���a� d�%%�Mnp�vT�>�"Oo_�ڪ�.'���QP�&^w�p���F/f+�/@��<��DM
data.tar.gz.sig CHANGED
Binary file
@@ -1,8 +1,41 @@
1
1
  ### Development
2
2
  [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.5.0.beta1...master)
3
3
 
4
+ Enhancements:
5
+
6
+ * Remove unneeded `:execution_result` example groups metadata, saving a
7
+ bit of memory. (Myron Marston, #2172)
8
+ * Apply hooks registered with `config` to previously defined groups.
9
+ (Myron Marston, #2189)
10
+ * `RSpec::Core::Configuration#reporter` is now public API under semver.
11
+ (Jon Rowe, #2193)
12
+ * Add new `config.when_first_matching_example_defined` hook. (Myron
13
+ Marston, #2175)
14
+
4
15
  ### 3.5.0.beta1 / 2016-02-06
5
- [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.4.2...v3.5.0.beta1)
16
+ [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.4.3...v3.5.0.beta1)
17
+
18
+ ### 3.4.4 / 2016-03-09
19
+ [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.4.3...v3.4.4)
20
+
21
+ Bug Fixes:
22
+
23
+ * Fix `RSpec::Core::RakeTask` so that it works with Rake 11.
24
+ (Travis Grathwell, #2197)
25
+
26
+ ### 3.4.3 / 2016-02-19
27
+ [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.4.2...v3.4.3)
28
+
29
+ Bug Fixes:
30
+
31
+ * Prevent a `TypeError` from occuring when running via the rake task when
32
+ Ruby crashes. (Patrik Wenger, #2161)
33
+ * Only consider example and group declaration lines from a specific file
34
+ when applying line number filtering, instead of considering all
35
+ declaration lines from all spec files. (Myron Marston, #2170)
36
+ * Fix failure snippet extraction so that snippets that contain `do-end` style
37
+ block and end with `end`-only line can be extracted properly.
38
+ (Yuji Nakayama, #2173)
6
39
 
7
40
  ### 3.4.2 / 2016-01-26
8
41
  [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.4.1...v3.4.2)
@@ -83,7 +83,6 @@ module RSpec
83
83
  def self.configuration
84
84
  @configuration ||= RSpec::Core::Configuration.new
85
85
  end
86
- configuration.expose_dsl_globally = true
87
86
 
88
87
  # Yields the global configuration to a block.
89
88
  # @yield [Configuration] global configuration
@@ -178,4 +177,7 @@ module RSpec
178
177
  require MODULES_TO_AUTOLOAD.fetch(name) { return super }
179
178
  ::RSpec.const_get(name)
180
179
  end
180
+
181
+ Core::DSL.expose_globally!
182
+ Core::SharedExampleGroup::TopLevelDSL.expose_globally!
181
183
  end
@@ -343,12 +343,13 @@ module RSpec
343
343
  # @private
344
344
  attr_writer :files_to_run
345
345
  # @private
346
- attr_accessor :filter_manager
346
+ attr_accessor :filter_manager, :world
347
347
  # @private
348
348
  attr_accessor :static_config_filter_manager
349
349
  # @private
350
350
  attr_reader :backtrace_formatter, :ordering_manager, :loaded_spec_files
351
351
 
352
+ # rubocop:disable Metrics/AbcSize
352
353
  def initialize
353
354
  # rubocop:disable Style/GlobalVars
354
355
  @start_time = $_rspec_core_load_started_at || ::RSpec::Core::Time.now
@@ -394,9 +395,11 @@ module RSpec
394
395
  @derived_metadata_blocks = FilterableItemRepository::QueryOptimized.new(:any?)
395
396
  @threadsafe = true
396
397
  @max_displayed_failure_line_count = 10
398
+ @world = World::Null
397
399
 
398
400
  define_built_in_hooks
399
401
  end
402
+ # rubocop:enable Metrics/AbcSize
400
403
 
401
404
  # @private
402
405
  #
@@ -822,7 +825,7 @@ module RSpec
822
825
  end
823
826
  end
824
827
 
825
- # @private
828
+ # @return [RSpec::Core::Reporter] the currently configured reporter
826
829
  def reporter
827
830
  # @reporter_buffer should only ever be set in this method to cover
828
831
  # initialization of @reporter.
@@ -1158,7 +1161,7 @@ module RSpec
1158
1161
  def include(mod, *filters)
1159
1162
  meta = Metadata.build_hash_from(filters, :warn_about_example_group_filtering)
1160
1163
  @include_modules.append(mod, meta)
1161
- configure_existing_groups(mod, meta, :safe_include)
1164
+ on_existing_matching_groups(meta) { |group| safe_include(mod, group) }
1162
1165
  end
1163
1166
 
1164
1167
  # Tells RSpec to extend example groups with `mod`. Methods defined in
@@ -1194,7 +1197,7 @@ module RSpec
1194
1197
  def extend(mod, *filters)
1195
1198
  meta = Metadata.build_hash_from(filters, :warn_about_example_group_filtering)
1196
1199
  @extend_modules.append(mod, meta)
1197
- configure_existing_groups(mod, meta, :safe_extend)
1200
+ on_existing_matching_groups(meta) { |group| safe_extend(mod, group) }
1198
1201
  end
1199
1202
 
1200
1203
  if RSpec::Support::RubyFeatures.module_prepends_supported?
@@ -1233,7 +1236,7 @@ module RSpec
1233
1236
  def prepend(mod, *filters)
1234
1237
  meta = Metadata.build_hash_from(filters, :warn_about_example_group_filtering)
1235
1238
  @prepend_modules.append(mod, meta)
1236
- configure_existing_groups(mod, meta, :safe_prepend)
1239
+ on_existing_matching_groups(meta) { |group| safe_prepend(mod, group) }
1237
1240
  end
1238
1241
  end
1239
1242
 
@@ -1247,21 +1250,6 @@ module RSpec
1247
1250
  configure_group_with group, @prepend_modules, :safe_prepend
1248
1251
  end
1249
1252
 
1250
- # @private
1251
- def configure_group_with(group, module_list, application_method)
1252
- module_list.items_for(group.metadata).each do |mod|
1253
- __send__(application_method, mod, group)
1254
- end
1255
- end
1256
-
1257
- # @private
1258
- def configure_existing_groups(mod, meta, application_method)
1259
- RSpec.world.all_example_groups.each do |group|
1260
- next unless meta.empty? || MetadataFilter.apply?(:any?, meta, group.metadata)
1261
- __send__(application_method, mod, group)
1262
- end
1263
- end
1264
-
1265
1253
  # @private
1266
1254
  #
1267
1255
  # Used internally to extend the singleton class of a single example's
@@ -1281,13 +1269,6 @@ module RSpec
1281
1269
  end
1282
1270
  end
1283
1271
 
1284
- if RSpec::Support::RubyFeatures.module_prepends_supported?
1285
- # @private
1286
- def safe_prepend(mod, host)
1287
- host.__send__(:prepend, mod) unless host < mod
1288
- end
1289
- end
1290
-
1291
1272
  # @private
1292
1273
  def requires=(paths)
1293
1274
  directories = ['lib', default_path].select { |p| File.directory? p }
@@ -1305,31 +1286,6 @@ module RSpec
1305
1286
  Regexp.union(regexes)
1306
1287
  end
1307
1288
 
1308
- # @private
1309
- if RUBY_VERSION.to_f >= 1.9
1310
- # @private
1311
- def safe_include(mod, host)
1312
- host.__send__(:include, mod) unless host < mod
1313
- end
1314
-
1315
- # @private
1316
- def safe_extend(mod, host)
1317
- host.extend(mod) unless host.singleton_class < mod
1318
- end
1319
- else # for 1.8.7
1320
- # :nocov:
1321
- # @private
1322
- def safe_include(mod, host)
1323
- host.__send__(:include, mod) unless host.included_modules.include?(mod)
1324
- end
1325
-
1326
- # @private
1327
- def safe_extend(mod, host)
1328
- host.extend(mod) unless (class << host; self; end).included_modules.include?(mod)
1329
- end
1330
- # :nocov:
1331
- end
1332
-
1333
1289
  # @private
1334
1290
  def configure_mock_framework
1335
1291
  RSpec::Core::ExampleGroup.__send__(:include, mock_framework)
@@ -1352,7 +1308,7 @@ module RSpec
1352
1308
  # in that case, the spec file was loaded by `ruby` and
1353
1309
  # isn't loaded by us here so we only know about it because
1354
1310
  # of an example group being registered in it.
1355
- RSpec.world.registered_example_group_files.each do |f|
1311
+ world.registered_example_group_files.each do |f|
1356
1312
  loaded_spec_files << f # the registered files are already expended absolute paths
1357
1313
  end
1358
1314
 
@@ -1597,6 +1553,41 @@ module RSpec
1597
1553
  @derived_metadata_blocks.append(block, meta)
1598
1554
  end
1599
1555
 
1556
+ # Defines a callback that runs after the first example with matching
1557
+ # metadata is defined. If no examples are defined with matching metadata,
1558
+ # it will not get called at all.
1559
+ #
1560
+ # This can be used to ensure some setup is performed (such as bootstrapping
1561
+ # a DB or loading a specific file that adds significantly to the boot time)
1562
+ # if needed (as indicated by the presence of an example with matching metadata)
1563
+ # but avoided otherwise.
1564
+ #
1565
+ # @example
1566
+ # RSpec.configure do |config|
1567
+ # config.when_first_matching_example_defined(:db) do
1568
+ # # Load a support file that does some heavyweight setup,
1569
+ # # including bootstrapping the DB, but only if we have loaded
1570
+ # # any examples tagged with `:db`.
1571
+ # require 'support/db'
1572
+ # end
1573
+ # end
1574
+ def when_first_matching_example_defined(*filters, &block)
1575
+ specified_meta = Metadata.build_hash_from(filters, :warn_about_example_group_filtering)
1576
+
1577
+ callback = lambda do |example_or_group_meta|
1578
+ # Example groups do not have `:example_group` metadata
1579
+ # (instead they have `:parent_example_group` metadata).
1580
+ return unless example_or_group_meta.key?(:example_group)
1581
+
1582
+ # Ensure the callback only fires once.
1583
+ @derived_metadata_blocks.items_for(specified_meta).delete(callback)
1584
+
1585
+ block.call
1586
+ end
1587
+
1588
+ @derived_metadata_blocks.append(callback, specified_meta)
1589
+ end
1590
+
1600
1591
  # @private
1601
1592
  def apply_derived_metadata_to(metadata)
1602
1593
  @derived_metadata_blocks.items_for(metadata).each do |block|
@@ -1613,9 +1604,13 @@ module RSpec
1613
1604
  # @see #prepend_before
1614
1605
  # @see #after
1615
1606
  # @see #append_after
1616
- def before(*args, &block)
1617
- handle_suite_hook(args, @before_suite_hooks, :push,
1618
- Hooks::BeforeHook, block) || super(*args, &block)
1607
+ def before(scope=nil, *meta, &block)
1608
+ handle_suite_hook(scope, meta) do
1609
+ @before_suite_hooks << Hooks::BeforeHook.new(block, {})
1610
+ end || begin
1611
+ on_existing_matching_groups({}) { |g| g.before(scope, *meta, &block) }
1612
+ super(scope, *meta, &block)
1613
+ end
1619
1614
  end
1620
1615
  alias_method :append_before, :before
1621
1616
 
@@ -1632,9 +1627,13 @@ module RSpec
1632
1627
  # @see #before
1633
1628
  # @see #after
1634
1629
  # @see #append_after
1635
- def prepend_before(*args, &block)
1636
- handle_suite_hook(args, @before_suite_hooks, :unshift,
1637
- Hooks::BeforeHook, block) || super(*args, &block)
1630
+ def prepend_before(scope=nil, *meta, &block)
1631
+ handle_suite_hook(scope, meta) do
1632
+ @before_suite_hooks.unshift Hooks::BeforeHook.new(block, {})
1633
+ end || begin
1634
+ on_existing_matching_groups({}) { |g| g.prepend_before(scope, *meta, &block) }
1635
+ super(scope, *meta, &block)
1636
+ end
1638
1637
  end
1639
1638
 
1640
1639
  # Defines a `after` hook. See {Hooks#after} for full docs.
@@ -1646,9 +1645,13 @@ module RSpec
1646
1645
  # @see #append_after
1647
1646
  # @see #before
1648
1647
  # @see #prepend_before
1649
- def after(*args, &block)
1650
- handle_suite_hook(args, @after_suite_hooks, :unshift,
1651
- Hooks::AfterHook, block) || super(*args, &block)
1648
+ def after(scope=nil, *meta, &block)
1649
+ handle_suite_hook(scope, meta) do
1650
+ @after_suite_hooks.unshift Hooks::AfterHook.new(block, {})
1651
+ end || begin
1652
+ on_existing_matching_groups({}) { |g| g.after(scope, *meta, &block) }
1653
+ super(scope, *meta, &block)
1654
+ end
1652
1655
  end
1653
1656
  alias_method :prepend_after, :after
1654
1657
 
@@ -1665,9 +1668,22 @@ module RSpec
1665
1668
  # @see #append_after
1666
1669
  # @see #before
1667
1670
  # @see #prepend_before
1668
- def append_after(*args, &block)
1669
- handle_suite_hook(args, @after_suite_hooks, :push,
1670
- Hooks::AfterHook, block) || super(*args, &block)
1671
+ def append_after(scope=nil, *meta, &block)
1672
+ handle_suite_hook(scope, meta) do
1673
+ @after_suite_hooks << Hooks::AfterHook.new(block, {})
1674
+ end || begin
1675
+ on_existing_matching_groups({}) { |g| g.append_after(scope, *meta, &block) }
1676
+ super(scope, *meta, &block)
1677
+ end
1678
+ end
1679
+
1680
+ # Registers `block` as an `around` hook.
1681
+ #
1682
+ # See {Hooks#around} for full `around` hook docs.
1683
+ def around(scope=nil, *meta, &block)
1684
+ on_existing_matching_groups({}) { |g| g.around(scope, *meta, &block) }
1685
+
1686
+ super(scope, *meta, &block)
1671
1687
  end
1672
1688
 
1673
1689
  # @private
@@ -1704,11 +1720,10 @@ module RSpec
1704
1720
 
1705
1721
  private
1706
1722
 
1707
- def handle_suite_hook(args, collection, append_or_prepend, hook_type, block)
1708
- scope, meta = *args
1723
+ def handle_suite_hook(scope, meta)
1709
1724
  return nil unless scope == :suite
1710
1725
 
1711
- if meta
1726
+ unless meta.empty?
1712
1727
  # TODO: in RSpec 4, consider raising an error here.
1713
1728
  # We warn only for backwards compatibility.
1714
1729
  RSpec.warn_with "WARNING: `:suite` hooks do not support metadata since " \
@@ -1717,7 +1732,7 @@ module RSpec
1717
1732
  "The metadata you have provided (#{meta.inspect}) will be ignored."
1718
1733
  end
1719
1734
 
1720
- collection.__send__(append_or_prepend, hook_type.new(block, {}))
1735
+ yield
1721
1736
  end
1722
1737
 
1723
1738
  def run_hooks_with(hooks, hook_context)
@@ -1814,7 +1829,7 @@ module RSpec
1814
1829
  end
1815
1830
 
1816
1831
  def assert_no_example_groups_defined(config_option)
1817
- return unless RSpec.world.example_groups.any?
1832
+ return unless world.example_groups.any?
1818
1833
 
1819
1834
  raise MustBeConfiguredBeforeExampleGroupsError.new(
1820
1835
  "RSpec's #{config_option} configuration option must be configured before " \
@@ -1863,6 +1878,44 @@ module RSpec
1863
1878
  @last_run_statuses = nil
1864
1879
  @spec_files_with_failures = nil
1865
1880
  end
1881
+
1882
+ def configure_group_with(group, module_list, application_method)
1883
+ module_list.items_for(group.metadata).each do |mod|
1884
+ __send__(application_method, mod, group)
1885
+ end
1886
+ end
1887
+
1888
+ def on_existing_matching_groups(meta)
1889
+ world.all_example_groups.each do |group|
1890
+ yield group if meta.empty? || MetadataFilter.apply?(:any?, meta, group.metadata)
1891
+ end
1892
+ end
1893
+
1894
+ if RSpec::Support::RubyFeatures.module_prepends_supported?
1895
+ def safe_prepend(mod, host)
1896
+ host.__send__(:prepend, mod) unless host < mod
1897
+ end
1898
+ end
1899
+
1900
+ if RUBY_VERSION.to_f >= 1.9
1901
+ def safe_include(mod, host)
1902
+ host.__send__(:include, mod) unless host < mod
1903
+ end
1904
+
1905
+ def safe_extend(mod, host)
1906
+ host.extend(mod) unless host.singleton_class < mod
1907
+ end
1908
+ else # for 1.8.7
1909
+ # :nocov:
1910
+ def safe_include(mod, host)
1911
+ host.__send__(:include, mod) unless host.included_modules.include?(mod)
1912
+ end
1913
+
1914
+ def safe_extend(mod, host)
1915
+ host.extend(mod) unless (class << host; self; end).included_modules.include?(mod)
1916
+ end
1917
+ # :nocov:
1918
+ end
1866
1919
  end
1867
1920
  # rubocop:enable Metrics/ClassLength
1868
1921
  end
@@ -40,7 +40,9 @@ module RSpec
40
40
  example_group_aliases << name
41
41
 
42
42
  (class << RSpec; self; end).__send__(:define_method, name) do |*args, &example_group_block|
43
- RSpec.world.register RSpec::Core::ExampleGroup.__send__(name, *args, &example_group_block)
43
+ group = RSpec::Core::ExampleGroup.__send__(name, *args, &example_group_block)
44
+ RSpec.world.record(group)
45
+ group
44
46
  end
45
47
 
46
48
  expose_example_group_alias_globally(name) if exposed_globally?
@@ -178,6 +178,16 @@ module RSpec
178
178
  @example_group_class = example_group_class
179
179
  @example_block = example_block
180
180
 
181
+ # Register the example with the group before creating the metadata hash.
182
+ # This is necessary since creating the metadata hash triggers
183
+ # `when_first_matching_example_defined` callbacks, in which users can
184
+ # load RSpec support code which defines hooks. For that to work, the
185
+ # examples and example groups must be registered at the time the
186
+ # support code is called or be defined afterwards.
187
+ # Begin defined beforehand but registered afterwards causes hooks to
188
+ # not be applied where they should.
189
+ example_group_class.examples << self
190
+
181
191
  @metadata = Metadata::ExampleHash.create(
182
192
  @example_group_class.metadata, user_metadata,
183
193
  example_group_class.method(:next_runnable_index_for),
@@ -143,9 +143,7 @@ module RSpec
143
143
  options.update(:skip => RSpec::Core::Pending::NOT_YET_IMPLEMENTED) unless block
144
144
  options.update(extra_options)
145
145
 
146
- example = RSpec::Core::Example.new(self, desc, options, block)
147
- examples << example
148
- example
146
+ RSpec::Core::Example.new(self, desc, options, block)
149
147
  end
150
148
  end
151
149
 
@@ -235,27 +233,27 @@ module RSpec
235
233
  thread_data = RSpec::Support.thread_local_data
236
234
  top_level = self == ExampleGroup
237
235
 
238
- if top_level
239
- if thread_data[:in_example_group]
240
- raise "Creating an isolated context from within a context is " \
241
- "not allowed. Change `RSpec.#{name}` to `#{name}` or " \
242
- "move this to a top-level scope."
236
+ registration_collection =
237
+ if top_level
238
+ if thread_data[:in_example_group]
239
+ raise "Creating an isolated context from within a context is " \
240
+ "not allowed. Change `RSpec.#{name}` to `#{name}` or " \
241
+ "move this to a top-level scope."
242
+ end
243
+
244
+ thread_data[:in_example_group] = true
245
+ RSpec.world.example_groups
246
+ else
247
+ children
243
248
  end
244
249
 
245
- thread_data[:in_example_group] = true
246
- end
247
-
248
250
  begin
249
-
250
251
  description = args.shift
251
252
  combined_metadata = metadata.dup
252
253
  combined_metadata.merge!(args.pop) if args.last.is_a? Hash
253
254
  args << combined_metadata
254
255
 
255
- subclass(self, description, args, &example_group_block).tap do |child|
256
- children << child
257
- end
258
-
256
+ subclass(self, description, args, registration_collection, &example_group_block)
259
257
  ensure
260
258
  thread_data.delete(:in_example_group) if top_level
261
259
  end
@@ -347,7 +345,7 @@ module RSpec
347
345
  @descendant_filtered_examples = nil
348
346
  @_descendants = nil
349
347
  @parent_groups = nil
350
- @declaration_line_numbers = nil
348
+ @declaration_locations = nil
351
349
  end
352
350
 
353
351
  # Adds an example to the example group
@@ -379,9 +377,9 @@ module RSpec
379
377
  # @!endgroup
380
378
 
381
379
  # @private
382
- def self.subclass(parent, description, args, &example_group_block)
380
+ def self.subclass(parent, description, args, registration_collection, &example_group_block)
383
381
  subclass = Class.new(parent)
384
- subclass.set_it_up(description, *args, &example_group_block)
382
+ subclass.set_it_up(description, args, registration_collection, &example_group_block)
385
383
  subclass.module_exec(&example_group_block) if example_group_block
386
384
 
387
385
  # The LetDefinitions module must be included _after_ other modules
@@ -394,7 +392,7 @@ module RSpec
394
392
  end
395
393
 
396
394
  # @private
397
- def self.set_it_up(description, *args, &example_group_block)
395
+ def self.set_it_up(description, args, registration_collection, &example_group_block)
398
396
  # Ruby 1.9 has a bug that can lead to infinite recursion and a
399
397
  # SystemStackError if you include a module in a superclass after
400
398
  # including it in a subclass: https://gist.github.com/845896
@@ -405,6 +403,16 @@ module RSpec
405
403
  # here.
406
404
  ensure_example_groups_are_configured
407
405
 
406
+ # Register the example with the group before creating the metadata hash.
407
+ # This is necessary since creating the metadata hash triggers
408
+ # `when_first_matching_example_defined` callbacks, in which users can
409
+ # load RSpec support code which defines hooks. For that to work, the
410
+ # examples and example groups must be registered at the time the
411
+ # support code is called or be defined afterwards.
412
+ # Begin defined beforehand but registered afterwards causes hooks to
413
+ # not be applied where they should.
414
+ registration_collection << self
415
+
408
416
  user_metadata = Metadata.build_hash_from(args)
409
417
 
410
418
  @metadata = Metadata::ExampleGroupHash.create(
@@ -444,10 +452,19 @@ module RSpec
444
452
  # @private
445
453
  def self.next_runnable_index_for(file)
446
454
  if self == ExampleGroup
447
- RSpec.world.num_example_groups_defined_in(file)
455
+ # We add 1 so the ids start at 1 instead of 0. This is
456
+ # necessary for this branch (but not for the other one)
457
+ # because we register examples and groups with the
458
+ # `children` and `examples` collection BEFORE this
459
+ # method is called as part of metadata hash creation,
460
+ # but the example group is recorded with
461
+ # `RSpec.world.example_group_counts_by_spec_file` AFTER
462
+ # the metadata hash is created and the group is returned
463
+ # to the caller.
464
+ RSpec.world.num_example_groups_defined_in(file) + 1
448
465
  else
449
466
  children.count + examples.count
450
- end + 1
467
+ end
451
468
  end
452
469
 
453
470
  # @private
@@ -613,10 +630,10 @@ module RSpec
613
630
  end
614
631
 
615
632
  # @private
616
- def self.declaration_line_numbers
617
- @declaration_line_numbers ||= [metadata[:line_number]] +
618
- examples.map { |e| e.metadata[:line_number] } +
619
- FlatMap.flat_map(children, &:declaration_line_numbers)
633
+ def self.declaration_locations
634
+ @declaration_locations ||= [Metadata.location_tuple_from(metadata)] +
635
+ examples.map { |e| Metadata.location_tuple_from(e.metadata) } +
636
+ FlatMap.flat_map(children, &:declaration_locations)
620
637
  end
621
638
 
622
639
  # @return [String] the unique id of this example group. Pass
@@ -23,13 +23,6 @@ module RSpec
23
23
  if RSpec::Support::RubyFeatures.ripper_supported?
24
24
  NoExpressionAtLineError = Class.new(StandardError)
25
25
 
26
- PAREN_TOKEN_TYPE_PAIRS = {
27
- :on_lbracket => :on_rbracket,
28
- :on_lparen => :on_rparen,
29
- :on_lbrace => :on_rbrace,
30
- :on_heredoc_beg => :on_heredoc_end
31
- }
32
-
33
26
  attr_reader :source, :beginning_line_number, :max_line_count
34
27
 
35
28
  def self.extract_expression_lines_at(file_path, beginning_line_number, max_line_count=nil)
@@ -64,29 +57,29 @@ module RSpec
64
57
  def line_range_of_expression
65
58
  @line_range_of_expression ||= begin
66
59
  line_range = line_range_of_location_nodes_in_expression
67
- initial_unclosed_parens = unclosed_paren_tokens_in_line_range(line_range)
68
- unclosed_parens = initial_unclosed_parens
60
+ initial_unclosed_tokens = unclosed_tokens_in_line_range(line_range)
61
+ unclosed_tokens = initial_unclosed_tokens
69
62
 
70
- until (initial_unclosed_parens & unclosed_parens).empty?
63
+ until (initial_unclosed_tokens & unclosed_tokens).empty?
71
64
  line_range = (line_range.begin)..(line_range.end + 1)
72
- unclosed_parens = unclosed_paren_tokens_in_line_range(line_range)
65
+ unclosed_tokens = unclosed_tokens_in_line_range(line_range)
73
66
  end
74
67
 
75
68
  line_range
76
69
  end
77
70
  end
78
71
 
79
- def unclosed_paren_tokens_in_line_range(line_range)
72
+ def unclosed_tokens_in_line_range(line_range)
80
73
  tokens = FlatMap.flat_map(line_range) do |line_number|
81
74
  source.tokens_by_line_number[line_number]
82
75
  end
83
76
 
84
77
  tokens.each_with_object([]) do |token, unclosed_tokens|
85
- if PAREN_TOKEN_TYPE_PAIRS.keys.include?(token.type)
78
+ if token.opening?
86
79
  unclosed_tokens << token
87
80
  else
88
81
  index = unclosed_tokens.rindex do |unclosed_token|
89
- PAREN_TOKEN_TYPE_PAIRS[unclosed_token.type] == token.type
82
+ unclosed_token.closed_by?(token)
90
83
  end
91
84
  unclosed_tokens.delete_at(index) if index
92
85
  end
@@ -342,14 +342,7 @@ module RSpec
342
342
  private
343
343
 
344
344
  # @private
345
- class Hook
346
- attr_reader :block, :options
347
-
348
- def initialize(block, options)
349
- @block = block
350
- @options = options
351
- end
352
- end
345
+ Hook = Struct.new(:block, :options)
353
346
 
354
347
  # @private
355
348
  class BeforeHook < Hook
@@ -106,6 +106,11 @@ module RSpec
106
106
  "#{metadata[:rerun_file_path]}[#{metadata[:scoped_id]}]"
107
107
  end
108
108
 
109
+ # @private
110
+ def self.location_tuple_from(metadata)
111
+ [metadata[:absolute_file_path], metadata[:line_number]]
112
+ end
113
+
109
114
  # @private
110
115
  # Used internally to populate metadata hashes with computed keys
111
116
  # managed by RSpec.
@@ -123,7 +128,6 @@ module RSpec
123
128
  def populate
124
129
  ensure_valid_user_keys
125
130
 
126
- metadata[:execution_result] = Example::ExecutionResult.new
127
131
  metadata[:block] = block
128
132
  metadata[:description_args] = description_args
129
133
  metadata[:description] = build_description_from(*metadata[:description_args])
@@ -214,6 +218,7 @@ module RSpec
214
218
  end)
215
219
  group_metadata.update(example_metadata)
216
220
 
221
+ example_metadata[:execution_result] = Example::ExecutionResult.new
217
222
  example_metadata[:example_group] = group_metadata
218
223
  example_metadata[:shared_group_inclusion_backtrace] = SharedExampleGroupInclusionStackFrame.current_backtrace
219
224
  example_metadata.delete(:parent_example_group)
@@ -15,9 +15,9 @@ module RSpec
15
15
  # @private
16
16
  def filter_applies?(key, value, metadata)
17
17
  silence_metadata_example_group_deprecations do
18
- return location_filter_applies?(value, metadata) if key == :locations
19
- return id_filter_applies?(value, metadata) if key == :ids
20
- return filters_apply?(key, value, metadata) if Hash === value
18
+ return location_filter_applies?(value, metadata) if key == :locations
19
+ return id_filter_applies?(value, metadata) if key == :ids
20
+ return filters_apply?(key, value, metadata) if Hash === value
21
21
 
22
22
  return false unless metadata.key?(key)
23
23
  return true if TrueClass === value && !!metadata[key]
@@ -49,13 +49,14 @@ module RSpec
49
49
  end
50
50
 
51
51
  def location_filter_applies?(locations, metadata)
52
- line_numbers = example_group_declaration_lines(locations, metadata)
53
- line_number_filter_applies?(line_numbers, metadata)
54
- end
52
+ Metadata.ascend(metadata).any? do |meta|
53
+ file_path = meta[:absolute_file_path]
54
+ line_num = meta[:line_number]
55
55
 
56
- def line_number_filter_applies?(line_numbers, metadata)
57
- preceding_declaration_lines = line_numbers.map { |n| RSpec.world.preceding_declaration_line(n) }
58
- !(relevant_line_numbers(metadata) & preceding_declaration_lines).empty?
56
+ locations[file_path].any? do |filter_line_num|
57
+ line_num == RSpec.world.preceding_declaration_line(file_path, filter_line_num)
58
+ end
59
+ end
59
60
  end
60
61
 
61
62
  def proc_filter_applies?(key, proc, metadata)
@@ -66,16 +67,6 @@ module RSpec
66
67
  end
67
68
  end
68
69
 
69
- def relevant_line_numbers(metadata)
70
- Metadata.ascend(metadata).map { |meta| meta[:line_number] }
71
- end
72
-
73
- def example_group_declaration_lines(locations, metadata)
74
- FlatMap.flat_map(Metadata.ascend(metadata)) do |meta|
75
- locations[meta[:absolute_file_path]]
76
- end.uniq
77
- end
78
-
79
70
  def filters_apply?(key, value, metadata)
80
71
  subhash = metadata[key]
81
72
  return false unless Hash === subhash || HashImitatable === subhash
@@ -81,14 +81,14 @@ module RSpec
81
81
 
82
82
  return unless fail_on_error
83
83
  $stderr.puts "#{command} failed" if verbose
84
- exit $?.exitstatus
84
+ exit $?.exitstatus || 1
85
85
  end
86
86
 
87
87
  private
88
88
 
89
89
  # @private
90
90
  def define(args, &task_block)
91
- desc "Run RSpec code examples" unless ::Rake.application.last_comment
91
+ desc "Run RSpec code examples" unless ::Rake.application.last_description
92
92
 
93
93
  task name, *args do |_, task_args|
94
94
  RakeFileUtils.__send__(:verbose, verbose) do
@@ -150,19 +150,28 @@ module RSpec
150
150
  end
151
151
 
152
152
  # @private
153
- # rubocop:disable Lint/EnsureReturn
154
153
  def self.running_in_drb?
155
- if defined?(DRb) && DRb.current_server && DRb.current_server.alive?
156
- require 'socket'
157
- require 'uri'
158
- local_ipv4 = IPSocket.getaddress(Socket.gethostname)
159
- local_drb = ["127.0.0.1", "localhost", local_ipv4].any? { |addr| addr == URI(DRb.current_server.uri).host }
160
- end
161
- rescue DRb::DRbServerNotFound
162
- ensure
163
- return local_drb || false
154
+ return false unless defined?(DRb)
155
+
156
+ server = begin
157
+ DRb.current_server
158
+ rescue DRb::DRbServerNotFound
159
+ return false
160
+ end
161
+
162
+ return false unless server && server.alive?
163
+
164
+ require 'socket'
165
+ require 'uri'
166
+
167
+ local_ipv4 = begin
168
+ IPSocket.getaddress(Socket.gethostname)
169
+ rescue SocketError
170
+ return false
171
+ end
172
+
173
+ ["127.0.0.1", "localhost", local_ipv4].any? { |addr| addr == URI(DRb.current_server.uri).host }
164
174
  end
165
- # rubocop:enable Lint/EnsureReturn
166
175
 
167
176
  # @private
168
177
  def self.trap_interrupt
@@ -175,7 +184,7 @@ module RSpec
175
184
  exit!(1)
176
185
  else
177
186
  RSpec.world.wants_to_quit = true
178
- STDERR.puts "\nRSpec is shutting down and will print the summary report... Interrupt again to force quit."
187
+ $stderr.puts "\nRSpec is shutting down and will print the summary report... Interrupt again to force quit."
179
188
  end
180
189
  end
181
190
  end
@@ -6,6 +6,17 @@ module RSpec
6
6
  # @private
7
7
  # A wrapper for Ripper token which is generated with `Ripper.lex`.
8
8
  class Token
9
+ CLOSING_TYPES_BY_OPENING_TYPE = {
10
+ :on_lbracket => :on_rbracket,
11
+ :on_lparen => :on_rparen,
12
+ :on_lbrace => :on_rbrace,
13
+ :on_heredoc_beg => :on_heredoc_end
14
+ }.freeze
15
+
16
+ CLOSING_KEYWORDS_BY_OPENING_KEYWORD = {
17
+ 'do' => 'end'
18
+ }.freeze
19
+
9
20
  attr_reader :token
10
21
 
11
22
  def self.tokens_from_ripper_tokens(ripper_tokens)
@@ -37,6 +48,38 @@ module RSpec
37
48
  def inspect
38
49
  "#<#{self.class} #{type} #{string.inspect}>"
39
50
  end
51
+
52
+ def keyword?
53
+ type == :on_kw
54
+ end
55
+
56
+ def opening?
57
+ opening_delimiter? || opening_keyword?
58
+ end
59
+
60
+ def closed_by?(other)
61
+ closed_by_delimiter?(other) || closed_by_keyword?(other)
62
+ end
63
+
64
+ private
65
+
66
+ def opening_delimiter?
67
+ CLOSING_TYPES_BY_OPENING_TYPE.key?(type)
68
+ end
69
+
70
+ def opening_keyword?
71
+ return false unless keyword?
72
+ CLOSING_KEYWORDS_BY_OPENING_KEYWORD.key?(string)
73
+ end
74
+
75
+ def closed_by_delimiter?(other)
76
+ other.type == CLOSING_TYPES_BY_OPENING_TYPE[type]
77
+ end
78
+
79
+ def closed_by_keyword?(other)
80
+ return false unless other.keyword?
81
+ other.string == CLOSING_KEYWORDS_BY_OPENING_KEYWORD[string]
82
+ end
40
83
  end
41
84
  end
42
85
  end
@@ -3,7 +3,7 @@ module RSpec
3
3
  # Version information for RSpec Core.
4
4
  module Version
5
5
  # Current version of RSpec Core, in semantic versioning format.
6
- STRING = '3.5.0.beta1'
6
+ STRING = '3.5.0.beta2'
7
7
  end
8
8
  end
9
9
  end
@@ -12,6 +12,7 @@ module RSpec
12
12
 
13
13
  def initialize(configuration=RSpec.configuration)
14
14
  @configuration = configuration
15
+ configuration.world = self
15
16
  @example_groups = []
16
17
  @example_group_counts_by_spec_file = Hash.new(0)
17
18
  @filtered_examples = Hash.new do |hash, group|
@@ -47,12 +48,10 @@ module RSpec
47
48
 
48
49
  # @api private
49
50
  #
50
- # Register an example group.
51
- def register(example_group)
51
+ # Records an example group.
52
+ def record(example_group)
52
53
  @configuration.on_example_group_definition_callbacks.each { |block| block.call(example_group) }
53
- example_groups << example_group
54
54
  @example_group_counts_by_spec_file[example_group.metadata[:absolute_file_path]] += 1
55
- example_group
56
55
  end
57
56
 
58
57
  # @private
@@ -96,10 +95,12 @@ module RSpec
96
95
  # @api private
97
96
  #
98
97
  # Find line number of previous declaration.
99
- def preceding_declaration_line(filter_line)
100
- declaration_line_numbers.sort.inject(nil) do |highest_prior_declaration_line, line|
101
- line <= filter_line ? line : highest_prior_declaration_line
98
+ def preceding_declaration_line(absolute_file_name, filter_line)
99
+ line_numbers = descending_declaration_line_numbers_by_file.fetch(absolute_file_name) do
100
+ return nil
102
101
  end
102
+
103
+ line_numbers.find { |num| num <= filter_line }
103
104
  end
104
105
 
105
106
  # @private
@@ -179,8 +180,22 @@ module RSpec
179
180
 
180
181
  private
181
182
 
182
- def declaration_line_numbers
183
- @declaration_line_numbers ||= FlatMap.flat_map(example_groups, &:declaration_line_numbers)
183
+ def descending_declaration_line_numbers_by_file
184
+ @descending_declaration_line_numbers_by_file ||= begin
185
+ declaration_locations = FlatMap.flat_map(example_groups, &:declaration_locations)
186
+ hash_of_arrays = Hash.new { |h, k| h[k] = [] }
187
+
188
+ # TODO: change `inject` to `each_with_object` when we drop 1.8.7 support.
189
+ line_nums_by_file = declaration_locations.inject(hash_of_arrays) do |hash, (file_name, line_number)|
190
+ hash[file_name] << line_number
191
+ hash
192
+ end
193
+
194
+ line_nums_by_file.each_value do |list|
195
+ list.sort!
196
+ list.reverse!
197
+ end
198
+ end
184
199
  end
185
200
 
186
201
  def fail_if_config_and_cli_options_invalid
@@ -192,6 +207,24 @@ module RSpec
192
207
  1 # exit code
193
208
  )
194
209
  end
210
+
211
+ # @private
212
+ # Provides a null implementation for initial use by configuration.
213
+ module Null
214
+ def self.registered_example_group_files
215
+ []
216
+ end
217
+
218
+ # :nocov:
219
+ def self.example_groups
220
+ []
221
+ end
222
+
223
+ def self.all_example_groups
224
+ []
225
+ end
226
+ # :nocov:
227
+ end
195
228
  end
196
229
  end
197
230
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.5.0.beta1
4
+ version: 3.5.0.beta2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steven Baker
@@ -46,7 +46,7 @@ cert_chain:
46
46
  ZsVDj6a7lH3cNqtWXZxrb2wO38qV5AkYj8SQK7Hj3/Yui9myUX3crr+PdetazSqQ
47
47
  F3MdtaDehhjC
48
48
  -----END CERTIFICATE-----
49
- date: 2016-02-06 00:00:00.000000000 Z
49
+ date: 2016-03-10 00:00:00.000000000 Z
50
50
  dependencies:
51
51
  - !ruby/object:Gem::Dependency
52
52
  name: rspec-support
@@ -54,28 +54,14 @@ dependencies:
54
54
  requirements:
55
55
  - - '='
56
56
  - !ruby/object:Gem::Version
57
- version: 3.5.0.beta1
57
+ version: 3.5.0.beta2
58
58
  type: :runtime
59
59
  prerelease: false
60
60
  version_requirements: !ruby/object:Gem::Requirement
61
61
  requirements:
62
62
  - - '='
63
63
  - !ruby/object:Gem::Version
64
- version: 3.5.0.beta1
65
- - !ruby/object:Gem::Dependency
66
- name: rake
67
- requirement: !ruby/object:Gem::Requirement
68
- requirements:
69
- - - "~>"
70
- - !ruby/object:Gem::Version
71
- version: 10.0.0
72
- type: :development
73
- prerelease: false
74
- version_requirements: !ruby/object:Gem::Requirement
75
- requirements:
76
- - - "~>"
77
- - !ruby/object:Gem::Version
78
- version: 10.0.0
64
+ version: 3.5.0.beta2
79
65
  - !ruby/object:Gem::Dependency
80
66
  name: cucumber
81
67
  requirement: !ruby/object:Gem::Requirement
@@ -293,9 +279,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
293
279
  version: 1.3.1
294
280
  requirements: []
295
281
  rubyforge_project:
296
- rubygems_version: 2.4.5.1
282
+ rubygems_version: 2.5.1
297
283
  signing_key:
298
284
  specification_version: 4
299
- summary: rspec-core-3.5.0.beta1
285
+ summary: rspec-core-3.5.0.beta2
300
286
  test_files: []
301
287
  has_rdoc:
metadata.gz.sig CHANGED
Binary file