From 3d07cb387b1cae6f97897dfb85512e30f5e888e9 Mon Sep 17 00:00:00 2001 From: Andrew Haines Date: Fri, 18 Jan 2013 17:10:37 +0000 Subject: [PATCH] Prevent leaking view contexts between tests --- lib/draper/test/rspec_integration.rb | 4 ++++ lib/draper/test_case.rb | 20 ++++++++++++++++ spec/dummy/app/views/posts/_post.html.erb | 3 +++ spec/dummy/lib/tasks/test.rake | 16 +++++++------ ...ec_integration_spec.rb => helpers_spec.rb} | 6 +---- .../spec/decorators/post_decorator_spec.rb | 4 ++++ spec/dummy/spec/decorators/spec_type_spec.rb | 7 ++++++ .../spec/decorators/view_context_spec.rb | 22 +++++++++++++++++ spec/dummy/spec/mailers/post_mailer_spec.rb | 4 ++++ .../test/decorators/minitest/helpers_test.rb | 15 ++++++++++++ .../decorators/minitest/spec_type_test.rb} | 12 +++++++--- .../decorators/minitest/view_context_test.rb | 24 +++++++++++++++++++ .../test/decorators/test_unit/helpers_test.rb | 15 ++++++++++++ .../decorators/test_unit/view_context_test.rb | 24 +++++++++++++++++++ spec/dummy/test/minitest_helper.rb | 4 ++++ spec/dummy/test/test_helper.rb | 3 +++ spec/integration/integration_spec.rb | 10 +++++++- 17 files changed, 177 insertions(+), 16 deletions(-) rename spec/dummy/spec/decorators/{rspec_integration_spec.rb => helpers_spec.rb} (74%) create mode 100644 spec/dummy/spec/decorators/spec_type_spec.rb create mode 100644 spec/dummy/spec/decorators/view_context_spec.rb create mode 100644 spec/dummy/test/decorators/minitest/helpers_test.rb rename spec/dummy/{mini_test/mini_test_integration_test.rb => test/decorators/minitest/spec_type_test.rb} (83%) create mode 100644 spec/dummy/test/decorators/minitest/view_context_test.rb create mode 100644 spec/dummy/test/decorators/test_unit/helpers_test.rb create mode 100644 spec/dummy/test/decorators/test_unit/view_context_test.rb create mode 100644 spec/dummy/test/minitest_helper.rb create mode 100644 spec/dummy/test/test_helper.rb diff --git a/lib/draper/test/rspec_integration.rb b/lib/draper/test/rspec_integration.rb index c41c11dc..0a787fe7 100755 --- a/lib/draper/test/rspec_integration.rb +++ b/lib/draper/test/rspec_integration.rb @@ -8,5 +8,9 @@ module DecoratorExampleGroup RSpec.configure do |config| config.include DecoratorExampleGroup, example_group: {file_path: %r{spec/decorators}}, type: :decorator + + [:decorator, :controller, :mailer].each do |type| + config.after(:each, type: type) { Draper::ViewContext.clear! } + end end end diff --git a/lib/draper/test_case.rb b/lib/draper/test_case.rb index eb625cd9..62320e9f 100644 --- a/lib/draper/test_case.rb +++ b/lib/draper/test_case.rb @@ -13,6 +13,13 @@ module Draper end class TestCase < active_support_test_case + module ViewContextTeardown + def teardown + super + Draper::ViewContext.clear! + end + end + module Behavior if defined?(::Devise) require 'draper/test/devise_helper' @@ -29,5 +36,18 @@ module Behavior end include Behavior + include ViewContextTeardown + end +end + +if defined?(ActionController::TestCase) + class ActionController::TestCase + include Draper::TestCase::ViewContextTeardown + end +end + +if defined?(ActionMailer::TestCase) + class ActionMailer::TestCase + include Draper::TestCase::ViewContextTeardown end end diff --git a/spec/dummy/app/views/posts/_post.html.erb b/spec/dummy/app/views/posts/_post.html.erb index 35f25f77..8170f7f1 100644 --- a/spec/dummy/app/views/posts/_post.html.erb +++ b/spec/dummy/app/views/posts/_post.html.erb @@ -2,6 +2,9 @@
Environment:
<%= Rails.env %>
+
Draper view context controller:
+
<%= Draper::ViewContext.current.controller.class %>
+
Posted:
<%= post.posted_date %>
diff --git a/spec/dummy/lib/tasks/test.rake b/spec/dummy/lib/tasks/test.rake index fc5a4fb0..56052a85 100644 --- a/spec/dummy/lib/tasks/test.rake +++ b/spec/dummy/lib/tasks/test.rake @@ -1,14 +1,16 @@ -require 'rspec/core/rake_task' require 'rake/testtask' +require 'rspec/core/rake_task' + +Rake::Task[:test].clear +Rake::TestTask.new :test do |t| + t.libs << "test" + t.pattern = "test/**/*_test.rb" +end -RSpec::Core::RakeTask.new :rspec +RSpec::Core::RakeTask.new :spec RSpec::Core::RakeTask.new :fast_spec do |t| t.pattern = "fast_spec/**/*_spec.rb" end -Rake::TestTask.new :mini_test do |t| - t.test_files = ["mini_test/mini_test_integration_test.rb"] -end - -task :default => [:rspec, :mini_test, :fast_spec] +task :default => [:test, :spec, :fast_spec] diff --git a/spec/dummy/spec/decorators/rspec_integration_spec.rb b/spec/dummy/spec/decorators/helpers_spec.rb similarity index 74% rename from spec/dummy/spec/decorators/rspec_integration_spec.rb rename to spec/dummy/spec/decorators/helpers_spec.rb index 716b07e8..2376626f 100644 --- a/spec/dummy/spec/decorators/rspec_integration_spec.rb +++ b/spec/dummy/spec/decorators/helpers_spec.rb @@ -1,8 +1,4 @@ -describe "A spec in this folder" do - it "is a decorator spec" do - expect(example.metadata[:type]).to be :decorator - end -end +require 'spec_helper' describe "A decorator spec" do it "can access helpers through `helper`" do diff --git a/spec/dummy/spec/decorators/post_decorator_spec.rb b/spec/dummy/spec/decorators/post_decorator_spec.rb index 7ecda5db..7f1b738c 100755 --- a/spec/dummy/spec/decorators/post_decorator_spec.rb +++ b/spec/dummy/spec/decorators/post_decorator_spec.rb @@ -39,4 +39,8 @@ it "serializes overriden attributes" do expect(decorator.serializable_hash["updated_at"]).to be :overridden end + + it "uses a test view context from ApplicationController" do + expect(Draper::ViewContext.current.controller).to be_an ApplicationController + end end diff --git a/spec/dummy/spec/decorators/spec_type_spec.rb b/spec/dummy/spec/decorators/spec_type_spec.rb new file mode 100644 index 00000000..7a98ce7a --- /dev/null +++ b/spec/dummy/spec/decorators/spec_type_spec.rb @@ -0,0 +1,7 @@ +require 'spec_helper' + +describe "A spec in this folder" do + it "is a decorator spec" do + expect(example.metadata[:type]).to be :decorator + end +end diff --git a/spec/dummy/spec/decorators/view_context_spec.rb b/spec/dummy/spec/decorators/view_context_spec.rb new file mode 100644 index 00000000..2ba93a95 --- /dev/null +++ b/spec/dummy/spec/decorators/view_context_spec.rb @@ -0,0 +1,22 @@ +require 'spec_helper' + +def it_does_not_leak_view_context + 2.times do + it "has an independent view context" do + expect(Draper::ViewContext.current).not_to be :leaked + Draper::ViewContext.current = :leaked + end + end +end + +describe "A decorator spec", type: :decorator do + it_does_not_leak_view_context +end + +describe "A controller spec", type: :controller do + it_does_not_leak_view_context +end + +describe "A mailer spec", type: :mailer do + it_does_not_leak_view_context +end diff --git a/spec/dummy/spec/mailers/post_mailer_spec.rb b/spec/dummy/spec/mailers/post_mailer_spec.rb index 3297766f..3d6699ad 100644 --- a/spec/dummy/spec/mailers/post_mailer_spec.rb +++ b/spec/dummy/spec/mailers/post_mailer_spec.rb @@ -25,5 +25,9 @@ it "can use url helpers with an id" do expect(email_body).to have_css "#url_with_id", text: "http://www.example.com:12345/en/posts/#{post.id}" end + + it "uses the correct view context controller" do + expect(email_body).to have_css "#controller", text: "PostMailer" + end end end diff --git a/spec/dummy/test/decorators/minitest/helpers_test.rb b/spec/dummy/test/decorators/minitest/helpers_test.rb new file mode 100644 index 00000000..49b03968 --- /dev/null +++ b/spec/dummy/test/decorators/minitest/helpers_test.rb @@ -0,0 +1,15 @@ +require 'minitest_helper' + +describe "A decorator test" do + it "can access helpers through `helper`" do + assert_equal "

