Middleware not always called in capybara feature test (with rack-test)

700 Views Asked by At

I have a gem I'm working on that uses a railtie to add a middleware. Very simple stuff, followed the rails guides section almost exactly. Works fine in development/staging/production.

The middleware initializes a hash-like object in the env at a particular key.

But in my capybara tests, this key is only sometimes initialized. I added a debugger to the middleware and found that it isn't called every time I use the visit method.

What's more is that in this particular spec file, there are 4 examples, and each example calls visit once. But when I run the spec file, the middleware is sometimes called 3 times and sometimes called 2 times. Obviously the middleware stack should be called for every request.


tl;dr: sometimes calling visit in my capybara feature specs (with rack-test driver) does not result in my middleware stack being called.


Help?

  • ruby 2.0.0-p353
  • rails 4.0.2
  • capybara 2.2.1
  • rack-test 0.6.2

EDIT: This is some of the relevant code here: how the middleware is added and what it does. MyGem::Middleware#call is only sometimes called when using Capybara's visit method.

# railtie.rb
module MyGem
  class Railtie < Rails::Railtie
    initializer "my_gem.configure_rails_initialization" do |app|
      app.middleware.use MyGem::Middleware
    end
  end
end

# middleware.rb
module MyGem
  class Middleware
    def initialize(app, options={})
      @app = app
      # options unused
    end

    def call(env)
      # using a special internal version of the Rack::Session::Cookie class
      session = MyGem::Rack::Session::Cookie.new(
        @app,
        :coder => MyGem::Rack::Session::Cookie::Base64::Marshal.new,
        :key => ENV_SESSION_KEY,
        :path => '/',
        :domain => domain(env),
        :expire_after => 6.weeks.to_i, # seconds till this expires
        :secret => 'my_gem_secret_14f1c4ad25a6be00fe53f5fd2d746167',
      )

      # use Rack::Session:Cookie method
      session.context(env, @app)
    end
  end
end
1

There are 1 best solutions below

0
On

Figured it out!

I was also adding a Warden hook that expected the env key to be added after signing users in and out, and if the Warden::Manager middleware was added prior to my gem's middleware, then it would error out when running my hook that expected that env key to be set.

Solution was to do this in my railtie:

app.middleware.insert_before Warden::Manager, MyGem::Middleware