Skip to content

HTTP REST API client for testing APIs based on the ruby’s RSpec framework that binds a complete api automation framework setup within itself

License

Notifications You must be signed in to change notification settings

prashanth-sams/client-api

 
 

Repository files navigation

ClientApi

Gem Version Build Status

HTTP Rest Api client for RSpec test automation framework that binds within itself

Features

  • Custom Header, URL, and Timeout support
  • Datatype and key-pair value validation
  • Single key-pair response validation
  • Multi key-pair response validation
  • JSON response schema validation
  • JSON response content validation
  • Response headers validation
  • JSON template as body and schema
  • Support to store JSON responses of each tests for the current run
  • Logs support for debug
  • Custom logs remover
  • Auto-handle SSL for http(s) schemes

Installation

Add this line to your application's Gemfile:

gem 'client-api'

And then execute:

$ bundle

Or install it yourself as:

$ gem install client-api

Import the library in your env file

require 'client-api'

#Usage outline

Add this config snippet in the spec_helper.rb file:

ClientApi.configure do |config|
  # all these configs are optional; comment out the config if not required
  config.base_url = 'https://reqres.in'
  config.headers = {'Content-Type' => 'application/json', 'Accept' => 'application/json'}
  config.basic_auth = {'Username' => 'ahamilton@apigee.com', 'Password' => 'myp@ssw0rd'}
  config.json_output = {'Dirname' => './output', 'Filename' => 'test'}
  config.time_out = 10  # in secs
  config.logger = {'Dirname' => './logs', 'Filename' => 'test', 'StoreFilesCount' => 2}
  
  # add this snippet only if the logger is enabled
  config.before(:each) do |scenario|
    ClientApi::Request.new(scenario)
  end
end

Create client-api object with custom variable

api = ClientApi::Api.new

RSpec test scenarios look like,

it "GET request" do
  api = ClientApi::Api.new
  
  api.get('/api/users')
  expect(api.status).to eq(200)
  expect(api.code).to eq(200)
  expect(api.message).to eq('OK')
end

it "POST request" do
  api.post('/api/users', {"name": "prashanth sams"})
  expect(api.status).to eq(201)
end

it "DELETE request" do
  api.delete('/api/users/3')
  expect(api.status).to eq(204)
end

it "PUT request" do
  api.put('/api/users/2', {"data":{"email":"prashanth@mail.com","first_name":"Prashanth","last_name":"Sams"}})
  expect(api.status).to eq(200)
end

it "PATCH request" do
  api.patch('/api/users/2', {"data":{"email":"prashanth@mail.com","first_name":"Prashanth","last_name":"Sams"}})
  expect(api.status).to eq(200)
end

Validation shortcuts

Default validation

key features

  • datatype validation
  • key-pair value validation
  • single key-pair validation
  • multi key-pair validation
General Syntax Syntax | Model 2 Syntax | Model 3
validate(
    api.body,
    {
        key: '', 
        value: '', 
        operator: '', 
        type: ''
    }
)
            
validate(
    api.body,
    {
        key: '', 
        value: '', 
        operator: '', 
    }
)
            
validate(
    api.body,
    {
        key: '', 
        operator: '', 
        type: ''
    },
    {
        key: '', 
        operator: '', 
        value: ''
    }
)
            

JSON response content validation

key benefits

  • the most recommended validation for fixed / static JSON responses
  • validates each JSON content value

what to know?

  • replace null with nil in the expected json (whenever applicable); cos, ruby don't know what is null
General Syntax Syntax | Model 2
validate_json(
    {
        "data":
            {
                "id": 2,
                "first_name": "Prashanth",
                "last_name": "Sams",
            }
    },
    {
        "data":
            {
                "id": 2,
                "first_name": "Prashanth",
                "last_name": "Sams",
            }
    }
)
            
validate_json(
    api.body,
    {
        "data":
            {
                "id": 2,
                "first_name": "Prashanth",
                "last_name": "Sams",
                "link": nil
            }
    }
)
            

JSON response headers validation

key benefits

  • validates any response headers
General Syntax Syntax | Model 2
validate_headers(
    api.response_headers,
    {
       key: '',
       operator: '',
       value: ''
    }
)
            
validate_headers(
    api.response_headers,
    {
       key: "connection",
       operator: "!=",
       value: "open"
    },{
       key: "vary",
       operator: "==",
       value: "Origin, Accept-Encoding"
    }
)
            

#General usage

Using json template as body

it "JSON template as body" do
  api.post('/api/users', payload("./data/request/post.json"))
  expect(api.status).to eq(201)
end

Add custom header

it "GET request with custom header" do
  api.get('/api/users', {'Content-Type' => 'application/json', 'Accept' => 'application/json'})
  expect(api.status).to eq(200)
end

it "PATCH request with custom header" do
  api.patch('/api/users/2', {"data":{"email":"prashanth@mail.com","first_name":"Prashanth","last_name":"Sams"}}, {'Content-Type' => 'application/json', 'Accept' => 'application/json'})
  expect(api.status).to eq(200)
end

Full url support

it "full url", :post do
  api.post('https://api.enterprise.apigee.com/v1/organizations/ahamilton-eval',{},{'Authorization' => 'Basic YWhhbWlsdG9uQGFwaWdlZS5jb206bXlwYXNzdzByZAo'})
  expect(api.status).to eq(403)
