【问题标题】:Testing will paginate gem with Rspec/Capybara测试将使用 Rspec/Capybara 对 gem 进行分页
【发布时间】:2017-03-30 19:16:01
【问题描述】:

在我的应用程序中有一个管理部分,仅限于超级管理员(具有superadmin: true 属性的用户)。我有一个商店清单,我想对其进行分页和测试。

使用save_and_open_page 调试当前代码时,我得到一个空白页。如果我不是以超级管理员身份登录,我会被重定向到应用程序的根目录,并且在尝试使用 save_and_open_page 进行调试时会看到根页面。如果我根本没有登录,那么我将被重定向到登录页。所以基本功能应该可以工作。

我不知道为什么它不适用于superadmin,以及为什么我在使用save_and_open_page 进行调试时看不到商店列表。

这是我的spec/controllers/shops_controller_spec.rb(基本上是从here复制的):

require 'rails_helper'

RSpec.describe Admin::ShopsController, type: :controller do

  context "GET methods" do

    describe "#index action" do
      before(:all) {  
        amount = Rails.application.config.page_size
        amount.times { FactoryGirl.create(:shop) }
      }

      before(:each) {
        login_as(FactoryGirl.create(:user, superadmin: true), :scope => :user)
      }

      context "with entries == config.page_size" do
        it "has no second page" do
          get :index
          expect(response).not_to have_selector("a", :href => "/shops?page=2", :content => "2")
          # visit admin_shops_path
          # expect(page).to have_no_xpath("//*[@class='pagination']//a[text()='2']")
        end
      end

      context "with entries > config.page_size" do
        before { FactoryGirl.create(:shop) }

        it "has a second page with too many entries" do 
          visit "/admin/shops"
          save_and_open_page
          expect(page).to have_xpath("//*[@class='pagination']//a[text()='2']")
        end

        it "correctly redirects to next page" do
          visit admin_shops_path
          find("//*[@class='pagination']//a[text()='2']").click
          expect(page.status_code).to eq(200)
        end
      end
    end
  end
end

如您所见,我尝试以不同的方式进行测试(“预期块”取自this SO-question),但它们都不起作用。使用 get :index 我收到

Admin::ShopsController GET methods #index action with entries == config.page_size has no second page
     Failure/Error: expect(page).not_to have_selector("a", :href => "/shops?page=2", :content => "2")

     ArgumentError:
       invalid keys :href, :content, should be one of :count, :minimum, :maximum, :between, :text, :id, :class, :visible, :exact, :exact_text, :match, :wait, :filter_set

如果有帮助,这是我的 AdminController.rb:

class AdminController < ApplicationController
    layout 'admin'

  before_action :authenticate_user!, :verify_is_superadmin

    before_action :set_locale
    before_action :get_breadcrumbs

    private

    def get_breadcrumbs
        splitted_url = request.original_fullpath.split("/")
        # Remove first object
        splitted_url.shift
        result = splitted_url.map { |element| element.humanize.capitalize }
        session[:breadcrumbs] = result
        # debug
    end

    def set_locale
        I18n.locale =  params[:locale] || session[:locale] || I18n.default_locale
        # session[:locale] = I18n.locale
    end

  def verify_is_superadmin
    (current_user.nil?) ? redirect_to(root_path) : (redirect_to(root_path) unless current_user.superadmin?)
  end

end

更新 使用 Thomas 的回答,我最终将代码放入 spec/features,现在看起来像这样:

require "rails_helper"

RSpec.feature "Widget management", :type => :feature do

  before(:each) {  
    amount = Rails.application.config.page_size
    amount.times { FactoryGirl.create(:shop) }
  }

  before(:each) {
    login_as(FactoryGirl.create(:user, superadmin: true), :scope => :user)
  }

  scenario "with entries == config.page_size" do

    visit admin_shops_path
    #save_and_open_page
    expect(page).to have_no_xpath("//*[@class='pagination']//a[text()='2']")
  end

  scenario "with entries > config.page_size" do
    FactoryGirl.create(:shop)
    visit admin_shops_path
    expect(page).to have_xpath("//*[@class='pagination']//a[text()='2']")
  end

  scenario "with entries > config.page_size it correctly redirects to next page" do
    FactoryGirl.create(:shop)
    visit admin_shops_path
    find("//*[@class='pagination']//a[text()='2']").click
    expect(page.status_code).to eq(200)
  end
end

一切正常!

【问题讨论】:

    标签: ruby-on-rails ruby rspec pagination capybara


    【解决方案1】:

    这里有很多问题。

    首先,您链接到的另一个 SO 问题没有使用 Capybara,因此为匹配器复制其示例是错误的。

    其次,您正在编写控制器测试,而不是查看测试或功能测试。控制器测试默认不呈现页面,因此要测试页面上的元素,您需要编写视图测试或功能测试。 Capybara 是为功能测试而设计的,而不是为控制器测试而设计的。这就是为什么默认的capybara/rspec 配置文件仅将 Capybara DSL 包含到“功能”类型的测试中。它还将 Capybara RSpec 匹配器包含在视图测试中,因为它们对那里提供的渲染字符串很有用。

    第三,您在同一个文件中混合使用 get/responsevisit/page,这只会让事情变得混乱。

    如果您将这些重写为功能测试,那么要检查您在 capybara 中没有与特定 href 的链接,您会这样做

    expect(page).not_to have_link(href: '...')
    

    如果您想确保不存在带有特定文本和特定 href 的链接

    expect(page).not_to have_link('link text', href: '...')
    

    注意:检查是否存在与给定文本和给定 href 的链接,仍然可能存在与文本或 href 的链接

    【讨论】:

    • 谢谢!将所有内容放在规范/功能中确实解决了这个问题。我故意将get/responsevisit/page 混合在一起,以尝试至少运行一个测试用例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-12
    • 1970-01-01
    相关资源
    最近更新 更多