Back to Repositories

Testing RegexpValidator Parameter Validation in grape

This test suite examines the RegexpValidator functionality in the Grape API framework, focusing on parameter validation using regular expressions. The tests verify both simple string validation and array-based validation scenarios, including custom error messages and nested parameter structures.

Test Coverage Overview

The test suite provides comprehensive coverage of RegexpValidator functionality:

  • Basic string parameter validation against regex patterns
  • Array parameter validation with regex constraints
  • Nested parameter structures with regex validation
  • Custom error message handling
  • Edge cases including nil values and empty strings

Implementation Analysis

The testing approach utilizes RSpec’s context-based structure to organize test scenarios logically. It implements request-response testing patterns specific to Grape API validation, using GET requests to verify parameter validation behavior. The tests leverage RSpec’s expect syntax for assertions and custom message validation.

Technical Details

  • Testing Framework: RSpec
  • API Framework: Grape
  • Validation Type: RegexpValidator
  • HTTP Method: GET
  • Response Format: JSON
  • Test Pattern: Request-Response cycle

Best Practices Demonstrated

The test suite demonstrates several testing best practices:

  • Organized test structure using nested contexts
  • Comprehensive edge case coverage
  • Clear test case descriptions
  • Consistent assertion patterns
  • Isolated test scenarios
  • Proper error message validation

ruby-grape/grape

spec/grape/validations/validators/regexp_validator_spec.rb

            
# frozen_string_literal: true

describe Grape::Validations::Validators::RegexpValidator do
  let_it_be(:app) do
    Class.new(Grape::API) do
      default_format :json

      resources :custom_message do
        params do
          requires :name, regexp: { value: /^[a-z]+$/, message: 'format is invalid' }
        end
        get do
        end

        params do
          requires :names, type: { value: Array[String], message: 'can\'t be nil' }, regexp: { value: /^[a-z]+$/, message: 'format is invalid' }
        end
        get 'regexp_with_array' do
        end
      end

      params do
        requires :name, regexp: /^[a-z]+$/
      end
      get do
      end

      params do
        requires :names, type: Array[String], regexp: /^[a-z]+$/
      end
      get 'regexp_with_array' do
      end

      params do
        requires :people, type: Hash do
          requires :names, type: Array[String], regexp: /^[a-z]+$/
        end
      end
      get 'nested_regexp_with_array' do
      end
    end
  end

  context 'custom validation message' do
    context 'with invalid input' do
      it 'refuses inapppopriate' do
        get '/custom_message', name: 'invalid name'
        expect(last_response.status).to eq(400)
        expect(last_response.body).to eq('{"error":"name format is invalid"}')
      end

      it 'refuses empty' do
        get '/custom_message', name: ''
        expect(last_response.status).to eq(400)
        expect(last_response.body).to eq('{"error":"name format is invalid"}')
      end
    end

    it 'accepts nil' do
      get '/custom_message', name: nil
      expect(last_response.status).to eq(200)
    end

    it 'accepts valid input' do
      get '/custom_message', name: 'bob'
      expect(last_response.status).to eq(200)
    end

    context 'regexp with array' do
      it 'refuses inapppopriate items' do
        get '/custom_message/regexp_with_array', names: ['invalid name', 'abc']
        expect(last_response.status).to eq(400)
        expect(last_response.body).to eq('{"error":"names format is invalid"}')
      end

      it 'refuses empty items' do
        get '/custom_message/regexp_with_array', names: ['', 'abc']
        expect(last_response.status).to eq(400)
        expect(last_response.body).to eq('{"error":"names format is invalid"}')
      end

      it 'refuses nil items' do
        get '/custom_message/regexp_with_array', names: [nil, 'abc']
        expect(last_response.status).to eq(400)
        expect(last_response.body).to eq('{"error":"names can\'t be nil"}')
      end

      it 'accepts valid items' do
        get '/custom_message/regexp_with_array', names: ['bob']
        expect(last_response.status).to eq(200)
      end

      it 'accepts nil instead of array' do
        get '/custom_message/regexp_with_array', names: nil
        expect(last_response.status).to eq(200)
      end
    end
  end

  context 'invalid input' do
    it 'refuses inapppopriate' do
      get '/', name: 'invalid name'
      expect(last_response.status).to eq(400)
      expect(last_response.body).to eq('{"error":"name is invalid"}')
    end

    it 'refuses empty' do
      get '/', name: ''
      expect(last_response.status).to eq(400)
      expect(last_response.body).to eq('{"error":"name is invalid"}')
    end
  end

  it 'accepts nil' do
    get '/', name: nil
    expect(last_response.status).to eq(200)
  end

  it 'accepts valid input' do
    get '/', name: 'bob'
    expect(last_response.status).to eq(200)
  end

  context 'regexp with array' do
    it 'refuses inapppopriate items' do
      get '/regexp_with_array', names: ['invalid name', 'abc']
      expect(last_response.status).to eq(400)
      expect(last_response.body).to eq('{"error":"names is invalid"}')
    end

    it 'refuses empty items' do
      get '/regexp_with_array', names: ['', 'abc']
      expect(last_response.status).to eq(400)
      expect(last_response.body).to eq('{"error":"names is invalid"}')
    end

    it 'refuses nil items' do
      get '/regexp_with_array', names: [nil, 'abc']
      expect(last_response.status).to eq(400)
      expect(last_response.body).to eq('{"error":"names is invalid"}')
    end

    it 'accepts valid items' do
      get '/regexp_with_array', names: ['bob']
      expect(last_response.status).to eq(200)
    end

    it 'accepts nil instead of array' do
      get '/regexp_with_array', names: nil
      expect(last_response.status).to eq(200)
    end
  end

  context 'nested regexp with array' do
    it 'refuses inapppopriate' do
      get '/nested_regexp_with_array', people: 'invalid name'
      expect(last_response.status).to eq(400)
      expect(last_response.body).to eq('{"error":"people is invalid, people[names] is missing, people[names] is invalid"}')
    end
  end
end