lib/view_component/render_preview_helper.rb



# frozen_string_literal: true

module ViewComponent
  module RenderPreviewHelper
    # 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`.
    #
    # @param preview [String] The name of the preview to be rendered.
    # @return [Nokogiri::HTML]
    def render_preview(name)
      begin
        preview_klass = if respond_to?(:described_class)
          if described_class.nil?
            raise "`render_preview` expected a described_class, but it is nil."
          end

          "#{described_class}Preview"
        else
          self.class.name.gsub("Test", "Preview")
        end
        preview_klass = preview_klass.constantize
      rescue NameError
        raise NameError.new(
          "`render_preview` expected to find #{preview_klass}, but it does not exist."
        )
      end

      previews_controller = build_controller(ViewComponent::Base.preview_controller.constantize)
      previews_controller.request.params[:path] = "#{preview_klass.preview_name}/#{name}"
      previews_controller.response = ActionDispatch::Response.new
      result = previews_controller.previews

      @rendered_content = result

      Nokogiri::HTML.fragment(@rendered_content)
    end
  end
end