Testing
Unit test components using the render_inline test helper, asserting against the rendered output:
require "test_helper"
class ExampleComponentTest < ViewComponent::TestCase
  def test_render_component
    render_inline(ExampleComponent.new(title: "my title")) { "Hello, World!" }
    assert_component_rendered
    assert_selector("span[title='my title']", text: "Hello, World!")
    # or, to just assert against the text:
    assert_text("Hello, World!")
  end
end
(Capybara matchers are available if the gem is installed)
Note: assert_selector only matches on visible elements by default. To match on elements regardless of visibility, add visible: false. See the Capybara documentation for more details.
For debugging purposes, the rendered_content test helper outputs the rendered HTML.
Use with RSpec
To enable ViewComponent test helpers in RSpec, add:
# spec/rails_helper.rb
require "view_component/test_helpers"
RSpec.configure do |config|
  # ...
  config.include ViewComponent::TestHelpers, type: :component
  config.include ViewComponent::SystemSpecHelpers, type: :feature
  config.include ViewComponent::SystemSpecHelpers, type: :system
end
Testing Slots
def test_render_component
  component = ListComponent.new(title: "Fruits").tap do |c|
    c.with_item { "Apple" }
    c.with_item { "Orange" }
    c.with_extra { "<div><span>rendered html</span></div>".html_safe }
  end
  render_inline(component)
  assert_selector("ul")
  assert_selector("li", text: "Apple")
  assert_selector("li", text: "Orange")
end
Previews as test cases
Since 2.56.0
Use render_preview(name) to render previews in ViewComponent unit tests:
class ExampleComponentTest < ViewComponent::TestCase
  def test_render_preview
    render_preview(:with_default_title)
    assert_text("Example component default")
  end
end
Testing components with behaviors
To test ViewComponents with behaviors, visit a preview in a system test:
class MyComponentSystemTest < ActionDispatch::SystemTestCase
  def test_default_preview
    visit("/rails/view_components/my_component/default")
    click_on("Open dialog")
    assert_text("Test Dialog")
  end
end
Best practices
Prefer testing the rendered output over individual methods:
# Good
assert_selector(".Label", text: "My label")
# Bad
assert_equal MyComponent.new.label, "My label"
  Without capybara 
 In the absence of capybara, assert against the return value of render_inline, which is an instance of Nokogiri::HTML::DocumentFragment:
def test_render_component
  result = render_inline(ExampleComponent.new(title: "my title")) { "Hello, World!" }
  assert_includes result.css("span[title='my title']").to_html, "Hello, World!"
end
Slots
To test components that use Slots:
def test_renders_slots_with_content
  render_inline(SlotsComponent.new(footer: "Bye!")) do |component|
    component.with_title { "Hello!" }
    component.with_body { "Have a nice day." }
  end
  assert_selector(".title", text: "Hello!")
  assert_selector(".body", text: "Have a nice day.")
end
Action Pack Variants
Use the with_variant helper to test specific variants:
def test_render_component_for_tablet
  with_variant :tablet do
    render_inline(ExampleComponent.new(title: "my title")) { "Hello, tablets!" }
    assert_selector("span[title='my title']", text: "Hello, tablets!")
  end
end
Request formats
Use the with_format helper to test specific request formats:
def test_render_component_as_json
  with_format :json do
    render_inline(MultipleFormatsComponent.new)
    assert_equal(rendered_json["hello"], "world")
  end
end
Configuring the controller used in tests
Since 2.27.0
Component tests assume the existence of an ApplicationController class. To set the controller for a test file, define vc_test_controller_class:
class ExampleComponentTest < ViewComponent::TestCase
  def vc_test_controller_class
    PublicController
  end
  def test_component_in_public_controller
    render_inline ExampleComponent.new
    assert_text "foo"
  end
