0

I'm doing this test controller with RSpec on post_controller, but I'm having difficult to evaluate the users who don't have permission for check the categories.

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

This test it's like a way for a user don't hacking the post categories.

The

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

form:

- 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

So I'm using the private method sanitizing_parameters for deleting the parameters if a user don't have a permission.

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

error:

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
rld
  • 2,603
  • 2
  • 25
  • 39

1 Answers1

1

You're writing a controller or possibly request test, but Capybara is only for use in feature/system and view tests. When you attempt to call have_unchecked_field("Sports") it should have raised a no method error since you shouldn't even be including the Capybara methods into controller tests.

Since you have included Capybara::DSL into all your tests (assumed) it's taking posting.categories, converting it to a string, parsing it as HTML, and then looking for elements in it. Since posting.categories isn't HTML it's never going to work like that. What you probably want is something like

expect(posting.categories).to be_empty
Thomas Walpole
  • 48,548
  • 5
  • 64
  • 78
  • I try this be_empty. And raises this error: Failure/Error: expect(posting.categories).to be_empty expected `#]>.empty?` to return true, got false – rld Apr 09 '18 at 17:46
  • Yes, I was thinking and this match have_unchecked_field has no sense in controller tests... thank's for reply @Thomas Walpole – rld Apr 09 '18 at 17:47
  • @rld If it's telling you that `posting.categories` is not empty, then your test is either wrong or your code isn't doing what you think it is. You can see from that error that "Sports" has been added to `posting.categories` which is exactly what you're testing to make sure doesn't happen. – Thomas Walpole Apr 09 '18 at 17:59
  • I do this when try to create a post, and now I'm trying for updating the post. It has something wrong with the updating. – rld Apr 09 '18 at 18:15
  • Well in your `before` block you're adding a category to `posting` - I'm not sure if that defaults to 'Sports' for the category or not -- If it does then you test wouldn't actually be testing anything since the category would already be checked. – Thomas Walpole Apr 09 '18 at 19:04
  • Yes I do a: `before_action :set_categories, only: [:edit, :update] def set_categories @categories = Category.all.select(:id, :name) end` I pretend to delete the params of the categories like I do on tags. – rld Apr 11 '18 at 11:57
  • I commit the: `before :each do #posting.categories << category` and pass, there I was adding a category and I put to use a number rather than a string on: `category_ids:["1"] },` And pass. This test with checkbox is confusing. For the moment I'll leave it like this. Thank you for your help @Thomas Walpole – rld Apr 11 '18 at 12:25