Rails and Rspec - check for errors when the form fails

I have a Foo model where : a name is required to create.

I am writing a specification for validation validation

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 an error message is present on the page?

I tried page.errors.should have_key(:name) , but this is wrong.

I think I could do page.should have_content("Name can't be blank") , but I would rather not link my integration tests so much with the content

+6
source share
3 answers

If you test your checks correctly at the device testing level, add another test for the desired error message:

 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 

Thus, you isolated the error generation and copy the model, and it is reliably tested, which allows you to implement some kind of global error display (for example, using flash [: error] , without having to explicitly check each error message at the presentation level.

+12
source

You said that you are writing a specification for validation validation, but I see that you are testing in capybara (or similar) with "fill_in"

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

Specification / 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 

Thus, you test in isolation - only what you need to check is whether the controller, or the view, or even the loop through the flash is working correctly.

Thus, your test is fast, durable and isolated.

+6
source

The it block says, “You shouldn't create an invalid Foo,” and if this is really what you are testing, do a unit test in the Foo model, not the integration test.

However, if you are testing the SPECIFIC error message on the page, you need to check the contents. To make the test less related, you can check for a specific html element. For example, my errors are displayed in a flash message. I test them by looking for a div with a class called error or alert . I ignore the actual message and just check to make sure some error is displayed.

+1
source

Source: https://habr.com/ru/post/899733/


All Articles