Skip to content
This repository was archived by the owner on Nov 30, 2024. It is now read-only.

Commit d753818

Browse files
committed
Fix define_derived_metadata so that it supports cascades.
For example: ``` RSpec.configure do |c| c.define_derived_metadata(:elasticsearch) do |meta| meta[:vcr] = true end c.define_derived_metadata(:vcr) do |meta| meta[:retries] = 2 end end ``` With this configuration, an example or group tagged with `:elasticsearch` should get tagged with `:vcr` as well, which in turn should add `retries: 2` metadata to the example or group. Before this change, this did not work properly, because we did look to see if additional metadata blocks should apply after applying them once.
1 parent d04d4de commit d753818

File tree

3 files changed

+28
-2
lines changed

3 files changed

+28
-2
lines changed

Changelog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ Bug Fixes:
1919
* When defining `let` methods that overwrite an existing method, prevent
2020
a warning being issued by removing the old definition. (Jon Rowe, #2593)
2121
* Prevent warning on Ruby 2.6.0-rc1 (Keiji Yoshimi, #2582)
22+
* Fix `config.define_derived_metadata` so that it supports cascades.
23+
(Myron Marston, #2630).
2224

2325
### 3.8.0 / 2018-08-04
2426
[Full Changelog](http://github.com/rspec/rspec-core/compare/v3.7.1...v3.8.0)

lib/rspec/core/configuration.rb

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1855,8 +1855,18 @@ def when_first_matching_example_defined(*filters)
18551855

18561856
# @private
18571857
def apply_derived_metadata_to(metadata)
1858-
@derived_metadata_blocks.items_for(metadata).each do |block|
1859-
block.call(metadata)
1858+
already_run_blocks = Set.new
1859+
1860+
# We loop and attempt to re-apply metadata blocks to support cascades
1861+
# (e.g. where a derived bit of metadata triggers the application of
1862+
# another piece of derived metadata, etc)
1863+
loop do
1864+
break if @derived_metadata_blocks.items_for(metadata).all? do |block|
1865+
already_run_blocks.include?(block).tap do |skip_block|
1866+
block.call(metadata) unless skip_block
1867+
already_run_blocks << block
1868+
end
1869+
end
18601870
end
18611871
end
18621872

spec/rspec/core/configuration_spec.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1819,6 +1819,20 @@ def exclude?(line)
18191819
expect(group.metadata).to include(:b1_desc => "bar (block 1)", :b2_desc => "bar (block 1) (block 2)")
18201820
end
18211821

1822+
it 'supports cascades of derived metadata, but avoids re-running derived metadata blocks that have already been applied' do
1823+
RSpec.configure do |c|
1824+
c.define_derived_metadata(:foo1) { |m| m[:foo2] = (m[:foo2] || 0) + 1 }
1825+
c.define_derived_metadata(:foo2) { |m| m[:foo3] = (m[:foo3] || 0) + 1 }
1826+
c.define_derived_metadata(:foo3) { |m| m[:foo4] = (m[:foo4] || 0) + 1 }
1827+
end
1828+
1829+
group = RSpec.describe("bar", :foo1 => 1)
1830+
expect(group.metadata).to include(:foo1 => 1, :foo2 => 1, :foo3 => 1, :foo4 => 1)
1831+
1832+
ex = RSpec.describe("My group").example("foo", :foo1 => 1)
1833+
expect(ex.metadata).to include(:foo1 => 1, :foo2 => 1, :foo3 => 1, :foo4 => 1)
1834+
end
1835+
18221836
it "derives metadata before the group or example blocks are eval'd so their logic can depend on the derived metadata" do
18231837
RSpec.configure do |c|
18241838
c.define_derived_metadata(:foo) do |metadata|

0 commit comments

Comments
 (0)