janko / rodauth-rails

Rails integration for Rodauth authentication framework
https://github.com/jeremyevans/rodauth
MIT License
571 stars 40 forks source link

Add controller test integration #102

Closed janko closed 2 years ago

janko commented 2 years ago

This allows controllers calling Rodauth to be controller-tested, via ActionController::TestCase that's internally used by RSpec's controller specs. It ensures Rodauth instance(s) are set in request env, converts Rodauth responses into controller responses, and provides the #rodauth method.

# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
  before_action -> { rodauth.require_authentication }

  def index
    @articles = current_account.articles.all
  end

  # ...
end
# test/controllers/articles_controller_test.rb
class ArticlesControllerTest < ActionController::TestCase
  test "authentication" do
    get :index

    assert_response 302
    assert_redirected_to rodauth.login_path

    account = Account.create(email: "user@example.com", password: "secret", status: "verified")
    login(account)

    get :index

    assert_response 200
  end

  private

  def login(account)
    rodauth.account_from_login(account.email)
    rodauth.login_session("password")
  end
end

Afterwards I would consider the possibility of adding some login/logout test helper methods, similar to what Devise has.

wdperson commented 2 years ago

@janko I tested this out and I no longer get the error. It seems to be working, however, I can't seem to get a 200 success response. Only a 302 redirect. This is the only way I can get the test to pass:

  before(:each) do
    login(user)
  end

  it "should GET index" do
    get :index
    expect(response).to redirect_to("http://www.example.com/stores")
  end

If I update the test to do a second request to:

get :index

It fails saying the response was a 302 to "http://www.example.com/stores"

So, after signing in, it doesn't seem to be holding on to the session, but I may be wrong. A few other notes, which is we are using RSpec and also we have:

login_return_to_requested_location? true

set.

janko commented 2 years ago

That's strange. I'm not able to reproduce this in the test/controllers/test_controller_test.rb in this PR, nor in the rodauth-demo-rails app. What Rails version are you using, and is there something more in your Rodauth configuration? What you posted shouldn't affect this, as it's not used in #login_session.

wdperson commented 2 years ago

@janko I talked to one of my colleagues and we think the issue is somewhere in our application. So, I think this is a good update. Thank you for working on this. I really appreciate it.

janko commented 2 years ago

OK, thanks for the feedback, I will merge it shortly, and make a release tomorrow.

BTW, I ended up removing the #rodauth method, as to me it increases coupling of controller tests to Rodauth, and I didn't find that using Rodauth simplifies anything. This is the documented way to log in now:

account = Account.create!(email: "user@example.com", password: "secret", status: "verified")
session[:account_id] = account.id
session[:authenticated_by] = ["password"]