From 5c1edde743ec4f16d823f4eeadf304e5d93c733e Mon Sep 17 00:00:00 2001 From: fugufish Date: Mon, 11 Sep 2023 15:52:19 -0600 Subject: [PATCH 01/11] This updates test_helpers.rb to support Devise tests by ensuring the `@request` instance variable is set before devise runs its setup block. --- lib/view_component/test_helpers.rb | 36 +++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/lib/view_component/test_helpers.rb b/lib/view_component/test_helpers.rb index 1cb733451..18466e47f 100644 --- a/lib/view_component/test_helpers.rb +++ b/lib/view_component/test_helpers.rb @@ -21,13 +21,27 @@ def refute_component_rendered if ENV["DEBUG"] warn( "WARNING in `ViewComponent::TestHelpers`: Add `capybara` " \ - "to Gemfile to use Capybara assertions." + "to Gemfile to use Capybara assertions." ) end # :nocov: end + def self.included(base) + if defined?(Devise::Test::ControllerHelpers) + # the `@request` instance variable is used by Devise::Test::ControllerHelpers and must + # be in a `setup` block before including `Devise::Test::ControllerHelpers` + base.instance_eval do + setup do + @request = __vc_render_preview_controller.request + end + end + + base.include(Devise::Test::ControllerHelpers) + end + end + # Returns the result of a render_inline call. # # @return [ActionView::OutputBuffer] @@ -75,7 +89,7 @@ def render_inline(component, **args, &block) # @param params [Hash] Parameters to be passed to the preview. # @return [Nokogiri::HTML] def render_preview(name, from: __vc_test_helpers_preview_class, params: {}) - previews_controller = __vc_test_helpers_build_controller(Rails.application.config.view_component.preview_controller.constantize) + previews_controller = __vc_render_preview_controller # From what I can tell, it's not possible to overwrite all request parameters # at once, so we set them individually here. @@ -108,6 +122,7 @@ def render_in_view_context(*args, &block) @rendered_content = vc_test_controller.view_context.instance_exec(*args, &block) Nokogiri::HTML.fragment(@rendered_content) end + ruby2_keywords(:render_in_view_context) if respond_to?(:ruby2_keywords, true) # Set the Action Pack request variant for the given block: @@ -178,7 +193,7 @@ def with_request_url(path, host: nil) vc_test_request.path_info = path vc_test_request.path_parameters = Rails.application.routes.recognize_path_with_request(vc_test_request, path, {}) vc_test_request.set_header("action_dispatch.request.query_parameters", - Rack::Utils.parse_nested_query(query).with_indifferent_access) + Rack::Utils.parse_nested_query(query).with_indifferent_access) vc_test_request.set_header(Rack::QUERY_STRING, query) yield ensure @@ -226,6 +241,7 @@ def vc_test_request end # Note: We prefix private methods here to prevent collisions in consumer's tests. + private def __vc_test_helpers_build_controller(klass) @@ -234,15 +250,19 @@ def __vc_test_helpers_build_controller(klass) def __vc_test_helpers_preview_class result = if respond_to?(:described_class) - raise "`render_preview` expected a described_class, but it is nil." if described_class.nil? + raise "`render_preview` expected a described_class, but it is nil." if described_class.nil? - "#{described_class}Preview" - else - self.class.name.gsub("Test", "Preview") - end + "#{described_class}Preview" + else + self.class.name.gsub("Test", "Preview") + end result = result.constantize rescue NameError raise NameError, "`render_preview` expected to find #{result}, but it does not exist." end + + def __vc_render_preview_controller + @vc_render_preview_controller ||= __vc_test_helpers_build_controller(Rails.application.config.view_component.preview_controller.constantize) + end end end From d3ad78f29c225f000746321345e9e56d55a7d8c5 Mon Sep 17 00:00:00 2001 From: fugufish Date: Mon, 11 Sep 2023 16:04:24 -0600 Subject: [PATCH 02/11] fix silly indentation changes --- lib/view_component/test_helpers.rb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/view_component/test_helpers.rb b/lib/view_component/test_helpers.rb index 18466e47f..334f68d36 100644 --- a/lib/view_component/test_helpers.rb +++ b/lib/view_component/test_helpers.rb @@ -117,9 +117,9 @@ def render_preview(name, from: __vc_test_helpers_preview_class, params: {}) # # assert_text("Hello, World!") # ``` - def render_in_view_context(*args, &block) + def render_in_view_context(*, &block) @page = nil - @rendered_content = vc_test_controller.view_context.instance_exec(*args, &block) + @rendered_content = vc_test_controller.view_context.instance_exec(*, &block) Nokogiri::HTML.fragment(@rendered_content) end @@ -193,7 +193,7 @@ def with_request_url(path, host: nil) vc_test_request.path_info = path vc_test_request.path_parameters = Rails.application.routes.recognize_path_with_request(vc_test_request, path, {}) vc_test_request.set_header("action_dispatch.request.query_parameters", - Rack::Utils.parse_nested_query(query).with_indifferent_access) + Rack::Utils.parse_nested_query(query).with_indifferent_access) vc_test_request.set_header(Rack::QUERY_STRING, query) yield ensure @@ -250,12 +250,12 @@ def __vc_test_helpers_build_controller(klass) def __vc_test_helpers_preview_class result = if respond_to?(:described_class) - raise "`render_preview` expected a described_class, but it is nil." if described_class.nil? + raise "`render_preview` expected a described_class, but it is nil." if described_class.nil? - "#{described_class}Preview" - else - self.class.name.gsub("Test", "Preview") - end + "#{described_class}Preview" + else + self.class.name.gsub("Test", "Preview") + end result = result.constantize rescue NameError raise NameError, "`render_preview` expected to find #{result}, but it does not exist." From 73281efc699e7808e8f3382fb1ca42fc0361e71f Mon Sep 17 00:00:00 2001 From: fugufish Date: Mon, 11 Sep 2023 16:06:42 -0600 Subject: [PATCH 03/11] update changelog --- docs/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 5611bd3f1..f7cadc7b7 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -10,6 +10,10 @@ nav_order: 5 ## main +* Add support for `Devise::Test::ControllerHelpers` by resolving `NoMethodError: undefined method env for nil:NilClass` + + *fugufish* + * Refer to `helpers` in `NameError` message in development and test environments. *Simon Fish* From 94dd746f761da600719e52cd610b3ba869f45afd Mon Sep 17 00:00:00 2001 From: fugufish Date: Mon, 11 Sep 2023 18:08:39 -0600 Subject: [PATCH 04/11] revert autoformat change --- lib/view_component/test_helpers.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/view_component/test_helpers.rb b/lib/view_component/test_helpers.rb index 334f68d36..5124018d7 100644 --- a/lib/view_component/test_helpers.rb +++ b/lib/view_component/test_helpers.rb @@ -117,9 +117,9 @@ def render_preview(name, from: __vc_test_helpers_preview_class, params: {}) # # assert_text("Hello, World!") # ``` - def render_in_view_context(*, &block) + def render_in_view_context(*args, &block) @page = nil - @rendered_content = vc_test_controller.view_context.instance_exec(*, &block) + @rendered_content = vc_test_controller.view_context.instance_exec(*args, &block) Nokogiri::HTML.fragment(@rendered_content) end From 57b562fab2b17ab3c37da6c3a1b6a5b273810fc1 Mon Sep 17 00:00:00 2001 From: fugufish Date: Mon, 11 Sep 2023 18:19:33 -0600 Subject: [PATCH 05/11] remove include --- lib/view_component/test_helpers.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/view_component/test_helpers.rb b/lib/view_component/test_helpers.rb index 5124018d7..245e1281e 100644 --- a/lib/view_component/test_helpers.rb +++ b/lib/view_component/test_helpers.rb @@ -37,8 +37,6 @@ def self.included(base) @request = __vc_render_preview_controller.request end end - - base.include(Devise::Test::ControllerHelpers) end end From 2fa7ada68d72ff1abc71356327db9b482d32cd1c Mon Sep 17 00:00:00 2001 From: fugufish Date: Mon, 11 Sep 2023 18:28:17 -0600 Subject: [PATCH 06/11] better method of handling devise request --- docs/guide/testing.md | 11 +++++++++++ lib/view_component/test_helpers.rb | 22 ++-------------------- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/docs/guide/testing.md b/docs/guide/testing.md index ddcce5815..f86703245 100644 --- a/docs/guide/testing.md +++ b/docs/guide/testing.md @@ -164,6 +164,17 @@ class ExampleComponentTest < ViewComponent::TestCase end ``` +## Testing with Devise + +Testing with Devise reqiures you include `Devise::Test::ControllerHelpers` in the `ViewComponent::TestCase` class. This +is typically done by adding the following to `test/test_helper.rb`: + +```ruby +class ViewComponent::TestCase + include Devise::Test::ControllerHelpers +end +``` + ## Setting `request.path_parameters` Since 2.31.0 diff --git a/lib/view_component/test_helpers.rb b/lib/view_component/test_helpers.rb index 245e1281e..1cb733451 100644 --- a/lib/view_component/test_helpers.rb +++ b/lib/view_component/test_helpers.rb @@ -21,25 +21,13 @@ def refute_component_rendered if ENV["DEBUG"] warn( "WARNING in `ViewComponent::TestHelpers`: Add `capybara` " \ - "to Gemfile to use Capybara assertions." + "to Gemfile to use Capybara assertions." ) end # :nocov: end - def self.included(base) - if defined?(Devise::Test::ControllerHelpers) - # the `@request` instance variable is used by Devise::Test::ControllerHelpers and must - # be in a `setup` block before including `Devise::Test::ControllerHelpers` - base.instance_eval do - setup do - @request = __vc_render_preview_controller.request - end - end - end - end - # Returns the result of a render_inline call. # # @return [ActionView::OutputBuffer] @@ -87,7 +75,7 @@ def render_inline(component, **args, &block) # @param params [Hash] Parameters to be passed to the preview. # @return [Nokogiri::HTML] def render_preview(name, from: __vc_test_helpers_preview_class, params: {}) - previews_controller = __vc_render_preview_controller + previews_controller = __vc_test_helpers_build_controller(Rails.application.config.view_component.preview_controller.constantize) # From what I can tell, it's not possible to overwrite all request parameters # at once, so we set them individually here. @@ -120,7 +108,6 @@ def render_in_view_context(*args, &block) @rendered_content = vc_test_controller.view_context.instance_exec(*args, &block) Nokogiri::HTML.fragment(@rendered_content) end - ruby2_keywords(:render_in_view_context) if respond_to?(:ruby2_keywords, true) # Set the Action Pack request variant for the given block: @@ -239,7 +226,6 @@ def vc_test_request end # Note: We prefix private methods here to prevent collisions in consumer's tests. - private def __vc_test_helpers_build_controller(klass) @@ -258,9 +244,5 @@ def __vc_test_helpers_preview_class rescue NameError raise NameError, "`render_preview` expected to find #{result}, but it does not exist." end - - def __vc_render_preview_controller - @vc_render_preview_controller ||= __vc_test_helpers_build_controller(Rails.application.config.view_component.preview_controller.constantize) - end end end From b7e0c99fa881899f474501ead52248bb52230d0c Mon Sep 17 00:00:00 2001 From: fugufish Date: Mon, 11 Sep 2023 18:50:11 -0600 Subject: [PATCH 07/11] better way of handling devise --- lib/view_component/test_helpers.rb | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/view_component/test_helpers.rb b/lib/view_component/test_helpers.rb index 1cb733451..c8b952aff 100644 --- a/lib/view_component/test_helpers.rb +++ b/lib/view_component/test_helpers.rb @@ -75,7 +75,7 @@ def render_inline(component, **args, &block) # @param params [Hash] Parameters to be passed to the preview. # @return [Nokogiri::HTML] def render_preview(name, from: __vc_test_helpers_preview_class, params: {}) - previews_controller = __vc_test_helpers_build_controller(Rails.application.config.view_component.preview_controller.constantize) + previews_controller = __vc_render_preview_controller # From what I can tell, it's not possible to overwrite all request parameters # at once, so we set them individually here. @@ -103,9 +103,9 @@ def render_preview(name, from: __vc_test_helpers_preview_class, params: {}) # # assert_text("Hello, World!") # ``` - def render_in_view_context(*args, &block) + def render_in_view_context(*, &block) @page = nil - @rendered_content = vc_test_controller.view_context.instance_exec(*args, &block) + @rendered_content = vc_test_controller.view_context.instance_exec(*, &block) Nokogiri::HTML.fragment(@rendered_content) end ruby2_keywords(:render_in_view_context) if respond_to?(:ruby2_keywords, true) @@ -225,6 +225,11 @@ def vc_test_request end end + def before_setup + @request = __vc_render_preview_controller.request + super + end + # Note: We prefix private methods here to prevent collisions in consumer's tests. private @@ -244,5 +249,9 @@ def __vc_test_helpers_preview_class rescue NameError raise NameError, "`render_preview` expected to find #{result}, but it does not exist." end + + def __vc_render_preview_controller + @vc_render_preview_controller ||= __vc_test_helpers_build_controller(Rails.application.config.view_component.preview_controller.constantize) + end end end From 0041fb466f6ade03f09f1b95f3d3da0325ef1ea1 Mon Sep 17 00:00:00 2001 From: fugufish Date: Mon, 11 Sep 2023 19:11:37 -0600 Subject: [PATCH 08/11] revert formatting artifact --- lib/view_component/test_helpers.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/view_component/test_helpers.rb b/lib/view_component/test_helpers.rb index c8b952aff..62ecd8f52 100644 --- a/lib/view_component/test_helpers.rb +++ b/lib/view_component/test_helpers.rb @@ -103,9 +103,9 @@ def render_preview(name, from: __vc_test_helpers_preview_class, params: {}) # # assert_text("Hello, World!") # ``` - def render_in_view_context(*, &block) + def render_in_view_context(*args, &block) @page = nil - @rendered_content = vc_test_controller.view_context.instance_exec(*, &block) + @rendered_content = vc_test_controller.view_context.instance_exec(*args, &block) Nokogiri::HTML.fragment(@rendered_content) end ruby2_keywords(:render_in_view_context) if respond_to?(:ruby2_keywords, true) From 633e682b7f9fb3453456be2819a1a95775d63197 Mon Sep 17 00:00:00 2001 From: Jarod Reid Date: Tue, 12 Sep 2023 06:49:54 -0600 Subject: [PATCH 09/11] Update docs/guide/testing.md Co-authored-by: Hans Lemuet --- docs/guide/testing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guide/testing.md b/docs/guide/testing.md index f86703245..e57dbec4c 100644 --- a/docs/guide/testing.md +++ b/docs/guide/testing.md @@ -166,7 +166,7 @@ end ## Testing with Devise -Testing with Devise reqiures you include `Devise::Test::ControllerHelpers` in the `ViewComponent::TestCase` class. This +Testing with Devise requires you include `Devise::Test::ControllerHelpers` in the `ViewComponent::TestCase` class. This is typically done by adding the following to `test/test_helper.rb`: ```ruby From f24369af54e472300330e21de57924b99572d205 Mon Sep 17 00:00:00 2001 From: Jarod Reid Date: Tue, 12 Sep 2023 10:32:04 -0600 Subject: [PATCH 10/11] Update docs/guide/testing.md Co-authored-by: Blake Williams --- docs/guide/testing.md | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/docs/guide/testing.md b/docs/guide/testing.md index e57dbec4c..ddcce5815 100644 --- a/docs/guide/testing.md +++ b/docs/guide/testing.md @@ -164,17 +164,6 @@ class ExampleComponentTest < ViewComponent::TestCase end ``` -## Testing with Devise - -Testing with Devise requires you include `Devise::Test::ControllerHelpers` in the `ViewComponent::TestCase` class. This -is typically done by adding the following to `test/test_helper.rb`: - -```ruby -class ViewComponent::TestCase - include Devise::Test::ControllerHelpers -end -``` - ## Setting `request.path_parameters` Since 2.31.0 From 41e1169393d19c1b6b118af8570a40aa6ed99f7f Mon Sep 17 00:00:00 2001 From: fugufish Date: Tue, 12 Sep 2023 13:01:50 -0600 Subject: [PATCH 11/11] clear the @vc_render_preview_controller after each test run --- lib/view_component/test_helpers.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/view_component/test_helpers.rb b/lib/view_component/test_helpers.rb index 62ecd8f52..e450b5cbc 100644 --- a/lib/view_component/test_helpers.rb +++ b/lib/view_component/test_helpers.rb @@ -230,6 +230,11 @@ def before_setup super end + def teardown + super + @vc_render_preview_controller = nil + end + # Note: We prefix private methods here to prevent collisions in consumer's tests. private