Use cookies.signed[:user_id] in capybara tests

I have this code to authenticate channel subscribers:

module ApplicationCable
  class Connection < ActionCable::Connection::Base
    identified_by :current_user

    def connect
      self.current_user = find_verified_user
    end

    protected
      def find_verified_user
        if current_user = User.find_by(id: cookies.signed[:user_id])
          current_user
        else
          reject_unauthorized_connection
        end
      end
  end
end

And everything works fine. The problem is in feature tests. When I run this test:

require 'rails_helper'

feature 'Chat room' do
  scenario "send one message" do
    user = create(:user)
    login_as(user, :scope => :user)

    expect {
      fill_in 'message', with: 'hello friend'
      click_button 'Send'
      byebug
    }.to change(Message, :count).by(1)
    expect(current_path).to eq root_path
    expect(page).to have_content 'hello friend'
  end
end

The test log, says that the "An unauthorized connection attempt was rejected". Since the cookie is empty, it is not able to authenticate.

So how can I set the cookies in capybara tests?

I tried something do this cookies.signed[:user_id] = user.id in the test but it does not work.

How can I set the cookie like this cookies.signed[:user_id] = user.id in tests?

Answers


Assuming that the login_as you're calling is from the Warden test helpers, what it does is set up so that the next request sets the session cookie in the response. Because of this you probably need to visit a page after calling login_as. Additionally, since clicking 'Send' is asynchronous you need to wait for something to change before checking that Message.count has changed, and you really shouldn't be using with .eq with current_path if you want non-flaky tests. So all combined something like

#don't visit the page where you can fill in the message before calling login_as


scenario "send one message" do
  user = create(:user)
  login_as(user, :scope => :user)
  visit 'the path to the page where you can fill in a message'
  expect {
    fill_in 'message', with: 'hello friend'
    click_button 'Send'
    expect(page).to have_css('#messages', text:'hello friend') # adjust selector depending on where the message is supposed to appear
    expect(page).to have_current_path(root_path)
  }.to change(Message, :count).by(1)
end

should work for you


Need Your Help

Passing generic type of webmethod

c# silverlight c#-3.0 web-services asmx

im passing a array of KeyValuePair&lt;string,string&gt;[]

How to find and delete 15 days older files with Cron Jobs?

bash shell bin

I want to delete the files, which are older than 15 days. Files directory is