teamcapybara/capybara · error · CapybaraError

Capybara.disable_animation supports either a String (the css

Error message

Capybara.disable_animation supports either a String (the css selector to disable) or a boolean

What it means

AnimationDisabler.selector_for accepts only a CSS selector String or true (mapped to the universal selector '*'); any other value of Capybara.disable_animation raises CapybaraError when the disabler middleware is constructed at server boot. false/nil are filtered out before this code in the normal server path, so the error means a truthy value of the wrong type was configured.

Source

Thrown at lib/capybara/server/animation_disabler.rb:13

# frozen_string_literal: true

module Capybara
  class Server
    class AnimationDisabler
      def self.selector_for(css_or_bool)
        case css_or_bool
        when String
          css_or_bool
        when true
          '*'
        else
          raise CapybaraError, 'Capybara.disable_animation supports either a String (the css selector to disable) or a boolean'
        end
      end

      def initialize(app)
        @app = app
        @disable_css_markup = format(DISABLE_CSS_MARKUP_TEMPLATE,
                                     selector: self.class.selector_for(Capybara.disable_animation))
        @disable_js_markup = +DISABLE_JS_MARKUP_TEMPLATE
      end

      def call(env)
        status, headers, body = @app.call(env)
        return [status, headers, body] unless html_content?(headers)

        nonces = directive_nonces(headers).transform_values { |nonce| "nonce=\"#{nonce}\"" if nonce && !nonce.empty? }
        response = Rack::Response.new([], status, headers)

        body.each { |html| response.write insert_disable(html, nonces) }

View on GitHub (pinned to 15b5fdb76e)

Solutions

  1. Use Capybara.disable_animation = true to disable animations for all elements
  2. Or pass one CSS selector string covering the animated parts: Capybara.disable_animation = '.animated, .carousel'
  3. To opt out, leave it nil or set false rather than a sentinel like :none

Example fix

# before
Capybara.disable_animation = :all

# after
Capybara.disable_animation = true
# or target specific animated elements:
# Capybara.disable_animation = '.animation, .transition'
Defensive patterns

Strategy: validation

Validate before calling

def valid_disable_animation?(v)
  v.is_a?(String) || [true, false, nil].include?(v)
end

raise 'bad Capybara.disable_animation value' unless valid_disable_animation?(Capybara.disable_animation)

Type guard

def normalized_disable_animation(v)
  case v
  when String, true, false, nil then v
  else true # treat any other truthy intent as disable-all
  end
end

Capybara.disable_animation = normalized_disable_animation(raw_setting)

Try / catch

begin
  Capybara.current_session
rescue Capybara::CapybaraError => e
  raise unless e.message.include?('disable_animation')
  Capybara.disable_animation = true
  retry
end

Prevention

When it happens

Trigger: Setting Capybara.disable_animation = :all (or 1, ['*'], or any other truthy non-String) in spec_helper/rails_helper and then creating a session that boots the test server (run_server true with a Rack app); also directly constructing Capybara::Server::AnimationDisabler with such a config.

Common situations: Copy-pasted config assuming 'truthy means all'; passing an array of selectors (only one selector string is supported); intending 'disable everywhere' with the :all symbol; wrong branch of an env conditional setting a sentinel value.

Related errors


AI-assisted analysis of teamcapybara/capybara@15b5fdb76e (2026-08-21). Data as JSON: /api/errors/d3e4f74ef1c7f2c7. Report an issue: GitHub.