Skip to content

Commit

Permalink
Fix helpers not reloading in previews (#1075)
Browse files Browse the repository at this point in the history
  • Loading branch information
jdelStrother authored May 15, 2023
1 parent 16bd042 commit 18f9781
Show file tree
Hide file tree
Showing 14 changed files with 123 additions and 25 deletions.
6 changes: 4 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,12 @@ jobs:
run: |
bundle config path vendor/bundle
bundle update
bundle exec rake test spec
# Code-reloading isn't compatible with simplecov, so we need to run once
# to collect coverage, and again to test reloads.
MEASURE_COVERAGE=true bundle exec rake test spec
ENABLE_RELOADING=true bundle exec rake test spec
env:
RAISE_ON_WARNING: 1
MEASURE_COVERAGE: true
RAILS_VERSION: ${{ matrix.rails_version }}
CAPTURE_PATCH_ENABLED: ${{ matrix.mode == 'capture_patch_enabled' && 'true' || 'false' }}
- name: Upload coverage results
Expand Down
4 changes: 4 additions & 0 deletions app/controllers/concerns/view_component/preview_actions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ module PreviewActions
before_action :require_local!, unless: :show_previews?

content_security_policy(false) if respond_to?(:content_security_policy)

# Including helpers here ensures that we're loading the
# latest version of helpers if code-reloading is enabled
helper :all if include_all_helpers
end

def index
Expand Down
10 changes: 7 additions & 3 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,21 @@ nav_order: 5

## main

* Fix helpers not reloading in development.

*Jonathan del Strother*

* Add `SECURITY.md`.

*Joel Hawksley*
*Joel Hawksley*

* Add Ophelos to list of companies using ViewComponent.

*Graham Rogers*
*Graham Rogers*

* Add FlightLogger to list of companies using ViewComponent.

*Joseph Carpenter*
*Joseph Carpenter*

### v3.0.0

Expand Down
2 changes: 1 addition & 1 deletion lib/view_component/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class << self

# Returns the current config.
#
# @return [ViewComponent::Config]
# @return [ActiveSupport::OrderedOptions]
def config
@config ||= ActiveSupport::OrderedOptions.new
end
Expand Down
10 changes: 5 additions & 5 deletions test/sandbox/app/controllers/default_form_builder_controller.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# frozen_string_literal: true

class OtherFormBuilder < ActionView::Helpers::FormBuilder
def text_field(*)
"changed by default form builder"
class DefaultFormBuilderController < ActionController::Base
class OtherFormBuilder < ActionView::Helpers::FormBuilder
def text_field(*)
"changed by default form builder"
end
end
end

class DefaultFormBuilderController < ActionController::Base
default_form_builder OtherFormBuilder
end
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ def controller_inline_render_component
render_component(ControllerInlineComponent.new(message: "bar"))
end

def helpers_proxy_component
render(plain: render_to_string(HelpersProxyComponent.new))
end

def controller_to_string_render_component
render(plain: render_component_to_string(ControllerInlineComponent.new(message: "bar")))
end
Expand Down
5 changes: 4 additions & 1 deletion test/sandbox/config/environments/test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
# test suite. You never need to work with it otherwise. Remember that
# your test database is "scratch space" for the test suite and is wiped
# and recreated between test runs. Don't rely on the data there!
config.cache_classes = true

# `cache_classes=false` is necessary to test code-reloading for people using VC in development.
# However, it's incompatible with collecting simplecov coverage reports.
config.cache_classes = !ENV["ENABLE_RELOADING"]

# Show full error reports and disable caching
config.consider_all_requests_local = true
Expand Down
1 change: 1 addition & 0 deletions test/sandbox/config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,5 @@
constraints(lambda { |request| request.env["warden"].authenticate! }) do
get :constraints_with_env, to: "integration_examples#index"
end
get :helpers_proxy_component, to: "integration_examples#helpers_proxy_component"
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true

class HelpersProxyComponentPreview < ViewComponent::Preview
def default
render(HelpersProxyComponent.new)
end
end
70 changes: 61 additions & 9 deletions test/sandbox/test/integration_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,21 +52,21 @@ def test_rendering_component_in_a_controller_with_block
end

def test_template_changes_are_not_reflected_on_new_request_when_cache_template_loading_is_true
# cache_template_loading is set to true on the initializer
with_template_caching do
get "/controller_inline"
assert_select("div", "bar")
assert_response :success

get "/controller_inline"
assert_select("div", "bar")
assert_response :success
modify_file "app/components/controller_inline_component.html.erb", "<div>Goodbye world!</div>" do
get "/controller_inline"
assert_select("div", "bar")
assert_response :success
end

modify_file "app/components/controller_inline_component.html.erb", "<div>Goodbye world!</div>" do
get "/controller_inline"
assert_select("div", "bar")
assert_response :success
end

get "/controller_inline"
assert_select("div", "bar")
assert_response :success
end

def test_template_changes_are_reflected_on_new_request_when_cache_template_loading_is_false
Expand Down Expand Up @@ -127,6 +127,58 @@ def test_inherited_component_with_call_method_does_not_recompile_superclass
end
end

def test_helper_changes_are_reflected_on_new_request
skip if Rails.application.config.cache_classes

get "/helpers_proxy_component"
assert_select("div", "Hello helper method")
assert_response :success

helper = <<~RUBY
module MessageHelper
def message
"Goodbye world!"
end
end
RUBY
modify_file "app/helpers/message_helper.rb", helper do
get "/helpers_proxy_component"
assert_select("div", "Goodbye world!")
assert_response :success
end

get "/helpers_proxy_component"
assert_select("div", "Hello helper method")
assert_response :success
end

def test_helper_changes_are_reflected_on_new_request_with_previews
skip if Rails.application.config.cache_classes

with_preview_route("/previews") do
get "/previews/helpers_proxy_component/default"
assert_select("div", "Hello helper method")
assert_response :success

helper = <<~RUBY
module MessageHelper
def message
"Goodbye world!"
end
end
RUBY
modify_file "app/helpers/message_helper.rb", helper do
get "/previews/helpers_proxy_component/default"
assert_select("div", "Goodbye world!")
assert_response :success
end

get "/previews/helpers_proxy_component/default"
assert_select("div", "Hello helper method")
assert_response :success
end
end

def test_rendering_component_in_a_controller_using_render_to_string
get "/controller_inline_baseline"

Expand Down
4 changes: 3 additions & 1 deletion test/sandbox/test/rake_tasks_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
module ViewComponent
class RakeTasksTest < TestCase
def setup
Sandbox::Application.load_tasks
Kernel.silence_warnings do
Sandbox::Application.load_tasks
end
end

def test_statsetup_task
Expand Down
12 changes: 10 additions & 2 deletions test/sandbox/test/rendering_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -417,10 +417,18 @@ def test_validations_component
end

def test_compiles_unrendered_component
# The UnreferencedComponent will get compiled at boot,
# but that might have been thrown away if code-reloading is enabled
skip unless Rails.env.cache_classes?

assert UnreferencedComponent.compiled?
end

def test_compiles_components_without_initializers
# MissingInitializerComponent will get compiled at boot,
# but that might have been thrown away if code-reloading is enabled
skip unless Rails.env.cache_classes?

assert MissingInitializerComponent.compiled?
end

Expand Down Expand Up @@ -923,8 +931,8 @@ def test_inherited_component_renders_when_lazy_loading
# undo the changes made by self.class.compile and friends, forcing a compile the next time
# #render_template_for is called. This shouldn't be necessary except in the test environment,
# since eager loading is turned on here.
Object.send(:remove_const, :MyComponent)
Object.send(:remove_const, :InheritedWithOwnTemplateComponent)
Object.send(:remove_const, :MyComponent) if defined?(MyComponent)
Object.send(:remove_const, :InheritedWithOwnTemplateComponent) if defined?(InheritedWithOwnTemplateComponent)

load "test/sandbox/app/components/my_component.rb"
load "test/sandbox/app/components/inherited_with_own_template_component.rb"
Expand Down
4 changes: 3 additions & 1 deletion test/sandbox/test/tasks_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

class TasksTest < ActiveSupport::TestCase
setup do
Rails.application.load_tasks
Kernel.silence_warnings do
Rails.application.load_tasks
end
end

teardown do
Expand Down
9 changes: 9 additions & 0 deletions test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,15 @@ def with_generate_sidecar(enabled, &block)
with_generate_option(:sidecar, enabled, &block)
end

def with_template_caching
old_cache_template_loading = ActionView::Base.cache_template_loading
ActionView::Base.cache_template_loading = true

yield
ensure
ActionView::Base.cache_template_loading = old_cache_template_loading
end

def with_new_cache
old_cache = ViewComponent::CompileCache.cache
ViewComponent::CompileCache.cache = Set.new
Expand Down

0 comments on commit 18f9781

Please sign in to comment.