title: Anyone know of a full suite of Devise Rspec / Capybara tests
body: <p>I've been learning Rails 3 with Devise and, so far, seem to have it working quite well. I've got custom session &amp; registration controllers, recaptcha is working and a signed-in user can upload an avatar via carrierwave, which is saved on S3. Pretty happy with my progress.</p>
  
  <p>Now I'm writing Rspec tests. Not going so well! I have a reasonable User model test, but that's because I found it online (https://github.com/RailsApps/rails3-devise-rspec-cucumber/) and was able to add to it by following Michael Hartl's excellent "Ruby on Rails 3 Tutorial".</p>
  
  <p>My real problem is controller test and integration tests, especially controller tests. Initially I thought I'd be able to convert the tests in Michael's book, and I have to a small degree, but it's slow progress and I seem to be constantly hitting my head against a brick wall - partly, I think, because I don't know Rspec and capybara so well (have made some very dumb mistakes) but also because I don't really understand Devise well enough and am wondering if Devise plays as nicely as it might with Rspec; I read somewhere that, because Devise is Rack based, it might not always work as one might expect with Rspec. Don't know if that's true or not?</p>
  
  <p>I know some people will wonder why this might be necessary since Devise is a gem and therefore already tested but I've had a couple of instances where changes elsewhere have broken login or registration without me immediately realizing. I think a good set of controller &amp; integration tests would have solved this.</p>
  
  <p>If I was able to do this myself I would and I'd publish it for others but, so far, writing these tests has been extremely painful and I really need to move on to other things.</p>
  
  <p>I'm sure I wouldn't be the only one who could use this. Anyone know of a such a suite of tests?</p>
  
  <p><strong>In response to Jesse's kind offer of help...</strong></p>
  
  <p>Here is my registrations_controller_spec. The comments in "should render the 'edit' page" show the sort of things I am struggling with. Also, "should create a user" has some things I've tried to test but not been able to:</p>
  
  <pre><code>require File.dirname(__FILE__) + '/../spec_helper'
  
  describe Users::RegistrationsController do
    include Devise::TestHelpers
    fixtures :all
    render_views
  
    before(:each) do
      @request.env["devise.mapping"] = Devise.mappings[:user]
    end
  
    describe "POST 'create'" do
      describe "failure" do
        before(:each) do
          @attr = { :email =&gt; "", :password =&gt; "",
                    :password_confirmation =&gt; "", :display_name =&gt; "" }
        end
  
        it "should not create a user" do
          lambda do
            post :create, :user_registration =&gt; @attr
          end.should_not change(User, :count)
        end
  
        it "should render the 'new' page" do
          post :create, :user_registration =&gt; @attr
          response.should render_template('new')
        end
      end
  
      describe "success" do
        before(:each) do
          @attr = { :email =&gt; "user@example.com",
                    :password =&gt; "foobar01", :password_confirmation =&gt; "foobar01", :display_name =&gt; "New User" }
        end
  
        it "should create a user" do
          lambda do
            post :create, :user =&gt; @attr
            response.should redirect_to(root_path)
            #response.body.should have_selector('h1', :text =&gt; "Sample App")
            #response.should have_css('h1', :text =&gt; "Sample App")
            #flash[:success].should == "A message with a confirmation link has been sent to your email address. Please open the link to activate your account."
            #response.should have_content "A message with a confirmation link has been sent to your email address. Please open the link to activate your account."
          end.should change(User, :count).by(1)
        end
  
      end
  
    end
  
    describe "PUT 'update'" do
      before(:each) do
        @user = FactoryGirl.create(:user)
        @user.confirm! # or set a confirmed_at inside the factory. Only necessary if you are using the confirmable module
        sign_in @user
      end
  
      describe "Failure" do
  
        before(:each) do
          # The following information is valid except for display_name which is too long (max 20 characters)
          @attr = { :email =&gt; @user.email, :display_name =&gt; "Test", :current_password =&gt; @user.password }
        end
  
        it "should render the 'edit' page" do
          put :update, :id =&gt; subject.current_user, :user =&gt; @attr
  
          # HAVE PUT THE DEBUGS THAT I'D LIKE TO GET WORKING FIRST
          # Would like to be able to debug and check I'm getting the error(s) I'm expecting
          puts subject.current_user.errors.messages # doesn't show me the errors
          # Would like to be able to debug what html is being returned:
          puts page.html # only return the first line of html
  
          # Would like to be able to determine that this test is failing for the right reasons
          response.should have_content "Display name is too long (maximum is 20 characters)" # doesn't work
  
          response.should render_template('edit')
        end
      end
  
      describe "Success" do
  
        it "should change the user's display name" do
          @attr = { :email =&gt; @user.email, :display_name =&gt; "Test", :current_password =&gt; @user.password }
          put :update, :id =&gt; subject.current_user, :user =&gt; @attr
          subject.current_user.reload
          response.should redirect_to(root_path)
          subject.current_user.display_name == @attr[:display_name]
        end
  
      end
    end
  
    describe "authentication of edit/update pages" do
  
      describe "for non-signed-in users" do
  
        before(:each) do
          @user = FactoryGirl.create(:user)
        end
  
        describe "for non-signed-in users" do
  
          it "should deny access to 'edit'" do
            get :edit, :id =&gt; @user
            response.should redirect_to(new_user_session_path)
          end
  
          it "should deny access to 'update'" do
            put :update, :id =&gt; @user, :user =&gt; {}
            response.should redirect_to(new_user_session_path)
          end
  
        end
  
      end
    end
  
  end
  </code></pre>