视图规范

视图规范通过 type: :view 标记,或者如果已通过将它们放置在 spec/views 中设置了 config.infer_spec_type_from_file_location!

使用它们在不调用特定控制器的的情况下测试视图模板的内容。它们通常遵循三个步骤

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

  render

  expect(rendered).to match(/text/)
  1. 使用 assign 方法在视图中设置实例变量。

  2. 使用 render 方法渲染视图。

  3. 对生成的渲染模板设置期望。

视图规范渲染所描述的视图文件

假设一个名为“spec/views/widgets/index.html.erb_spec.rb”的文件,其中包含

require "rails_helper"

RSpec.describe "widgets/index" 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

当我运行 rspec spec/views

那么所有示例都应该通过。

视图规范可以有 before 块和嵌套

假设一个名为“spec/views/widgets/index.html.erb_spec.rb”的文件,其中包含

require "rails_helper"

RSpec.describe "widgets/index" 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

当我运行 rspec spec/views

那么所有示例都应该通过。

视图规范可以显式渲染模板

假设一个名为“spec/views/widgets/widget.html.erb_spec.rb”的文件,其中包含

require "rails_helper"

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

    render :template => "widgets/widget"

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

以及一个名为“app/views/widgets/widget.html.erb”的文件,其中包含

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

当我运行 rspec spec/views

那么所有示例都应该通过。

视图规范可以渲染布局中的模板

假设一个名为“spec/views/widgets/widget.html.erb_spec.rb”的文件,其中包含

require "rails_helper"

RSpec.describe "rendering the widget template" 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

以及一个名为“app/views/widgets/widget.html.erb”的文件,其中包含

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

以及一个名为“app/views/layouts/inventory.html.erb”的文件,其中包含

<%= yield %>

当我运行 rspec spec/views

那么所有示例都应该通过。

视图规范可以有包含格式和处理程序的描述

假设一个名为“spec/views/widgets/widget.xml.erb_spec.rb”的文件,其中包含

require "rails_helper"

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

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

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

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

以及一个名为“app/views/widgets/widget.html.erb”的文件,其中包含

HTML

以及一个名为“app/views/widgets/widget.xml.erb”的文件,其中包含

XML

当我运行 rspec spec/views

那么所有示例都应该通过。

视图规范可以渲染带有局部变量的模板

假设一个名为“spec/views/widgets/widget.html.erbspec.rb”的文件,其中包含

require "rails_helper"

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

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

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

以及一个名为“app/views/widgets/index.html.erb”的文件,其中包含

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

当我运行 rspec spec/views

那么所有示例都应该通过。

视图规范可以在局部视图中渲染局部变量

假设一个名为“spec/views/widgets/widget.html.erbspec.rb”的文件,其中包含

require "rails_helper"

RSpec.describe "rendering locals in a partial" 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

以及一个名为“app/views/widgets/_widget.html.erb”的文件,其中包含

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

当我运行 rspec spec/views

那么所有示例都应该通过。

视图规范可以在隐式局部视图中渲染局部变量

假设一个名为“spec/views/widgets/widget.html.erbspec.rb”的文件,其中包含

require "rails_helper"

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

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

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

以及一个名为“app/views/widgets/_widget.html.erb”的文件,其中包含

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

当我运行 rspec spec/views

那么所有示例都应该通过。

视图规范可以渲染文本

假设一个名为“spec/views/widgets/direct.html.erb_spec.rb”的文件,其中包含

require "rails_helper"

RSpec.describe "rendering text directly" do
  it "displays the given text" do

    render :plain => "This is directly rendered"

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

当我运行 rspec spec/views

那么所有示例都应该通过。

视图规范可以存根辅助方法

假设一个名为“app/helpers/application_helper.rb”的文件,其中包含

module ApplicationHelper
  def admin?
    false
  end
end

以及一个名为“app/views/secrets/index.html.erb”的文件,其中包含

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

以及一个名为“spec/views/secrets/index.html.erb_spec.rb”的文件,其中包含

require 'rails_helper'

RSpec.describe 'secrets/index' 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

当我运行 rspec spec/views/secrets

那么所有示例都应该通过。

视图规范在 request.path_parameters 中使用符号作为键以匹配 Rails 风格

假设一个名为“spec/views/widgets/index.html.erb_spec.rb”的文件,其中包含

require "rails_helper"

RSpec.describe "controller.request.path_parameters" 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

当我运行 rspec spec/views

那么所有示例都应该通过。

不需要额外参数的视图规范操作具有 request.fullpath 设置

假设一个名为“spec/views/widgets/index.html.erb_spec.rb”的文件,其中包含

  require "rails_helper"

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

当我运行 rspec spec/views

那么所有示例都应该通过。

当开发者提供额外参数时,需要额外参数的视图规范操作具有 request.fullpath 设置

假设一个名为“spec/views/widgets/show.html.erb_spec.rb”的文件,其中包含

  require "rails_helper"

  RSpec.describe "widgets/show" 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

当我运行 rspec spec/views

那么所有示例都应该通过。