Module: ViewComponent::TestHelpers

Included in:
SystemTestHelpers, TestCase
Defined in:
lib/view_component/test_helpers.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#rendered_contentActionView::OutputBuffer (readonly)

Returns the result of a render_inline call.

Returns:

  • (ActionView::OutputBuffer)


34
35
36
# File 'lib/view_component/test_helpers.rb', line 34

def rendered_content
  @rendered_content
end

Instance Method Details

#render_in_view_context(*args, &block) ⇒ Object

Execute the given block in the view context (using ‘instance_exec`). Internally sets `page` to be a `Capybara::Node::Simple`, allowing for Capybara assertions to be used. All arguments are forwarded to the block.

“‘ruby render_in_view_context(arg1, arg2: nil) do |arg1, arg2:|

render(MyComponent.new(arg1, arg2))

end

assert_text(“Hello, World!”) “‘



106
107
108
109
110
# File 'lib/view_component/test_helpers.rb', line 106

def render_in_view_context(*args, &block)
  @page = nil
  @rendered_content = vc_test_controller.view_context.instance_exec(*args, &block)
  Nokogiri::HTML.fragment(@rendered_content)
end

#render_inline(component, **args, &block) ⇒ Nokogiri::HTML

Render a component inline. Internally sets ‘page` to be a `Capybara::Node::Simple`, allowing for Capybara assertions to be used:

“‘ruby render_inline(MyComponent.new) assert_text(“Hello, World!”) “`

Parameters:

Returns:

  • (Nokogiri::HTML)


46
47
48
49
50
51
52
53
54
55
56
# File 'lib/view_component/test_helpers.rb', line 46

def render_inline(component, **args, &block)
  @page = nil
  @rendered_content =
    if Rails.version.to_f >= 6.1
      vc_test_controller.view_context.render(component, args, &block)
    else
      vc_test_controller.view_context.render_component(component, &block)
    end

  Nokogiri::HTML.fragment(@rendered_content)
end

#render_preview(name, from: __vc_test_helpers_preview_class, params: {}) ⇒ Nokogiri::HTML

Render a preview inline. Internally sets ‘page` to be a `Capybara::Node::Simple`, allowing for Capybara assertions to be used:

“‘ruby render_preview(:default) assert_text(“Hello, World!”) “`

Note: ‘#rendered_preview` expects a preview to be defined with the same class name as the calling test, but with `Test` replaced with `Preview`:

MyComponentTest -> MyComponentPreview etc.

In RSpec, ‘Preview` is appended to `described_class`.

Parameters:

  • name (String)

    The name of the preview to be rendered.

  • from (ViewComponent::Preview) (defaults to: __vc_test_helpers_preview_class)

    The class of the preview to be rendered.

  • params (Hash) (defaults to: {})

    Parameters to be passed to the preview.

Returns:

  • (Nokogiri::HTML)


77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/view_component/test_helpers.rb', line 77

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)

  # From what I can tell, it's not possible to overwrite all request parameters
  # at once, so we set them individually here.
  params.each do |k, v|
    previews_controller.request.params[k] = v
  end

  previews_controller.request.params[:path] = "#{from.preview_name}/#{name}"
  previews_controller.set_response!(ActionDispatch::Response.new)
  result = previews_controller.previews

  @rendered_content = result

  Nokogiri::HTML.fragment(@rendered_content)
end

#vc_test_controllerActionController::Base

Access the controller used by ‘render_inline`:

“‘ruby test “logged out user sees login link” do

vc_test_controller.expects(:logged_in?).at_least_once.returns(false)
render_inline(LoginComponent.new)
assert_selector("[aria-label='You must be signed in']")

end “‘

Returns:

  • (ActionController::Base)


204
205
206
# File 'lib/view_component/test_helpers.rb', line 204

def vc_test_controller
  @vc_test_controller ||= __vc_test_helpers_build_controller(Base.test_controller.constantize)
end

#vc_test_requestActionDispatch::TestRequest

Access the request used by ‘render_inline`:

“‘ruby test “component does not render in Firefox” do

request.env["HTTP_USER_AGENT"] = "Mozilla/5.0"
render_inline(NoFirefoxComponent.new)
refute_component_rendered

end “‘

Returns:

  • (ActionDispatch::TestRequest)


219
220
221
222
223
224
225
226
# File 'lib/view_component/test_helpers.rb', line 219

def vc_test_request
  @vc_test_request ||=
    begin
      out = ActionDispatch::TestRequest.create
      out.session = ActionController::TestSession.new
      out
    end
end

#with_controller_class(klass) ⇒ Object

Set the controller to be used while executing the given block, allowing access to controller-specific methods:

“‘ruby with_controller_class(UsersController) do

render_inline(MyComponent.new)

end “‘

Parameters:

  • klass (ActionController::Base)

    The controller to be used.



141
142
143
144
145
146
147
148
# File 'lib/view_component/test_helpers.rb', line 141

def with_controller_class(klass)
  old_controller = defined?(@vc_test_controller) && @vc_test_controller

  @vc_test_controller = __vc_test_helpers_build_controller(klass)
  yield
ensure
  @vc_test_controller = old_controller
end

#with_request_url(path, host: nil) ⇒ Object

Set the URL of the current request (such as when using request-dependent path helpers):

“‘ruby with_request_url(“/users/42”) do

render_inline(MyComponent.new)

end “‘

To use a specific host, pass the host param:

“‘ruby with_request_url(“/users/42”, host: “app.example.com”) do

render_inline(MyComponent.new)

end “‘

Parameters:

  • path (String)

    The path to set for the current request.

  • host (String) (defaults to: nil)

    The host to set for the current request.



168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'lib/view_component/test_helpers.rb', line 168

def with_request_url(path, host: nil)
  old_request_host = vc_test_request.host
  old_request_path_info = vc_test_request.path_info
  old_request_path_parameters = vc_test_request.path_parameters
  old_request_query_parameters = vc_test_request.query_parameters
  old_request_query_string = vc_test_request.query_string
  old_controller = defined?(@vc_test_controller) && @vc_test_controller

  path, query = path.split("?", 2)
  vc_test_request.host = host if host
  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)
  vc_test_request.set_header(Rack::QUERY_STRING, query)
  yield
ensure
  vc_test_request.host = old_request_host
  vc_test_request.path_info = old_request_path_info
  vc_test_request.path_parameters = old_request_path_parameters
  vc_test_request.set_header("action_dispatch.request.query_parameters", old_request_query_parameters)
  vc_test_request.set_header(Rack::QUERY_STRING, old_request_query_string)
  @vc_test_controller = old_controller
end

#with_variant(variant) ⇒ Object

Set the Action Pack request variant for the given block:

“‘ruby with_variant(:phone) do

render_inline(MyComponent.new)

end “‘

Parameters:

  • variant (Symbol)

    The variant to be set for the provided block.



122
123
124
125
126
127
128
129
# File 'lib/view_component/test_helpers.rb', line 122

def with_variant(variant)
  old_variants = vc_test_controller.view_context.lookup_context.variants

  vc_test_controller.view_context.lookup_context.variants = variant
  yield
ensure
  vc_test_controller.view_context.lookup_context.variants = old_variants
end