Search code examples
ruby-on-railsrspecruby-on-rails-3.2rspec-rails

Rspec test failing: creating new record rather than using existing one


I have the following code:

describe "when visiting roll call with no notes" do
  before do
    login_as_sensei
    @dojo = FactoryGirl.create(:dojo, name: "Melbourne")
    @time = FactoryGirl.create(:times, dojo: @dojo)
    @roll = FactoryGirl.create(:roll_call)
    visit time_roll_calls_path("melbourne", "14-2-2013", "1000")
  end

  specify { @roll.notes.should be_blank }
  it { should_not have_content("This is a note!") }

  describe "and filling in note information correctly" do
    before do
      fill_in "roll_call[notes]", with: "This is a note!"
      click_button "Add Notes"
    end

    it { should have_content("This is a note!") } # 'it' refers to the page
    specify { RollCall.last.notes.should_not be_blank }
    specify { @roll.notes.should_not be_blank }
    specify { @roll.reload.notes.should_not be_blank }
  end
end

As far as I know, all 4 tests at the end should pass, however only the first 2 do:

it { should have_content("This is a note!") }
specify { RollCall.last.notes.should_not be_blank }

And the last 2 return the following errors:

1) RollCalls when visiting roll call with no notes and filling in note information correctly 
 Failure/Error: specify { @roll.notes.should_not be_blank }
   expected blank? to return false, got true
 # ./spec/features/roll_calls_spec.rb:241:in `block (4 levels) in <top (required)>'

2) RollCalls when visiting roll call with no notes and filling in note information correctly 
 Failure/Error: specify { @roll.reload.notes.should_not be_blank }
   expected blank? to return false, got true
 # ./spec/features/roll_calls_spec.rb:242:in `block (4 levels) in <top (required)>'

Is this how rspec should work or am I doing something wrong?


Solution

  • You're mixing acceptance specs and request specs here. @roll will not be modified when you perform capybara requests (via fill_in, etc).

    Acceptance specs test the contents of the response. Request specs test operations on records for a given request. You might consider splitting up your tests like so:

    # Acceptance test
    describe "when visiting roll call with no notes" do
      before do
        login_as_sensei
        @dojo = FactoryGirl.create(:dojo, name: "Melbourne")
        @time = FactoryGirl.create(:times, dojo: @dojo)
        @roll = FactoryGirl.create(:roll_call)
        visit time_roll_calls_path("melbourne", "14-2-2013", "1000")
      end
    
      it { should_not have_content("This is a note!") }
    
      describe "and filling in note information correctly" do
        before do
          fill_in "roll_call[notes]", with: "This is a note!"
          click_button "Add Notes"
        end
    
        it { should have_content("This is a note!") } # 'it' refers to the page
      end
    end
    
    # Request specs
    describe RollCallsController do
      describe "#action" do
        before do
          login_as_sensei
          @roll = FactoryGirl.create(:roll_call)
    
        end
    
        it "should initially be blank" do
          get "/some/path", :id => @roll.id
        end
    
        it "should add a note" do
          post "/roll_calls/#{@roll.id}/notes/add", roll_call: {notes: "New note"}
          @roll.reload.notes.should_not be_blank
          @roll.reload.notes[0].note.should == "New note"
        end
      end
    end