title: How can I test that a user can't access a page with access reserved to another user?
body: <p>I manually give access to certain Deals to customers I choose on Active Admin panel.
  It's working "manually" but <strong>I don't know how to test that a customer can access his Deal but can't access another customer's deals.</strong></p>
  
  <p>Each deal pages can only be viewed by customer associated with it (owned by them if you want) by using CanCan abilities: </p>
  
  <pre><code>class CustomerAbility
    include CanCan::Ability
  
  
    def initialize(customer)
      alias_action :show, :to =&gt; :read #this will have no change on the alias :read!
  
      customer ||= Customer.new # guest customer (not logged in)
      if customer.has_role? :superadmin 
        Log.info "Ability: customer is superadmin"
        can :manage, :all     
      else
        can :read, Deal do |Deal|
          # Only customers who have been granted access in Active Admin to a deal can read 
          deal.customers.include? customer 
        end
      end
    end
  
  end
  </code></pre>
  
  <p>Note: Customer and Deals have a has_many through relationships (a deal has many customers / a customer has many deals)</p>
  
  <p>Here is the test i have so far but it's not right i think as i'm a TDD newbie:)</p>
  
  <pre><code>require 'spec_helper'
  require "cancan/matchers"
  
  describe DealsController do      
  
    let(:customer)      { FactoryGirl.create(:customer) } 
    let(:deal)          { FactoryGirl.create(:deal, :customers =&gt; [customer]) } # in array as a deal has_many customers    
  
    context "As signed-in CUSTOMER" do 
  
      before do
        @customer = FactoryGirl.create(:customer) #the factory builds a basic customer i.e with 'prospect role' attributed by default
        @deal     = FactoryGirl.create(:deal, :customers =&gt; [@customer])
        sign_in_customer @customer
  
      end
  
      describe "the customer can read=view the page of a Deal HE OWNS " do
        it "can access the page" do
          get :deal_page, { :id =&gt; @deal.id }
          expect(current_path).to eq(???????)
          # WHAT TO DO HERE ??????
          page.should have_content('here is your deal, dear customer')
        end 
      end
  
      describe "the customer can NOT read the page of a Deal he does not own =owned by other customers and is redirected his customer panel" do
        it "can't access the page" do
          get :deal_page, { :id =&gt; @deal.id }
          expect(response).to redirect_to(customer_panel_path)
          # WHAT TO DO HERE ??????
          flash[:alert].should eql("Sorry but you could not access this page as it is not your Deal!")
        end 
      end
  
    end
  </code></pre>
  
  <p><strong>The issue</strong> is that in the tests where customer SHOULD have access to the deal page, rspec says he does not as he is redirected to the homepage. I know where the problem is: i feel rspec does not know that this created customer is assocciated with this created deal.</p>
  
  <p>And here is where i define the Deal page: controllers/deals_controller.rb</p>
  
  <pre><code>def deal_page
      @deal = Deal.find(params[:id])
      authorize! :read, @deal # only allow customers with authorized access in AA; sends to customer_ability
  
      respond_to do |format|
        format.html 
        format.json { render json: @deal }
      end
    end
  </code></pre>
  
  <p>It seems a pretty basic test: how can i test that a customer can't access another customer pages (with a has_many relationship customer/deals) but i don'"t know how to tackle this issue.</p>
  
  <p><strong># Edit</strong>
  If it helps to the issue:</p>
  
  <p>appplication_controller.rb</p>
  
  <pre><code>class ApplicationController &lt; ActionController::Base
  
    protect_from_forgery
  
    # handle Cancan authorization exception
    rescue_from CanCan::AccessDenied do |exception|
      exception.default_message = t("errors.application_controller_exception_messages.only_open_to_admin")
      if current_user # if it's user redirect to main HP
        redirect_to root_path, :alert =&gt; exception.message
      else # if it's a Customer redirect him to client interface HP
        redirect_to customer_panel_path, :alert=&gt; exception.message
      end
    end
  
    def current_ability 
      @current_ability ||= case
                           when current_user
                             UserAbility.new(current_user)
                           when current_customer 
                             CustomerAbility.new(current_customer)
                           end
    end
  </code></pre>
  
  <p><strong>EDIT #2</strong></p>
  
  <p>Evidence of this failure is that the following test SUCCEED when is should FAIL:</p>
  
  <pre><code>it "can access the deal page" do
          get :deal_page, { :id =&gt; @deal.id }
          expect(current_path).to eq(customer_panel_path)            
        end
  </code></pre>
  
  <p><strong>Edit #3</strong></p>
  
  <p>Using Dave advice, wrote</p>
  
  <pre><code>before do
        @customer = FactoryGirl.create(:customer) #the factory builds a basic customer i.e with 'prospect role' attributed by default
        @deal    = FactoryGirl.create(:deal, :customers =&gt; [@customer])
        sign_in_customer @customer
      end
   (...)
   it "can access the DEAL he OWNS = HIS deals" do
          get :deal_page, { :id =&gt; @deal.id }
          expect(current_path).to eq(deal_page_path(@deal))
   end
  </code></pre>
  
  <p>but i get error:</p>
  
  <pre><code>DealsController As signed-in CUSTOMER with access to the deal page
   Failure/Error: expect(current_path).to eq(deal_page_path(@deal))
  
         expected: "/deals_page/2"
              got: "/customer_panel"
  
         (compared using ==)
  </code></pre>
  
  <p>It's like I don't manage to tell him that the created customer is associated with the created deal so the customer should be able to access it.</p>
  
  <p>Here is the detailed test log:</p>
  
  <pre><code>Deal Exists (0.8ms)  SELECT 1 AS one FROM "deals" WHERE LOWER("deals"."deal_code") = LOWER('CHA1FR001') LIMIT 1      
    SQL (2.1ms)  INSERT INTO "deals" ("admin_user_id", "client_contact_point_name", blabla") VALUES ($1, $2, blabla...) RETURNING "id"  [["admin_user_id", 1], ["client_contact_point_name", "henri Cool"], ["client_contact_point_profile_url", "http://example.com"], ....blabla...]
    (...blabla)
    Customer Exists (0.6ms)  SELECT 1 AS one FROM "customers" WHERE (LOWER("customers"."email") = LOWER('person_1@example.com') AND "customers"."id" != 1) LIMIT 1
    (...blabla)
  Started GET "/customers/signin" for 127.0.0.1 at 2014-05-28 18:37:05 +0200
  Processing by Customers::SessionsController#new as HTML
    Rendered customers/sessions/new.html.erb within layouts/lightbox (40.0ms)
    Rendered layouts/_metas.html.erb (0.4ms)
    Rendered layouts/_messages.html.erb (0.7ms)
    Rendered layouts/_footer.html.erb (1.2ms)
  Completed 200 OK in 77ms (Views: 51.5ms | ActiveRecord: 0.0ms)
  Started POST "/customers/signin" for 127.0.0.1 at 2014-05-28 18:37:05 +0200
  Processing by Customers::SessionsController#create as HTML
    Parameters: {"utf8"=&gt;"✓", "customer"=&gt;{"email"=&gt;"person_1@example.com", "password"=&gt;"[FILTERED]"}, "commit"=&gt;"Log In"}
    Customer Load (4.0ms)  SELECT "customers".* FROM "customers" WHERE "customers"."email" = 'person_1@example.com' ORDER BY "customers"."id" ASC LIMIT 1
    SQL (1.0ms)  UPDATE "customers" SET "remember_created_at" = $1, "updated_at" = $2 WHERE "customers"."id" = 1  [["remember_created_at", 2014-05-28 16:37:05 UTC], ["updated_at", 2014-05-28 18:37:05 +0200]]
    SQL (1.2ms)  UPDATE "customers" SET "last_sign_in_at" = $1, "current_sign_in_at" = $2, "last_sign_in_ip" = $3, "current_sign_in_ip" = $4, "sign_in_count" = $5, "updated_at" = $6 WHERE "customers"."id" = 1  [["last_sign_in_at", 2014-05-28 16:37:05 UTC], ["current_sign_in_at", 2014-05-28 16:37:05 UTC], ["last_sign_in_ip", "127.0.0.1"], ["current_sign_in_ip", "127.0.0.1"], ["sign_in_count", 1], ["updated_at", 2014-05-28 18:37:05 +0200]]
  **Redirected to http://www.example.com/customer_panel**
  Completed 302 Found in 33ms (ActiveRecord: 6.2ms)
  Started GET "/customer_panel" for 127.0.0.1 at 2014-05-28 18:37:05 +0200
  Processing by ClientreportingPagesController#index as HTML
    Customer Load (0.5ms)  SELECT "customers".* FROM "customers" WHERE "customers"."id" = 1 ORDER BY "customers"."id" ASC LIMIT 1
     (1.2ms)  SELECT COUNT(*) FROM "roles" INNER JOIN "customers_roles" ON "roles"."id" = "customers_roles"."role_id" WHERE "customers_roles"."customer_id" = $1 AND (((roles.name = 'prospect') AND (roles.resource_type IS NULL) AND (roles.resource_id IS NULL)))  [["customer_id", 1]]      
    Rendered layouts/_metas.html.erb (0.2ms)
     (0.8ms)  SELECT COUNT(*) FROM "roles" INNER JOIN "customers_roles" ON "roles"."id" = "customers_roles"."role_id" WHERE "customers_roles"."customer_id" = $1 AND (((roles.name = 'superadmin') AND (roles.resource_type IS NULL) AND (roles.resource_id IS NULL)))  [["customer_id", 1]]
    Rendered layouts/client_interface_partials
  Completed 200 OK in 34ms (Views: 27.7ms | ActiveRecord: 2.4ms)
  Processing by DealsController#deal_page as HTML
    Parameters: {"id"=&gt;"2"}
  **Completed 401 Unauthorized in 1ms**
    Rendered text template (0.1ms)
     (0.5ms)  ROLLBACK TO SAVEPOINT active_record_2
     (0.3ms)  ROLLBACK TO SAVEPOINT active_record_1
     (0.3ms)  ROLLBACK
  </code></pre>
  
  <p>2 lines in BOLD seem strange to me: </p>
  
  <ul>
  <li><p>why does rspec send to example.com/customer_panel (i have in my spec_helper file told rspec that i test locally: Capybara.asset_host = 'http:// localhost:3000') ?</p></li>
  <li><p>and why does rspec experience a "Completed 401 Unauthorized in 1ms at the end ?</p></li>
  </ul>