'How to correctly use Devise + Confirmable + fixtures

I'm using Devise + Confirmable for user authentication and Minitest + Capybara + fixtures for testing. I can make working logged in tests for users as long as I included some form of login (either with the helper login_as(@user) or going to the login page with Capybara) and the line@user.confirm before running.

How can I confirm users in the fixture itself though so I don't have to include this line every time.

Right now I have:

confirmed_at: Time.now

in the yml, but it doesn't seem to make a difference.

Here is a working sample test, if it's useful for illustration:

def setup
    @user = users(:user)
  end

   test 'user should be redirected to profile edit on first login' do
     @user.confirm
     visit(new_user_session_path)
     fill_in('user_email', :with => @user.email)
     fill_in('user_password', :with => 'foobar')
     click_button('Log in')
     assert_current_path(edit_user_registration_path)
   end

and the user fixture:

user:
  email: [email protected]
  confirmed_at: Time.now
  encrypted_password: <%= Devise::Encryptor.digest(User, 'foobar') %>
  sign_in_count: 0


Solution 1:[1]

I updated my answer. The solution of the problem is found here. You need to configure it as in the guide and call the method user.confirm! inside the module ControllerMacros method def login_user

https://github.com/plataformatec/devise/wiki/How-To:-Test-controllers-with-Rails-3-and-4-(and-RSpec)#controller-specs

Open source github page of a complete Devise Rspec Project including testing

https://github.com/RailsApps/rails-devise/blob/master/spec/features/users/sign_in_spec.rb


you are trying to set

User.confirmed_at = Time.now

but confirmed_at has datetime datatype at least in my postegresql db, so this may depend on the db you are using.

confirmed_at: datetime

So this is the Time.now format

pry(main)> Time.now
=> 2017-03-14 11:14:06 +0100

While this is is the User.confirmed_at format

user.confirmed_at
=> Sun, 05 Mar 2017 15:05:03 UTC +00:00

So you should use a compatible format/variable, try to search the DateTime class for a compatible format that includes the UTC as DateTime.now returns:

[40] pry(main)> DateTime.now
=> Tue, 14 Mar 2017 11:19:25 +0100

DateTime has a utc() method. If I run this it is almost what is needed.

DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24)).utc

DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24)).utc
=> 2005-02-21 16:11:12 UTC

Check the DateTime api and if needed you can check the utc() method on github

DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24))     # => Mon, 21 Feb 2005 10:11:12 -0600
DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24)).utc # => Mon, 21 Feb 2005 16:11:12 UTC


# File activesupport/lib/active_support/core_ext/date_time/calculations.rb, line 168
def utc
  utc = new_offset(0)

  Time.utc(
    utc.year, utc.month, utc.day,
    utc.hour, utc.min, utc.sec + utc.sec_fraction
  )
end

http://api.rubyonrails.org/classes/DateTime.html#method-i-utc

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Lee McAlilly