Ensure prepare_container works as expected in App (#1185)
We want to ensure that the `prepare_container` block is run at the _last moment_ before the container is marked as `configured!`. With this change, this is now true for both `App` and `Slice`. Before this change, the `prepare_container` block for `App` was being run before the app-specific configuration was applied.
This commit is contained in:
parent
f554c474ac
commit
1705bb19c8
|
@ -219,6 +219,7 @@ module Hanami
|
|||
|
||||
prepare_all
|
||||
|
||||
instance_exec(container, &@prepare_container_block) if @prepare_container_block
|
||||
container.configured!
|
||||
|
||||
@prepared = true
|
||||
|
@ -258,7 +259,6 @@ module Hanami
|
|||
prepare_container_imports
|
||||
prepare_container_providers
|
||||
prepare_autoloader
|
||||
instance_exec(container, &@prepare_container_block) if @prepare_container_block
|
||||
|
||||
prepare_slices
|
||||
end
|
||||
|
|
|
@ -0,0 +1,123 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
RSpec.describe "Container / prepare_container", :app_integration do
|
||||
# (Most of) the examples below make their expectations on a `container_to_prepare`,
|
||||
# which is the container yielded to the `Slice.prepare_container` block _at the moment
|
||||
# it is called_.
|
||||
#
|
||||
# This around hook ensures the examples are run at the right time and container is
|
||||
# available to each.
|
||||
around(in_prepare_container: true) do |example|
|
||||
# Eagerly capture @loaded_features here (see spec/support/app_integration.rb) since
|
||||
# around hooks are run before any before hooks (where we ordinarily capture
|
||||
# @loaded_features), and by invoking `example_group_instance.subject` below, we're
|
||||
# making requires that we want to ensure are properly cleaned between examples.
|
||||
@loaded_features = $LOADED_FEATURES.dup
|
||||
|
||||
slice = example.example_group_instance.subject
|
||||
|
||||
slice.prepare_container do |container|
|
||||
example.example.example_group.let(:container_to_prepare) { container }
|
||||
example.run
|
||||
end
|
||||
|
||||
# The prepare_container block is called when the slice is prepared
|
||||
slice.prepare
|
||||
end
|
||||
|
||||
describe "in app", :in_prepare_container do
|
||||
before :context do
|
||||
with_directory(@dir = make_tmp_directory) do
|
||||
write "config/app.rb", <<~'RUBY'
|
||||
module TestApp
|
||||
class App < Hanami::App
|
||||
end
|
||||
end
|
||||
RUBY
|
||||
|
||||
write "app/.keep", ""
|
||||
end
|
||||
end
|
||||
|
||||
subject {
|
||||
with_directory(@dir) { require "hanami/setup" }
|
||||
Hanami.app
|
||||
}
|
||||
|
||||
it "receives the container for the app" do
|
||||
expect(container_to_prepare).to be TestApp::Container
|
||||
end
|
||||
|
||||
specify "the container has been already configured by the app" do
|
||||
expect(container_to_prepare.config.component_dirs.dir("app")).to be
|
||||
end
|
||||
|
||||
specify "the container is not yet marked as configured" do
|
||||
expect(container_to_prepare).not_to be_configured
|
||||
end
|
||||
|
||||
describe "after app is prepared", in_prepare_container: false do
|
||||
before do
|
||||
subject.prepare_container do |container|
|
||||
container.config.name = :custom_name
|
||||
end
|
||||
end
|
||||
|
||||
it "preserves any container configuration changes made via the block" do
|
||||
expect { subject.prepare }
|
||||
.to change { subject.container.config.name }
|
||||
.to :custom_name
|
||||
|
||||
expect(subject.container).to be_configured
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "in slice", :in_prepare_container do
|
||||
before :context do
|
||||
with_directory(@dir = make_tmp_directory) do
|
||||
write "config/app.rb", <<~'RUBY'
|
||||
module TestApp
|
||||
class App < Hanami::App
|
||||
end
|
||||
end
|
||||
RUBY
|
||||
|
||||
write "slices/main/.keep", ""
|
||||
end
|
||||
end
|
||||
|
||||
subject {
|
||||
with_directory(@dir) { require "hanami/setup" }
|
||||
Hanami.app.register_slice(:main)
|
||||
}
|
||||
|
||||
it "receives the container for the slice" do
|
||||
expect(container_to_prepare).to be Main::Container
|
||||
end
|
||||
|
||||
specify "the container has been already configured by the slice" do
|
||||
expect(container_to_prepare.config.component_dirs.dir("")).to be
|
||||
end
|
||||
|
||||
specify "the container is not yet marked as configured" do
|
||||
expect(container_to_prepare).not_to be_configured
|
||||
end
|
||||
|
||||
describe "after slice is prepared", in_prepare_container: false do
|
||||
before do
|
||||
subject.prepare_container do |container|
|
||||
container.config.name = :custom_name
|
||||
end
|
||||
end
|
||||
|
||||
it "preserves any container configuration changes made via the block" do
|
||||
expect { subject.prepare }
|
||||
.to change { subject.container.config.name }
|
||||
.to :custom_name
|
||||
|
||||
expect(subject.container).to be_configured
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -29,8 +29,10 @@ RSpec.configure do |config|
|
|||
config.include_context "Application integration", :app_integration
|
||||
|
||||
config.before :each, :app_integration do
|
||||
@load_paths = $LOAD_PATH.dup
|
||||
@loaded_features = $LOADED_FEATURES.dup
|
||||
# Conditionally assign these in case they have been assigned earlier for specific
|
||||
# example groups (e.g. container/prepare_container_spec.rb)
|
||||
@load_paths ||= $LOAD_PATH.dup
|
||||
@loaded_features ||= $LOADED_FEATURES.dup
|
||||
end
|
||||
|
||||
config.after :each, :app_integration do
|
||||
|
@ -56,7 +58,7 @@ RSpec.configure do |config|
|
|||
|
||||
$LOAD_PATH.replace(@load_paths)
|
||||
|
||||
# Remove any specific LOADED_FEATURES added over the course of running each example
|
||||
# Remove example-specific LOADED_FEATURES added when running each example
|
||||
new_features_to_keep = ($LOADED_FEATURES - @loaded_features).tap { |feats|
|
||||
feats.delete_if do |path|
|
||||
path =~ %r{hanami/(setup|prepare|boot|application/container/providers)} ||
|
||||
|
|
|
@ -14,20 +14,4 @@ RSpec.describe Hanami::Slice, :app_integration do
|
|||
.to raise_error Hanami::SliceLoadError, /Slice must have a class name/
|
||||
end
|
||||
end
|
||||
|
||||
describe ".prepare_container" do
|
||||
let(:app_modules) { %i[TestApp Slice1 Slice2] }
|
||||
|
||||
it "allows the user to configure the container after defaults settings have been applied" do
|
||||
slice = Hanami.app.register_slice(:slice1).prepare
|
||||
expect(slice.container.config.name).to eq :slice1
|
||||
|
||||
slice = Hanami.app.register_slice(:slice2) {
|
||||
prepare_container do |container|
|
||||
container.config.name = :my_slice
|
||||
end
|
||||
}.prepare
|
||||
expect(slice.container.config.name).to eq :my_slice
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue