Skip to content

Commit

Permalink
Prevent stub_template from leaking between view specs
Browse files Browse the repository at this point in the history
  • Loading branch information
JonRowe committed Nov 21, 2023
1 parent 6c89ad4 commit 9b80d52
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 14 deletions.
1 change: 1 addition & 0 deletions example_app_generator/app/views/_example.html.erb
@@ -0,0 +1 @@
TEMPLATE_HTML
2 changes: 2 additions & 0 deletions example_app_generator/generate_stuff.rb
Expand Up @@ -14,10 +14,12 @@ def setup_tasks

def final_tasks
copy_file 'spec/verify_active_record_spec.rb'
copy_file 'app/views/_example.html.erb'
copy_file 'app/views/foo.html'
copy_file 'app/views/some_templates/bar.html'
copy_file 'spec/verify_custom_renderers_spec.rb'
copy_file 'spec/verify_fixture_warning_spec.rb'
copy_file 'spec/verify_view_path_stub_spec.rb'
run('bin/rake db:migrate')
end

Expand Down
17 changes: 17 additions & 0 deletions example_app_generator/spec/verify_view_path_stub_spec.rb
@@ -0,0 +1,17 @@
require 'rails_helper'

RSpec.describe "verify view path doesnt leak stubs between examples", type: :view, order: :defined do
subject(:html) do
render partial: "example"
rendered
end

it "renders the stub template" do
stub_template("_example.html.erb" => "STUB_HTML")
expect(html).to include("STUB_HTML")
end

it "renders the file template" do
expect(html).to include("TEMPLATE_HTML")
end
end
2 changes: 1 addition & 1 deletion lib/rspec/rails/example/view_example_group.rb
Expand Up @@ -91,7 +91,7 @@ def view
#
# stub_template("widgets/_widget.html.erb" => "This content.")
def stub_template(hash)
view.view_paths.send(:initialize_copy, ActionView::PathSet.new([StubResolverCache.resolver_for(hash)] + view.view_paths.paths))
controller.prepend_view_path(StubResolverCache.resolver_for(hash))
end
else
# Simulates the presence of a template on the file system by adding a
Expand Down
58 changes: 45 additions & 13 deletions spec/rspec/rails/example/view_example_group_spec.rb
Expand Up @@ -280,33 +280,65 @@ def _view; end

describe '#stub_template' do
let(:view_spec_group) do
Class.new do
include ViewExampleGroup::ExampleMethods
def _view
@_view ||= Struct.new(:view_paths).new(ActionView::PathSet.new(['some-path']))
end
RSpec.describe "a view spec" do
include ::RSpec::Rails::ViewExampleGroup
end
end

it 'prepends an ActionView::FixtureResolver to the view path' do
view_spec = view_spec_group.new
view_spec.stub_template('some_path/some_template' => 'stubbed-contents')
result = :not_loaded

result = view_spec.view.view_paths.first
view_spec_group.specify do
stub_template('some_path/some_template' => 'stubbed-contents')
result = view.view_paths.first
end
view_spec_group.run

expect(result).to be_instance_of(ActionView::FixtureResolver)
data = result.respond_to?(:data) ? result.data : result.hash
expect(data).to eq('some_path/some_template' => 'stubbed-contents')
end

it 'caches FixtureResolver instances between examples' do
example_one_view_paths = :not_set
example_two_view_paths = :not_set

view_spec_group.specify do
stub_template('some_path/some_template' => 'stubbed-contents')
example_one_view_paths = view.view_paths
end
view_spec_group.specify do
stub_template('some_path/some_template' => 'stubbed-contents')
example_two_view_paths = view.view_paths
end
view_spec_group.run

expect(example_one_view_paths.first).to eq(example_two_view_paths.first)
end

it 'caches FixtureResolver instances between example groups' do
view_spec_one = view_spec_group.new
view_spec_two = view_spec_group.new
example_one_view_paths = :not_set
example_two_view_paths = :not_set

view_spec_one.stub_template('some_path/some_template' => 'stubbed-contents')
view_spec_two.stub_template('some_path/some_template' => 'stubbed-contents')
RSpec.describe "a view spec" do
include ::RSpec::Rails::ViewExampleGroup

specify do
stub_template('some_path/some_template' => 'stubbed-contents')
example_one_view_paths = view.view_paths
end
end.run

RSpec.describe "another view spec" do
include ::RSpec::Rails::ViewExampleGroup

specify do
stub_template('some_path/some_template' => 'stubbed-contents')
example_two_view_paths = view.view_paths
end
end.run

expect(view_spec_one.view.view_paths.first).to eq(view_spec_two.view.view_paths.first)
expect(example_one_view_paths.first).to eq(example_two_view_paths.first)
end
end
end
Expand Down

0 comments on commit 9b80d52

Please sign in to comment.