end
To configure the controller used for a test case, use with_controller_class from ViewComponent::TestHelpers.
class ExampleComponentTest < ViewComponent::TestCase
  def test_component_in_public_controller
    with_controller_class PublicController do
      render_inline ExampleComponent.new
      assert_text "foo"
    end
  end
  def test_component_in_authenticated_controller
    with_controller_class AuthenticatedController do
      render_inline ExampleComponent.new
      assert_text "bar"
    end
  end
end
  Setting request.path_parameters 
 Since 2.31.0
Some Rails helpers won’t work unless request.path_parameters are set correctly, resulting in an ActionController::UrlGenerationError.
To set request.path_parameters for a test case, use with_request_url from ViewComponent::TestHelpers:
class ExampleComponentTest < ViewComponent::TestCase
  def test_with_request_url
    with_request_url "/products/42" do
      render_inline ExampleComponent.new # contains i.e. `link_to "French", url_for(locale: "fr")`
      assert_link "French", href: "/products/42?locale=fr"
    end
  end
end
  Setting request.host 
 Since 3.3.0
Rails routes that have a subdomain constraint require request.host to be set correctly.
To set request.host for a test case, use with_request_url from ViewComponent::TestHelpers:
class ExampleComponentTest < ViewComponent::TestCase
  def test_with_request_url
    with_request_url "/products/42", host: "app.example.com" do
      render_inline ExampleComponent.new # contains i.e. `products_path` that is constrained to the 'app' subdomain
      assert_link "Products", href: "/products"
    end
  end
end
Query parameters
Since 2.41.0
It’s also possible to set query parameters:
class ExampleComponentTest < ViewComponent::TestCase
  def test_with_request_url
    with_request_url "/products/42?locale=en" do
      render_inline ExampleComponent.new # contains i.e. `link_to "Recent", url_for(request.query_parameters.merge(filter: "recent"))`
      assert_link "Recent", href: "/?locale=en&filter=recent"
    end
  end
end
RSpec configuration
To use RSpec, add the following:
# spec/rails_helper.rb
require "view_component/test_helpers"
require "view_component/system_test_helpers"
require "capybara/rspec"
RSpec.configure do |config|
  config.include ViewComponent::TestHelpers, type: :component
  config.include ViewComponent::SystemTestHelpers, type: :component
  config.include Capybara::RSpecMatchers, type: :component
end
To access Devise’s controller helper methods in tests, add the following:
RSpec.configure do |config|
  config.include Devise::Test::ControllerHelpers, type: :component
  config.before(:each, type: :component) do
    @request = vc_test_controller.request
  end
end
Specs created by the generator have access to test helpers like render_inline. For example:
require "rails_helper"
RSpec.describe ExampleComponent, type: :component do
  it "renders component" do
    render_inline(described_class.new(title: "my title")) { "Hello, World!" }
    expect(page).to have_css "span[title='my title']", text: "Hello, World!"
    # or, to just assert against the text
    expect(page).to have_text "Hello, World!"
  end
end
To use component previews:
# config/application.rb
config.view_component.previews.paths << "#{Rails.root}/spec/components/previews"
Component system tests
Use with_rendered_component_path with render_inline to system test components:
class ViewComponentSystemTest < ViewComponent::SystemTestCase
  def test_simple_js_interaction_in_browser_without_layout
    with_rendered_component_path(render_inline(SimpleJavascriptInteractionWithJsIncludedComponent.new)) do |path|
      visit(path)
      assert(find("[data-hidden-field]", visible: false))
      find("[data-button]", text: "Click Me To Reveal Something Cool").click
      assert(find("[data-hidden-field]", visible: true))
    end
  end
end
For components that depend on a layout, provide the layout argument:
class ViewComponentSystemTest < ViewComponent::SystemTestCase
  def test_simple_js_interaction_in_browser_with_layout
    with_rendered_component_path(render_inline(SimpleJavascriptInteractionWithoutJsIncludedComponent.new), layout: "application") do |path|
      # ...
    end
  end
end