Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails and Rspec - checking for existence of errors when form submission fails

I have a Foo model, where :name is required on creation.

I'm writing a spec to test the validations

it 'should not create an invalid Foo' do
  fill_in "Name", :with=>""
  # an error message will be displayed when this button is clicked
  click_button "Create Foo"
end

How can I confirm that the error message is present on the page?

I've tried page.errors.should have_key(:name) but this is not right.

I guess I could do page.should have_content("Name can't be blank") but I'd prefer to avoid coupling my integration tests so strongly with the content

like image 560
stephenmurdoch Avatar asked Oct 20 '11 20:10

stephenmurdoch


Video Answer


2 Answers

If you're testing your validations correctly at the unit testing level, adding another test for your desired error message is easy:

describe Foo do
  describe "validations" do
    describe "name" do
      before { @foo = FactoryGirl.build(:foo) } # or Foo.new if you aren't using FactoryGirl

      context "when blank" do
        before { @foo.name = "" }

        it "is invalid" do
          @foo.should_not be_valid
        end

        it "adds the correct error message" do
          @foo.valid?
          @foo.errors.messages[:name].should include("Name cannot be blank")
        end
      end # positive test case omitted for brevity
    end
  end
end

This way, you've isolated the error generation and copy to the model, and it's reliably tested, which allows you to implement some kind of global error display (for instance, using flash[:error], without having to test each error message explicitly at the view level.

like image 173
mhriess Avatar answered Sep 27 '22 23:09

mhriess


You said that you're writing a spec to test the validations, but I see that you're testing in capybara (or similar) with "fill_in"

Instead, I highly recommend writing unit tests to test your models.

spec/models/your_model_spec.rb

require 'spec_helper'
describe YourModel do

  it "should not allow a blank name" do
    subject.name = ""
    subject.should_not be_valid
    subject.should have(1).error_on(:name)
  end

end

That way, you're testing in isolation --- only what you need to test, not whether the controller is working correctly, or the view, or even looping through the flash.

This way, your test is fast, durable, and isolated.

like image 37
Jesse Wolgamott Avatar answered Sep 27 '22 22:09

Jesse Wolgamott