Help!

", helper.content_tag(:p, "Help!") + end + + it "can access helpers through `helpers`" do + assert_equal "

Help!

", helpers.content_tag(:p, "Help!") + end + + it "can access helpers through `h`" do + assert_equal "

Help!

", h.content_tag(:p, "Help!") + end +end diff --git a/spec/dummy/mini_test/mini_test_integration_test.rb b/spec/dummy/test/decorators/minitest/spec_type_test.rb similarity index 83% rename from spec/dummy/mini_test/mini_test_integration_test.rb rename to spec/dummy/test/decorators/minitest/spec_type_test.rb index 0a25ba28..b1710a6c 100644 --- a/spec/dummy/mini_test/mini_test_integration_test.rb +++ b/spec/dummy/test/decorators/minitest/spec_type_test.rb @@ -1,6 +1,4 @@ -require File.expand_path('../../config/environment', __FILE__) -require 'minitest/autorun' -require 'minitest/rails' +require 'minitest_helper' def it_is_a_decorator_test it "is a decorator test" do @@ -33,6 +31,14 @@ def it_is_not_a_decorator_test it_is_a_decorator_test end +describe "Any decorator" do + it_is_a_decorator_test +end + +describe "AnyDecoratorTest" do + it_is_a_decorator_test +end + describe "Any decorator test" do it_is_a_decorator_test end diff --git a/spec/dummy/test/decorators/minitest/view_context_test.rb b/spec/dummy/test/decorators/minitest/view_context_test.rb new file mode 100644 index 00000000..c1df670e --- /dev/null +++ b/spec/dummy/test/decorators/minitest/view_context_test.rb @@ -0,0 +1,24 @@ +require 'minitest_helper' + +def it_does_not_leak_view_context + 2.times do + it "has an independent view context" do + refute_equal :leaked, Draper::ViewContext.current + Draper::ViewContext.current = :leaked + end + end +end + +describe "A decorator test" do + it_does_not_leak_view_context +end + +describe "A controller test" do + tests Class.new(ActionController::Base) + + it_does_not_leak_view_context +end + +describe "A mailer test" do + it_does_not_leak_view_context +end diff --git a/spec/dummy/test/decorators/test_unit/helpers_test.rb b/spec/dummy/test/decorators/test_unit/helpers_test.rb new file mode 100644 index 00000000..52321971 --- /dev/null +++ b/spec/dummy/test/decorators/test_unit/helpers_test.rb @@ -0,0 +1,15 @@ +require 'test_helper' + +class HelpersTest < Draper::TestCase + def test_access_helpers_through_helper + assert_equal "

