This has taken me longer to figure out than it should, so I am writing this down in the hopes of saving other people some time and headache.

TLDR

use env "rack.session", {account_id: account.id} before issuing any other Rack::Test methods, and it just works.

I was switching my small Hanami project over to rodauth from a handrolled solution with warden following Tim Riley’s tutorial. Which went mostly great, except for the part where most of my tests broke.

Warden comes with a login_as test helper that makes it really easy to test, but rodauth does not have something similar.

In my feature specs it wasn’t really a problem, I just had to extract a small function that clicked on the sign-in link, filled out the form and submitted it.

But the request test seemed more daunting. But they actually were a lot easier than expected. Rack::Test provides an env method, and setting rack.session to the values you need in the session just works. For rodauth to consider you logged in, setting account_id to the account’s id is all that is needed.

So a working request specs looks like this:

RSpec.describe "AuthenticationSpec", :db, type: :request do
  context "when action inherits from authenticated action" do
    context "when account is logged in" do
      let!(:account) do
        Factory[:account, name: "John Mastodon", email: "john.mastodon@example.com"]
      end

      it "succeeds" do
        env "rack.session", {account_id: account.id}

        get "/entries"

        expect(last_response.status).to be(200)
      end
    end

    context "when there is no account" do
      it "rejects the request, redirects" do
        get "/entries"

        expect(last_response).to be_redirect
      end
    end
  end
end