Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion lib/fixture_kit/rspec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ module ClassMethods
def fixture(name = nil, extends: nil, &block)
definition = Definition.new(extends: extends, &block) if block_given?
declaration = ::RSpec.configuration.fixture_kit.register(name || definition, self)
metadata[DECLARATION_METADATA_KEY] = declaration
# Use update_inherited_metadata to set the declaration on this group
# AND propagate to any child groups already created (e.g., shared
# example groups auto-included via `config.include_context` during
# RSpec configuration).
update_inherited_metadata(DECLARATION_METADATA_KEY => declaration)

prepend_before(:context) do
self.class.metadata[DECLARATION_METADATA_KEY].generate
Expand Down
29 changes: 29 additions & 0 deletions spec/dummy/spec/integration/fixture_kit_integration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,26 @@ module FixtureKitIntegrationTimeHelpers
config.include(FixtureKitIntegrationTimeHelpers)
end

# Shared examples auto-included via config.include_context to reproduce the
# ordering issue: RSpec creates the shared group during configuration (before
# the host group's `fixture` call sets metadata), so fixture declarations
# must propagate through runtime metadata inheritance.
RSpec.shared_examples "auto-included shared examples" do
context "inside auto-included shared context" do
let(:shared_user) { User.find_by!(email: "alice@team.test") }

it "can access fixture data through let blocks defined in the host group" do
expect(fixture.alice.email).to eq("alice@team.test")
expect(shared_user).to eq(fixture.alice)
puts "FKIT_ASSERT:SHARED_EXAMPLE_FIXTURE_ACCESS"
end
end
end

RSpec.configure do |config|
config.include_context "auto-included shared examples", :include_shared_fixture_test
end

RSpec.describe "FixtureKit integration" do
describe "fixture preload timing" do
fixture "teams/basic"
Expand Down Expand Up @@ -220,6 +240,15 @@ module FixtureKitIntegrationTimeHelpers
end
end

describe "fixture with auto-included shared examples", :include_shared_fixture_test do
fixture "teams/basic"

it "works in the host group" do
expect(fixture.alice.name).to eq("Alice")
puts "FKIT_ASSERT:SHARED_EXAMPLE_HOST_FIXTURE"
end
end

describe "fixture instance reader without declaration" do
it "raises a helpful error message" do
expect do
Expand Down
7 changes: 7 additions & 0 deletions spec/integration/dummy_app_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,13 @@ def run_dummy_tests
"FKIT_ASSERT:UNDECLARED_FIXTURE_READER"
]

if INTEGRATION_FRAMEWORK == "rspec"
expected_markers += [
"FKIT_ASSERT:SHARED_EXAMPLE_FIXTURE_ACCESS",
"FKIT_ASSERT:SHARED_EXAMPLE_HOST_FIXTURE"
]
end

expected_markers.each do |marker|
expect(output).to include(marker), "Expected marker #{marker.inspect} in output.\nOutput:\n#{output}"
end
Expand Down
4 changes: 4 additions & 0 deletions spec/unit/rspec_entrypoint_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ def build_group(parent_metadata = {})
@fixture_kit_before_context_hook
end

define_singleton_method(:update_inherited_metadata) do |updates|
metadata.update(updates)
end

define_singleton_method(:append_after) do |scope, &block|
raise "Unexpected scope: #{scope}" unless scope == :context

Expand Down