RSpec::RequestDescriber

repository·main·Indexed 41 days ago

https://github.com/r7kamura/rspec-request_describer

A plugin for RSpec that creates self-documenting request specs by parsing the HTTP method and path directly from the RSpec.describe string. It automatically defines the request subject and provides let helpers for headers, params, and path parameters (e.g., /users/:user_id) to streamline the definition of HTTP request tests.

Tokens
2K
Snippets
8
Records
8
Agent score
2%

What's inside RSpec::RequestDescriber

  1. Write self-documenting request specs

    main

    Define your HTTP method and URL path in the top-level RSpec.describe string. The plugin automatically parses this string to define the subject (which executes the request) and provides helper let variables for http_method, path, headers, and params.

    RSpec.describe 'GET /users' do
      it 'returns 200' do
        subject
        expect(response).to have_http_status(200)
      end
    end
  2. Install and setup RSpec::RequestDescriber

    main

    To use RSpec::RequestDescriber, add the gem to your Gemfile within the :test group and include the module in your RSpec configuration for request specs.

    # Gemfile
    group :test do
      gem 'rspec-request_describer'
    end
    
    # spec/rails_helper.rb
    RSpec.configure do |config|
      config.include RSpec::RequestDescriber, type: :request
    end
  3. How to use RSpec::RequestDescriber in your specs

    main

    To use RSpec::RequestDescriber, include the module in your RSpec configuration (typically in rails_helper.rb or spec_helper.rb).

    When included, the module automatically sets up a subject that executes send_request. It also provides several let helpers that you can override in your request specs to define the request behavior:

    • headers: A hash of HTTP headers. The plugin automatically transforms these into the appropriate Rack env format (e.g., Content-Type becomes CONTENT_TYPE, while reserved names like host are handled specifically).
    • params: A hash of request parameters. If the Content-Type header is set to application/json, these params will be automatically converted to a JSON string.
    • request_body: An internal helper used to determine the body sent to the request based on the params and headers configuration.

    Important Requirement: Your describe or context blocks must follow a specific naming convention to define the HTTP method and path. The format must be "METHOD /path" (e.g., describe 'GET /users').

    # In your spec file
    RSpec::RequestDescriber.included do
      # The module provides these helpers for you to override
      let(:headers) { { 'Authorization' => 'Bearer token' } }
      let(:params) { { id: 1 } }
    end
    
    # The describe block MUST follow the 'METHOD /path' pattern
    describe 'GET /users/:id' do
      # You can define methods for path parameters here
      def id
        '123'
      end
    
      it 'returns success' do
        expect(subject.status).to eq(200)
      end
    end
  4. Define request paths and methods using describe blocks

    main

    The plugin parses the description of your describe or context block to determine the HTTP method and the URL path.

    Format: "METHOD /path"

    • Supported Methods: DELETE, GET, HEAD, PATCH, POST, PUT.
    • Path Parameters: You can use colon-prefixed symbols in the path (e.g., /:id). To resolve these, define a method in your spec with the same name as the parameter.

    If the description does not match the "METHOD /path" pattern, the plugin will raise an RSpec::RequestDescriber::IncorrectDescribe error.

    # Correct usage
    describe 'POST /users' do
      # ...
    end
    
    # Usage with path parameters
    describe 'GET /users/:user_id' do
      def user_id
        '42'
      end
    
      it 'works' do
        # The path becomes '/users/42'
        expect(subject.path).to eq('/users/42')
      end
    end
  5. Modify request parameters

    main

    To customize request parameters (query params or body), override the params hash within a context or before block.

    RSpec.describe 'GET /users' do
      context 'with sort parameter' do
        before do
          params['sort'] = 'id'
        end
    
        it 'returns 200 with expected JSON body' do
          subject
          expect(response).to have_http_status(200)
          expect(response.parsed_body).to match(
            [
              hash_including('id' => 1),
              hash_including('id' => 2),
            ]
          )
        end
      end
    end
  6. Modify request headers

    main

    To customize request headers, override the headers hash within a context or before block. The plugin uses the headers let variable to pass options to the request.

    RSpec.describe 'GET /users' do
      context 'with Authorization header' do
        before do
          headers['Authorization'] = 'token 12345'
        end
    
        it 'returns 200' do
          subject
          expect(response).to have_http_status(200)
        end
      end
    end
  7. Use path parameters in URLs

    main

    You can use colon-prefixed symbols in the description string (e.g., /users/:user_id) to represent path parameters. The plugin will look for a method or let variable matching the symbol name (e.g., user_id) and embed its return value into the URL path.

    RSpec.describe 'GET /users/:user_id' do
      let(:user) do
        User.create(name: 'alice')
      end
    
      let(:user_id) do
        user.id
      end
    
      it 'returns 200' do
        subject
        expect(response).to have_http_status(200)
      end
    end
  8. Configure request headers and params

    main

    The plugin provides let helpers to control the request state.

    Headers

    Define headers using the headers hash. The plugin transforms these into Rack-compatible env keys.

    • Standard headers are prefixed with HTTP_ and hyphens are replaced with underscores (e.g., X-Api-Key becomes HTTP_X_API_KEY).
    • Reserved Headers: content-type, host, and https are treated specially and do not receive the HTTP_ prefix.

    Parameters and JSON Body

    Define request parameters using the params hash.

    • If headers includes {'Content-Type' => 'application/json'}, the params hash is automatically serialized to a JSON string for the request body.
    • Otherwise, the params are merged into a standard hash format.
    # Example: JSON request
    describe 'POST /api/data' do
      let(:headers) { { 'Content-Type' => 'application/json' } }
      let(:params) { { name: 'test', value: 123 } }
    
      it 'sends JSON' do
        # The request body will be '{"name":"test","value":123}'
        expect(subject.body).to include('"name":"test"')
      end
    end