Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add "Testing View Partials" section to the Testing Guides #49193

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions actionview/lib/action_view/test_case.rb
Expand Up @@ -9,6 +9,9 @@

module ActionView
# = Action View Test Case
#
# Read more about <tt>ActionView::TestCase</tt> in {Testing Rails Applications}[https://guides.rubyonrails.org/testing.html#testing-view-partials]
# in the guides.
class TestCase < ActiveSupport::TestCase
class TestController < ActionController::Base
include ActionDispatch::TestProcess
Expand Down
1 change: 1 addition & 0 deletions actionview/test/fixtures/developers/_developer_with_h1.erb
@@ -0,0 +1 @@
<h1 id="name"><%= developer.name %></h1>
34 changes: 34 additions & 0 deletions actionview/test/template/test_case_test.rb
Expand Up @@ -2,6 +2,7 @@

require "abstract_unit"
require "rails/engine"
require "capybara/minitest"

module ActionView
module ATestHelper
Expand Down Expand Up @@ -352,6 +353,35 @@ def render_from_helper
end
end

class PlaceholderAssertionsTest < ActionView::TestCase
helper_method def render_from_helper
content_tag "a", "foo", href: "/bar"
end

test "supports placeholders in assert_select calls" do
render(partial: "test/from_helper")

assert_select "a[href=?]", "/bar", text: "foo"
end
end

class CapybaraHTMLEncoderTest < ActionView::TestCase
include ::Capybara::Minitest::Assertions

def page
Capybara.string(document_root_element)
end

test "document_root_element can be configured to utilize Capybara" do
developer = DeveloperStruct.new("Eloy")

render "developers/developer_with_h1", developer: developer

assert_kind_of Capybara::Node::Simple, page
assert_css "h1", text: developer.name
end
end

module AHelperWithInitialize
def initialize(*)
super
Expand All @@ -365,3 +395,7 @@ class AHelperWithInitializeTest < ActionView::TestCase
end
end
end

if RUBY_VERSION >= "3.1"
require_relative "./test_case_test/pattern_matching_test_cases"
end
@@ -0,0 +1,14 @@
# frozen_string_literal: true

class ActionView::PatternMatchingTestCases < ActionView::TestCase
test "document_root_element integrates with pattern matching" do
developer = DeveloperStruct.new("Eloy")

render "developers/developer_with_h1", developer: developer

# rubocop:disable Lint/Syntax
assert_pattern { document_root_element.at("h1") => { content: "Eloy", attributes: [{ name: "id", value: "name" }] } }
refute_pattern { document_root_element.at("h1") => { content: "Not Eloy" } }
# rubocop:enable Lint/Syntax
end
end
104 changes: 104 additions & 0 deletions guides/source/testing.md
Expand Up @@ -1691,6 +1691,110 @@ assert_select_email do
end
```

Testing View Partials
---------------------

Partial templates - usually called "partials" - are another device for breaking the rendering process into more manageable chunks. With partials, you can extract pieces of code from your templates to separate files and reuse them throughout your templates.

View tests provide an opportunity to test that partials render content the way you expect. View partial tests reside in `test/views/` and inherit from `ActionView::TestCase`.

To render a partial, call `render` like you would in a template. The content is
available through the test-local `rendered` method:

```ruby
class ArticlePartialTest < ActionView::TestCase
test "renders a link to itself" do
article = Article.create! title: "Hello, world"

render "articles/article", article: article

assert_includes rendered, article.title
end
end
```

Tests that inherit from `ActionView::TestCase` also have access to [`assert_select`](#Testing-Views) and the [other additional view-based assertions](#Additional-View-Based-Assertions) provided by [rails-dom-testing][]:

```ruby
test "renders a link to itself" do
article = Article.create! title: "Hello, world"

render "articles/article", article: article

assert_select "a[href=?]", article_url(article), text: article.title
end
```

In order to integrate with [rails-dom-testing][], tests that inherit from
`ActionView::TestCase` declare a `document_root_element` method that returns the
rendered content as an instance of a
[Nokogiri::XML::Node](https://www.rubydoc.info/github/sparklemotion/nokogiri/Nokogiri/XML/Node):

```ruby
test "renders a link to itself" do
article = Article.create! title: "Hello, world"

render "articles/article", article: article
anchor = document_root_element.at("a")

assert_equal article.name, anchor.text
assert_equal article_url(article), anchor["href"]
end
```

If your application uses Ruby >= 3.0 or higher, depends on [Nokogiri >= 1.14.0](https://github.com/sparklemotion/nokogiri/releases/tag/v1.14.0) or
higher, and depends on [Minitest >= >5.18.0](https://github.com/minitest/minitest/blob/v5.18.0/History.rdoc#5180--2023-03-04-),
`document_root_element` supports [Ruby's Pattern Matching](https://docs.ruby-lang.org/en/master/syntax/pattern_matching_rdoc.html):

```ruby
test "renders a link to itself" do
article = Article.create! title: "Hello, world"

render "articles/article", article: article
anchor = document_root_element.at("a")

assert_pattern do
anchor => { content: article.title, attributes: [{ name: "href", value: article_url(article) }] }
end
end
```

If you'd like to access the same [Capybara-powered Assertions](https://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Minitest/Assertions)
that your [Functional and System Testing](#Functional-and-System-Testing) tests
utilize, you can define a base class that inherits from `ActionView::TestCase`
and transforms the `document_root_element` into a `page` method:

```ruby
# test/view_partial_test_case.rb

require "test_helper"
require "capybara/minitest"

class ViewPartialTestCase < ActionView::TestCase
include Capybara::Minitest::Assertions

def page
Capybara.string(document_root_element)
end
end

# test/views/article_partial_test.rb

require "view_partial_test_case"

class ArticlePartialTest < ViewPartialTestCase
test "renders a link to itself" do
article = Article.create! title: "Hello, world"

render "articles/article", article: article

assert_link article.title, href: article_url(article)
end
end
```

[rails-dom-testing]: https://github.com/rails/rails-dom-testing

Testing Helpers
---------------

Expand Down