FeifanZ
FeifanZ

Reputation: 16316

Capybara visit page, assigns always nil

In my spec, I'm visiting a page and checking that an instance variable is being set correctly. The spec is always saying that the assigns is nil. Looking at the saved page, it's blank—not a 404 or any sort of error page.

describe ArtistsController do
    before :each do
        @artist = Artist.first
    end
    describe "GET #about" do
        it "finds artist by artistname" do
            visit artist_about_path(@artist.artistname); save_page
            puts "2 ===================== #{ artist_about_path(@artist.artistname) }"
            # assigns(:artist).should eq(@artist)
            assigns[:artist].should_not be_nil
        end
        it "renders the :about view" do
            visit artist_about_path(@artist.artistname)
            # response.should render_template :about
            response.should be_success
        end
    end
# Similar specs for other pages to be rendered

Artist.first comes from a rake task that's being run in spec_helper to populate the database; that part works correctly in other tests.

I'm checking the path by printing it, and it looks fine. Controller methods:

class ArtistsController < ApplicationController
before_filter :get_artist_from_params
def about
    @artist = Artist.find_by_artistname(params[:artistname].downcase)
    @contact_info = @artist.contact_info
    puts "1 ==============================="
    puts @artist.inspect
  end

In the server logs, @artist is the object we expect.

def get_artist_from_params
    if !params[:artistname].blank?
      @artist = Artist.find_by_artistname(params[:artistname].downcase)
      if @artist.blank?
        not_found
      end
    end
end

I'm not sure where the test is going wrong…The puts are outputting the right values.

Using Ruby 2.0, Rails 3.2, Capybara 2.1, Rspec 2.12.

Upvotes: 1

Views: 1369

Answers (1)

dasnixon
dasnixon

Reputation: 998

I'm a little confused by this testing, but maybe I can help shore some up.

I think you can leave your about action blank:

def about
end

Then you can clean up your before_filter as such:

private

def get_artist_from_params
  if params[:artistname]
    @artist = Artist.find_by_artistname(params[:artistname].downcase)
    if @artist
      @contact_info = @artist.contact_info
    else
      not_found
    end
  end
end

First, I honestly don't think you need to do integration testing, if all you want to do is assure yourself that your instance variables are being set properly in your controllers. I believe you want to do functional testing as shown here http://guides.rubyonrails.org/testing.html#what-to-include-in-your-functional-tests. Alright, so lets see if we can do this with what you have so far:

describe ArtistsController do
  let(:artist) { Artist.first } #May want to look into FactoryGirl
  describe "GET #about" do
    before :each do
      @parameters = { artistname: artist.name }
      Artist.should_receive(:find_by_artistname).with(artist.name.downcase).and_return(artist)
    end
    it "assigns artist and contact_info instance variables" do
      get :about, @parameters
      assigns(:artist).should eq(artist)
      assigns(:contact_info).should eq(artist.contact_info)
    end
    it "responds successfully" do
      get :about, @parameters
      expect(response).to be_success
    end
    it "renders about template" do
      get :about, @parameters
      expect(response).to render_template("about")
    end
  end
end

Let me know if that makes sense I can provide additional details.

Upvotes: 1

Related Questions