Back to Repositories

Testing Request Parameter and Header Processing in grape

This test suite validates the Grape::Request class functionality, focusing on parameter handling and HTTP header processing in the Grape framework. The tests ensure proper request parameter formatting and header manipulation for web API requests.

Test Coverage Overview

The test suite provides comprehensive coverage of request parameter processing and HTTP header handling.

Key areas tested include:
  • Parameter key stringification and symbolization
  • Routing argument handling
  • HTTP header processing and formatting
  • Edge cases for non-HTTP headers and symbolic header names

Implementation Analysis

The testing approach uses RSpec’s describe/context blocks to organize related test scenarios hierarchically. The implementation leverages let blocks for setup and employs Rack::MockRequest for simulating HTTP requests.

Notable patterns include:
  • Shared context setup using let statements
  • Mock request environment configuration
  • Parameter builder extension testing

Technical Details

Testing tools and configuration:
  • RSpec testing framework
  • Rack::MockRequest for HTTP request simulation
  • ActiveSupport::HashWithIndifferentAccess for parameter handling
  • Grape::Extensions::Hash::ParamBuilder for parameter processing

Best Practices Demonstrated

The test suite exhibits strong testing practices through organized test structure and thorough coverage.

Notable practices include:
  • Isolated test contexts
  • Clear test descriptions
  • Comprehensive edge case coverage
  • DRY principle application through shared setup
  • Consistent assertion patterns

ruby-grape/grape

spec/grape/request_spec.rb

            
# frozen_string_literal: true

describe Grape::Request do
  let(:default_method) { Rack::GET }
  let(:default_params) { {} }
  let(:default_options) do
    {
      method: method,
      params: params
    }
  end
  let(:default_env) do
    Rack::MockRequest.env_for('/', options)
  end
  let(:method) { default_method }
  let(:params) { default_params }
  let(:options) { default_options }
  let(:env) { default_env }

  let(:request) do
    described_class.new(env)
  end

  describe '#params' do
    let(:params) do
      {
        a: '123',
        b: 'xyz'
      }
    end

    it 'by default returns stringified parameter keys' do
      expect(request.params).to eq(ActiveSupport::HashWithIndifferentAccess.new('a' => '123', 'b' => 'xyz'))
    end

    context 'when build_params_with: Grape::Extensions::Hash::ParamBuilder is specified' do
      let(:request) do
        described_class.new(env, build_params_with: Grape::Extensions::Hash::ParamBuilder)
      end

      it 'returns symbolized params' do
        expect(request.params).to eq(a: '123', b: 'xyz')
      end
    end

    describe 'with grape.routing_args' do
      let(:options) do
        default_options.merge('grape.routing_args' => routing_args)
      end
      let(:routing_args) do
        {
          version: '123',
          route_info: '456',
          c: 'ccc'
        }
      end

      it 'cuts version and route_info' do
        expect(request.params).to eq(ActiveSupport::HashWithIndifferentAccess.new(a: '123', b: 'xyz', c: 'ccc'))
      end
    end
  end

  describe '#headers' do
    let(:options) do
      default_options.merge(request_headers)
    end

    describe 'with http headers in env' do
      let(:request_headers) do
        {
          'HTTP_X_GRAPE_IS_COOL' => 'yeah'
        }
      end
      let(:x_grape_is_cool_header) do
        'x-grape-is-cool'
      end

      it 'cuts HTTP_ prefix and capitalizes header name words' do
        expect(request.headers).to eq(x_grape_is_cool_header => 'yeah')
      end
    end

    describe 'with non-HTTP_* stuff in env' do
      let(:request_headers) do
        {
          'HTP_X_GRAPE_ENTITY_TOO' => 'but now we are testing Grape'
        }
      end

      it 'does not include them' do
        expect(request.headers).to eq({})
      end
    end

    describe 'with symbolic header names' do
      let(:request_headers) do
        {
          HTTP_GRAPE_LIKES_SYMBOLIC: 'it is true'
        }
      end
      let(:env) do
        default_env.merge(request_headers)
      end
      let(:grape_likes_symbolic_header) do
        'grape-likes-symbolic'
      end

      it 'converts them to string' do
        expect(request.headers).to eq(grape_likes_symbolic_header => 'it is true')
      end
    end
  end
end