Help!

", helper.content_tag(:p, "Help!") + end + + def test_access_helpers_through_helpers + assert_equal "

Help!

", helpers.content_tag(:p, "Help!") + end + + def test_access_helpers_through_h + assert_equal "

Help!

", h.content_tag(:p, "Help!") + end +end diff --git a/spec/dummy/test/decorators/test_unit/view_context_test.rb b/spec/dummy/test/decorators/test_unit/view_context_test.rb new file mode 100644 index 00000000..98b71a75 --- /dev/null +++ b/spec/dummy/test/decorators/test_unit/view_context_test.rb @@ -0,0 +1,24 @@ +require 'test_helper' + +def it_does_not_leak_view_context + 2.times do |n| + define_method("test_has_independent_view_context_#{n}") do + refute_equal :leaked, Draper::ViewContext.current + Draper::ViewContext.current = :leaked + end + end +end + +class DecoratorTest < Draper::TestCase + it_does_not_leak_view_context +end + +class ControllerTest < ActionController::TestCase + tests Class.new(ActionController::Base) + + it_does_not_leak_view_context +end + +class MailerTest < ActionMailer::TestCase + it_does_not_leak_view_context +end diff --git a/spec/dummy/test/minitest_helper.rb b/spec/dummy/test/minitest_helper.rb new file mode 100644 index 00000000..2b5462fc --- /dev/null +++ b/spec/dummy/test/minitest_helper.rb @@ -0,0 +1,4 @@ +ENV['RAILS_ENV'] ||= 'test' +require File.expand_path('../../config/environment', __FILE__) +require 'minitest/autorun' +require 'minitest/rails' diff --git a/spec/dummy/test/test_helper.rb b/spec/dummy/test/test_helper.rb new file mode 100644 index 00000000..0f359de4 --- /dev/null +++ b/spec/dummy/test/test_helper.rb @@ -0,0 +1,3 @@ +ENV['RAILS_ENV'] ||= 'test' +require File.expand_path('../../config/environment', __FILE__) +require 'rails/test_help' diff --git a/spec/integration/integration_spec.rb b/spec/integration/integration_spec.rb index b1edfbc7..4da2f5ff 100644 --- a/spec/integration/integration_spec.rb +++ b/spec/integration/integration_spec.rb @@ -3,9 +3,13 @@ require 'support/matchers/have_text' app = DummyApp.new(ENV["RAILS_ENV"]) +spec_types = { + view: ["/posts/1", "PostsController"], + mailer: ["/posts/1/mail", "PostMailer"] +} app.start_server do - {view: "/posts/1", mailer: "/posts/1/mail"}.each do |type, path| + spec_types.each do |type, (path, controller)| page = app.get(path) describe "in a #{type}" do @@ -13,6 +17,10 @@ expect(page).to have_text(app.environment).in("#environment") end + it "uses the correct view context controller" do + expect(page).to have_text(controller).in("#controller") + end + it "can use built-in helpers" do expect(page).to have_text("Once upon a...").in("#truncated") end