Donn Felker
Donn Felker

Reputation: 9651

Using RSpec to test a layout

What is the best way to test logic in a rails 3 layout?

Example: when a user signs into my site, if they have not completed the onboarding process I show them an alert at the top of the screen on ALL pages. This logic was placed into the application layout. I simply check the logged in user for a particular key. If the key is NOT present I show the alert. As soon as the key is present (meaning they've completed the onboarding) I DO NOT show the alert.

Currently I'm attempting to do this with a view test, but I'm getting all sorts of ActionView::Template::Error: undefined methodauthenticate' for nil:NilClass` errors by including the application layout and I cant seem to test this feature.

I need to make sure I have this under test because if for some reason one of my devs accidentally breaks this feature (view showing up with onboarding is not complete) we need to know immediately upon build.

The code that I'm trying to test in my layout looks like this:

<% if user_signed_in? %>
    <% unless current_user.has_completed_onboarding? %>
      <div class="alert">
        You cannot accept payments from your clients until you set up your payment gateway.
        <%= link_to "Set up your", payment_gateway_path %> payment gateway. Its quick, we promise. :)
      </div>
    <% end %>
<% end %>

I want to make sure that if they onboarding details have NOT been provided that this message will show and if they have been provided, then do not show this message.

Upvotes: 10

Views: 2768

Answers (2)

mohamagdy
mohamagdy

Reputation: 2093

The error you got ActionView::Template::Error: undefined method authenticate for nil:NilClass is caused by the user_signed_in? method call in the view. You can handle this by stubbing the user_signed_in? method in your tests as @shioyama showed in the code.

The following code shows how to stub the user_signed_in? method and return true if you wanted the if statement in your view to be executed or false if you don't. view.stub(:user_signed_in?).and_return(true)

Upvotes: 2

Chris Salzberg
Chris Salzberg

Reputation: 27374

You can test your layout just like any other view. Just create a file application.html.erb_spec.rb (replace erb by haml if necessary) in spec/views/layouts/, and in that file write up your specs as you normally would, e.g.:

require 'spec_helper'

describe 'layouts/application' do

  context 'signed-in user' do

    before { view.stub(:user_signed_in?) { true } }

    context 'completed onboarding' do

      before do
        user = double('user')
        user.stub(:has_completed_onboarding?) { false }
        assign(:current_user, user)
      end

      it "should display alert" do
        render
        rendered.should have_selector('.alert')
      end

    end

    ...

  end

  context 'signed-out user' do
    ...
  end

  ...

end

I do this with one of my apps and it works no problem, so I don't see why it wouldn't work for your case as well.

Upvotes: 14

Related Questions