Search code examples
ruby-on-rails-4rspecrspec-railsrspec3

RSpec 3.4/Rails 4.2: how to test view containing button_to


I am using Rails 4.2 and RSpec 3.4. I am trying to write a view test for a view that contains a <%= button_to ... %> delete button. My test fails with this error:

Failures:

  1) projects/show.html.erb get secret project as nondisclosed devcomm user shows the obfuscated name and disclosed user
     Failure/Error: <%= button_to "Delete this project and reassign all children to parent", {}, method: "delete", data: { confirm: "Are you sure?" }, class: "btn btn-danger" %>

     ActionView::Template::Error:
       No route matches {:action=>"show", :controller=>"projects"}
     # ./app/views/projects/show.html.erb:13:in `_app_views_projects_show_html_erb___2105827750050220814_23458641445220'
     # ./spec/views/projects/show.html.erb_spec.rb:23:in `block (3 levels) in <top (required)>'
     # ------------------
     # --- Caused by: ---
     # ActionController::UrlGenerationError:
     #   No route matches {:action=>"show", :controller=>"projects"}
     #   ./app/views/projects/show.html.erb:13:in `_app_views_projects_show_html_erb___2105827750050220814_23458641445220'

The test is as follows:

require 'rails_helper'

RSpec.describe "projects/show.html.erb", type: :view do
  fixtures :users, :projects

  context "get secret project as disclosed user" do
    it "shows the unobfuscated name and disclosed user" do
      assign(:user, users(:nondevcomm1))
      assign(:project, projects(:secretproject2))

      render

      expect(rendered).to match "Secret project 2"
      expect(rendered).to match "Boo Wah, Another job title"
    end
  end

  context "get secret project as nondisclosed devcomm user" do
    it "shows the obfuscated name and disclosed user" do
      assign(:user, users(:devcomm1))
      assign(:project, projects(:secretproject2))

      render  ### This is where it fails

      expect(rendered).to match "Project 3"
      expect(rendered).to match "Boo Wah, Another job title"
    end
  end

end

The reason the first test passes and the second fails is because the user in the first test is nondevcomm and the view has a conditional to only display the button_to if the user is devcomm.

I found this related StackOverflow question, but because the button that is causing the issue deletes records, I want to keep it as a button and not a link, so I can't just change it to a link_to.

Any ideas of how I can test a view containing a button_to?


Solution

  • I found the issue. In the view, I was not providing the object to act on. I changed the <%= button_to ... %> to this and now my test passes:

    <%= button_to "Delete this project and reassign all children to parent", @project, method: "delete", data: { confirm: "Are you sure?" }, class: "btn btn-danger"
    %>