Browse files

Fix a `described_class` edge case.

In a case like:

  describe "in some context" do
    # example { described_class }
    describe MyClass do
      example { described_class }
    end
  end

...the value of `described_class` in the inner example group
changed based on whether or not the example in the outer group
was commented out or not. This was due to the fact that
`GroupMetadataHash#described_class` would return the parent
group's `described_class` if the key was present in that
group's metadata hash, but given the fact that `described_class`
is lazily computed and stored, the key would be present in the
parent group's metadata hash if and only if `described_class`
was called on the parent group--which would only be done if
the outer example was defined.

By adding the extra guard against nil, it allows the normal logic
to run to find the example group:

- scan the groups from the outer to the inner
- return the first non-string/non-symbol `describe` arg
  • Loading branch information...
1 parent edaf976 commit 538285b86e2785071539b6cc5432bf9507a89c35 @myronmarston myronmarston committed Jan 6, 2013
Showing with 38 additions and 2 deletions.
  1. +6 −2 lib/rspec/core/metadata.rb
  2. +32 −0 spec/rspec/core/example_group_spec.rb
View
8 lib/rspec/core/metadata.rb
@@ -126,8 +126,12 @@ module GroupMetadataHash
def described_class
container_stack.each do |g|
- return g[:described_class] if g.has_key?(:described_class)
- return g[:describes] if g.has_key?(:describes)
+ [:described_class, :describes].each do |key|
+ if g.has_key?(key)
+ value = g[key]
+ return value unless value.nil?
+ end
+ end
end
container_stack.reverse.each do |g|
View
32 spec/rspec/core/example_group_spec.rb
@@ -332,6 +332,38 @@ def metadata_hash(*args)
expect(group.run).to be_true, "expected examples in group to pass"
end
end
+
+ context "for `describe(SomeClass)` within a `describe 'some string' group" do
+ def define_and_run_group(define_outer_example = false)
+ outer_described_class = inner_described_class = nil
+
+ ExampleGroup.describe("some string") do
+ example { outer_described_class = described_class } if define_outer_example
+
+ describe Array do
+ example { inner_described_class = described_class }
+ end
+ end.run
+
+ return outer_described_class, inner_described_class
+ end
+
+ it "has a `nil` described_class in the outer group" do
+ outer_described_class, _ = define_and_run_group(:define_outer_example)
+ expect(outer_described_class).to be(nil)
+ end
+
+ it "has the inner described class as the described_class of the inner group" do
+ _, inner_described_class = define_and_run_group
+ expect(inner_described_class).to be(Array)
+
+ # This is weird, but in RSpec 2.12 (and before, presumably),
+ # the `described_class` value would be incorrect if there was an
+ # example in the outer group, and correct if there was not one.
+ _, inner_described_class = define_and_run_group(:define_outer_example)
+ expect(inner_described_class).to be(Array)
+ end
+ end
end
describe '#described_class' do

2 comments on commit 538285b

@exviva

👏

@alindeman

Nice. And great commit message.

Please sign in to comment.