end

Basic Authentication

ClientApi.configure do |config|
  ...
  config.basic_auth = {'Username' => 'ahamilton@apigee.com', 'Password' => 'myp@ssw0rd'}
end

Custom Timeout in secs

ClientApi.configure do |config|
  ...
  config.time_out = 10 # in secs
end

Output as json template

ClientApi.configure do |config|
  ...
  config.json_output = {'Dirname' => './output', 'Filename' => 'sample'}
end

Logs

Logs are optional in this library; you can do so through config in spec_helper.rb. The param,StoreFilesCount will keep the custom files as logs; you can remove it, if not needed.

ClientApi.configure do |config|
  ...
  config.logger = {'Dirname' => './logs', 'Filename' => 'test', 'StoreFilesCount' => 5}
  
  config.before(:each) do |scenario|
    ClientApi::Request.new(scenario)
  end
end

#Validation | more info.

Validate .json response values and datatype; validates single key-pair values in the response

validate(
    api.body,
    {
        "key": "name",
        "value": "prashanth sams",
        "operator": "==",
        "type": 'string'
    }
)

Multi key-pair values response validator

validate(
    api.body,
    {
        "key": "name",
        "value": "prashanth sams",
        "operator": "==",
        "type": 'string'
    },
    {
        "key": "event",
        "operator": "eql?",
        "type": 'boolean'
    },
    {
         "key": "posts->1->enabled",
         "value": false,
         "operator": "!=",
         "type": 'boolean'
    },
    {
        "key": "profile->name->id",
        "value": 2,
        "operator": "==",
        "type": 'integer'
    },
    {
        "key": "profile->name->id",
        "value": 2,
        "operator": "<",
        "type": 'integer'
    },
    {
        "key": "profile->name->id",
        "operator": ">=",
        "value": 2,
    },
    {
        "key": "post1->0->name",
        "operator": "contains",
        "value": "Sams"
    },
    {
        "key": "post2->0->id",
        "operator": "include",
        "value": 34,
        "type": 'integer'
    },
    {
        "key": "post1->0->available",
        "value": true,
        "operator": "not contains",
        "type": "boolean"
    }
)

Operator
Type options
Equal =, ==, eql?, equal, equal?
Not Equal !, !=, !eql?, not equal, !equal?
Greater than >, >=, greater than, greater than or equal to
Less than <, <=, less than, less than or equal to, lesser than, lesser than or equal to
Contains contains, has, contains?, has?, include, include?
Not Contains not contains, !contains, not include, !include
Datatype
Type options
String string, str
Integer integer, int
Symbol symbol, sym
Boolean boolean, bool
Array array, arr
Object object, obj
Float float
Hash hash
Complex complex
Rational rational
Fixnum fixnum
Falseclass falseclass, false
Trueclass trueclass, true
Bignum bignum

JSON response schema validation

validate_schema(
  schema_from_json('./data/schema/get_user_schema.json'),
  {
    "data":
        {
            "id": 2,
            "email": "janet.weaver@reqres.in",
            "firstd_name": "Janet",
            "last_name": "Weaver",
            "avatar": "https://s3.amazonaws.com/uifaces/faces/twitter/josephstein/128.jpg"
        }
  }
)
validate_schema(
    {
        "required": [
            "data"
        ],
        "type": "object",
        "properties": {
            "data": {
                "type": "object",
                "required": [
                    "id", "email", "first_name", "last_name", "avatar"
                ],
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "email": {
                        "type": "string"
                    },
                    "first_name": {
                        "type": "string"
                    },
                    "last_name": {
                        "type": "string"
                    },
                    "avatar": {
                        "type": "string"
                    }
                }
            }
        }
    },
  {
    "data":
        {
            "id": 2,
            "email": "janet.weaver@reqres.in",
            "first_name": "Janet",
            "last_name": "Weaver",
            "avatar": "https://s3.amazonaws.com/uifaces/faces/twitter/josephstein/128.jpg"
        }
  }
)
validate_schema(
    schema_from_json('./data/schema/get_user_schema.json'),
    api.body
)

JSON response content validation

json response content value validation as a structure

actual_body = {
    "posts":
        {
            "prashanth": {
                "id": 1,
                "title": "Post 1"
            },
            "sams": {
                "id": 2,
                "title": "Post 2"
            }
        },
    "profile":
        {
            "id": 44,
            "title": "Post 44"
        }
}

validate_json( actual_body,
{
    "posts":
        {
            "prashanth": {
                "id": 1,
                "title": "Post 1"
            },
            "sams": {
                "id": 2
            }
        },
    "profile":
        {
            "title": "Post 44"
        }
})
validate_json( api.body,
  {
      "posts": [
          {
              "id": 2,
              "title": "Post 2"
          }
      ],
      "profile": {
          "name": "typicode"
      }
  }
)

Response headers validation

validate_headers(
  api.response_headers,
  {
    key: "connection",
    operator: "!=",
    value: "open"
  },
  {
    key: "vary",
    operator: "==",
    value: "Origin, Accept-Encoding"
  }
)

Is there a demo available for this gem?

Yes, you can use this demo as an example, https://github.com/prashanth-sams/client-api

rake spec

About

HTTP REST API client for testing APIs based on the ruby’s RSpec framework that binds a complete api automation framework setup within itself

Topics

Resources

License

Code of conduct

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •