如何以正确的方式在PostController中使用RSpec测试未选中的复选框

时间:2018-04-09 15:54:06

标签: ruby-on-rails-4 capybara rspec-rails pundit

我在post_controller上使用RSpec执行此测试控制器,但是我很难评估没有权限检查类别的用户。

期待(posts.categories).to have_unchecked_field(“体育”)

这个测试对于用户来说就像是一种不破解帖子类别的方式。

context "restrictions for users on posts who" do
    let(:user) { create(:user) }
    let(:category) { create(:category)}
    let(:posting) { Post.create(title: "State transitions", subtitle: "Can't be hacked.", content: "State transitions now they can't be hacked anymore.", author: user) }

    before :each do
      posting.categories << category
      assign_role!(user, :editor, posting)
      sign_in user
    end

    it  "can edit a post, but not tag them" do
      put :update, { id: :posting.to_param, title: "Editing post for editors!",
                            content: "The editor users, they cannot tag a post",
                            tag_names: "these are tags" },
                    post_id: posting.id

      posting.reload
      expect(posting.tags).to be_empty
    end

    it  "can edit a post, but not check the categories" do
      put :update, { id: :posting.to_param,
                     title: "Editing post for editors!",
                    content: "The editor users, they cannot check categories",
                    category_ids:["Sports"] },
                  post_id: posting.id

      posting.reload

      expect(posting.categories).to have_unchecked_field("Sports")

    end

  end
end

形式:

- if policy(post).change_category?
  = f.association :categories, label: "Select the Categories:", as: :check_boxes , collection: @categories.map{|c| [c.name, c.id]}, include_hidden: false

因此,如果用户没有权限,我正在使用私有方法sanitizing_parameters来删除参数。

post_controller.rb

def update
    authorize @post, :update?
    @post.author = current_user

    if @post.update(sanitized_parameters)
      flash[:notice] = "Post has been updated."
      redirect_to @post
    else
      flash.now[:alert] = "Post has not been updated."
      render "edit"
    end
  end

...
private

  def post_params
params.require(:post).permit(:title,
                             :subtitle,
                             :content,
                             :tag_names,
                             :attachment,
                             :attachment_cache,
                             :remove_attachment,
                             :remote_attachment_url,
                             category_ids:[])
  end

  def sanitized_parameters
    whitelisted_params = post_params

    unless policy(@post).change_category?
      whitelisted_params.delete(category_ids:[])
    end

    unless policy(@post).tag?
      whitelisted_params.delete(:tag_names)
    end

    whitelisted_params
  end

错误:

Failures:

  1) PostsController restrictions for users on posts who can edit a post, but not check the categories
     Failure/Error: expect(posting.categories).to have_unchecked_field("Sports")
       expected to find field "Sports" that is not checked but there were no matches

1 个答案:

答案 0 :(得分:1)

您正在编写控制器或可能请求测试,但Capybara仅用于功能/系统和视图测试。当你试图调用have_unchecked_field("Sports")时,它应该引发一个no方法错误,因为你甚至不应该将Capybara方法包含在控制器测试中。

由于您已将Capybara :: DSL纳入所有测试(假设),它将posting.categories转换为字符串,将其解析为HTML,然后在其中查找元素。由于posting.categories不是HTML,因此它永远不会像那样工作。您可能想要的是

expect(posting.categories).to be_empty