View specs

View specs are marked by type: :view or if you have set config.infer_spec_type_from_file_location! by placing them in spec/views.

Use them to test the content of view templates without invoking a specific controller. They generally follow three steps:

  assign(:widget, Widget.new)  # sets @widget = Widget.new in the view template

  render

  expect(rendered).to match(/text/)
  1. Use the assign method to set instance variables in the view.

  2. Use the render method to render the view.

  3. Set expectations against the resulting rendered template.

View specs render the described view file

Given a file named “spec/views/widgets/index.html.erb_spec.rb” with:

require "rails_helper"

RSpec.describe "widgets/index" , type: :view do
  it "displays all the widgets" do
    assign(:widgets, [
      Widget.create!(:name => "slicer"),
      Widget.create!(:name => "dicer")
    ])

    render

    expect(rendered).to match /slicer/
    expect(rendered).to match /dicer/
  end
end

When I run rspec spec/views

Then the examples should all pass.

View specs can have before block and nesting

Given a file named “spec/views/widgets/index.html.erb_spec.rb” with:

require "rails_helper"

RSpec.describe "widgets/index" , type: :view do

  context "with 2 widgets" do
    before(:each) do
      assign(:widgets, [
        Widget.create!(:name => "slicer"),
        Widget.create!(:name => "dicer")
      ])
    end

    it "displays both widgets" do
      render

      expect(rendered).to match /slicer/
      expect(rendered).to match /dicer/
    end
  end
end

When I run rspec spec/views

Then the examples should all pass.

View specs can explicitly render templates

Given a file named “spec/views/widgets/widget.html.erb_spec.rb” with:

require "rails_helper"

RSpec.describe "rendering the widget template" , type: :view do
  it "displays the widget" do
    assign(:widget, Widget.create!(:name => "slicer"))

    render :template => "widgets/widget"

    expect(rendered).to match /slicer/
  end
end

And a file named “app/views/widgets/widget.html.erb” with:

<h2><%= @widget.name %></h2>

When I run rspec spec/views

Then the examples should all pass.

View specs can render templates in layouts

Given a file named “spec/views/widgets/widget.html.erb_spec.rb” with:

require "rails_helper"

RSpec.describe "rendering the widget template" , type: :view do
  context "with the inventory layout" do
    it "displays the widget" do
      assign(:widget, Widget.create!(:name => "slicer"))

      render :template => "widgets/widget", :layout => "layouts/inventory"

      expect(rendered).to match /slicer/
    end
  end
end

And a file named “app/views/widgets/widget.html.erb” with:

<h2><%= @widget.name %></h2>

And a file named “app/views/layouts/inventory.html.erb” with:

<%= yield %>

When I run rspec spec/views

Then the examples should all pass.

View specs can have description that includes the format and handler

Given a file named “spec/views/widgets/widget.xml.erb_spec.rb” with:

require "rails_helper"

RSpec.describe "widgets/widget.html.erb" , type: :view do
  it "renders the HTML template" do
    render

    expect(rendered).to match /HTML/
  end
end

RSpec.describe "widgets/widget.xml.erb" , type: :view do
  it "renders the XML template" do
    render

    expect(rendered).to match /XML/
  end
end

And a file named “app/views/widgets/widget.html.erb” with:

HTML

And a file named “app/views/widgets/widget.xml.erb” with:

XML

When I run rspec spec/views

Then the examples should all pass.

View specs can render a template with locals

Given a file named “spec/views/widgets/widget.html.erbspec.rb” with:

require "rails_helper"

RSpec.describe "widgets/index" , type: :view do
  it "displays the widget" do
    widget = Widget.create!(:name => "slicer")

    render :locals => {:widget => widget}

    expect(rendered).to match /slicer/
  end
end

And a file named “app/views/widgets/index.html.erb” with:

<h3><%= widget.name %></h3>

When I run rspec spec/views

Then the examples should all pass.

View specs can render locals in a partial

Given a file named “spec/views/widgets/widget.html.erbspec.rb” with:

require "rails_helper"

RSpec.describe "rendering locals in a partial" , type: :view do
  it "displays the widget" do
    widget = Widget.create!(:name => "slicer")

    render :partial => "widgets/widget", :locals => {:widget => widget}

    expect(rendered).to match /slicer/
  end
end

And a file named “app/views/widgets/_widget.html.erb” with:

<h3><%= widget.name %></h3>

When I run rspec spec/views

Then the examples should all pass.

View specs can render locals in an implicit partial

Given a file named “spec/views/widgets/widget.html.erbspec.rb” with:

require "rails_helper"

RSpec.describe "rendering locals in a partial" , type: :view do
  it "displays the widget" do
    widget = Widget.create!(:name => "slicer")

    render "widgets/widget", :widget => widget

    expect(rendered).to match /slicer/
  end
end

And a file named “app/views/widgets/_widget.html.erb” with:

<h3><%= widget.name %></h3>

When I run rspec spec/views

Then the examples should all pass.

View specs can render text

Given a file named “spec/views/widgets/direct.html.erb_spec.rb” with:

require "rails_helper"

RSpec.describe "rendering text directly" , type: :view do
  it "displays the given text" do

    render :plain => "This is directly rendered"

    expect(rendered).to match /directly rendered/
  end
end

When I run rspec spec/views

Then the examples should all pass.

View specs can stub a helper method

Given a file named “app/helpers/application_helper.rb” with:

module ApplicationHelper
  def admin?
    false
  end
end

And a file named “app/views/secrets/index.html.erb” with:

<%- if admin? %>
  <h1>Secret admin area</h1>
<%- end %>

And a file named “spec/views/secrets/index.html.erb_spec.rb” with:

require 'rails_helper'

RSpec.describe 'secrets/index' , type: :view do
  before do
    allow(view).to receive(:admin?).and_return(true)
  end

  it 'checks for admin access' do
    render
    expect(rendered).to match /Secret admin area/
  end
end

When I run rspec spec/views/secrets

Then the examples should all pass.

View specs use symbols for keys in request.path_parameters to match Rails style

Given a file named “spec/views/widgets/index.html.erb_spec.rb” with:

require "rails_helper"

RSpec.describe "controller.request.path_parameters" , type: :view do
  it "matches the Rails environment by using symbols for keys" do
    [:controller, :action].each { |k| expect(controller.request.path_parameters.keys).to include(k) }
  end
end

When I run rspec spec/views

Then the examples should all pass.

View spec actions that do not require extra parameters have request.fullpath set

Given a file named “spec/views/widgets/index.html.erb_spec.rb” with:

  require "rails_helper"

  RSpec.describe "widgets/index" , type: :view do
    it "has a request.fullpath that is defined" do
      expect(controller.request.fullpath).to eq widgets_path
    end
  end

When I run rspec spec/views

Then the examples should all pass.

View spec actions that require extra parameters have request.fullpath set when the developer supplies them

Given a file named “spec/views/widgets/show.html.erb_spec.rb” with:

  require "rails_helper"

  RSpec.describe "widgets/show" , type: :view do
    it "displays the widget with id: 1" do
      widget = Widget.create!(:name => "slicer")
      controller.extra_params = { :id => widget.id }

      expect(controller.request.fullpath).to eq widget_path(widget)
    end
  end

When I run rspec spec/views

Then the examples should all pass.