Tech Writers at PF
client-api is an open-source library (ruby gem), which is a HTTP REST API client for testing application APIs based on the ruby’s RSpec framework that binds a complete api automation framework setup within itself.
The client-api library reduces the effort of writing bulky lines of codes with simple and painless test steps. Debugging and validations are made easy and that greatly increases the end-user productivity.

List of client-api features
What features does client-api contain? Let me break them down:
- Custom Header, URL, Basic Auth, and Timeout support
- Datatype and key-pair value validation
- Single key-pair response validation
- Multi key-pair response validation
- JSON response content validation
- JSON response schema validation
- JSON response headers validation
- JSON template as a body and schema
- Support to store JSON responses of each tests for the current run
- Logs support for debugging
- Auto-handle SSL for http(s) schemes

Installation
Add this line to your application’s Gemfile:
gem 'client-api'
And then execute:
$ bundle
Or make a direct install:
$ gem install client-api
Import the library in your .env file
require 'client-api'
Usage outline
Add or remove the below optional configuration in the spec_helper.rb file, and make sure the values are updated that rely on your application.
ClientApi.configure do |config|
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
Initialize client-api object with custom variable and follow test steps,
api = ClientApi::Api.new
The RSpec test scenarios look like,
@api = ClientApi::Api.newit “GET request” do
@api.get(‘/api/users’)
expect(@api.status).to eq(200)
expect(@api.code).to eq(200)
expect(@api.message).to eq(‘OK’)
endit “POST request” do
@api.post(‘/api/users’, {“name”: “prashanth sams”})
expect(@api.status).to eq(201)
endit “DELETE request” do
@api.delete(‘/api/users/3’)
expect(@api.status).to eq(204)
endit “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)
endit “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
Validations
This modern library helps you to do different types of validations.
- Default validation
- JSON response content validation
- JSON response headers validation
- JSON response schema validation (3rd party)
Default validation
Default validation is a generic validation used by any global automation framework. ‘Datatype’ or ‘Key-pair value’ assertions are exclusive to this validation type. Please refer to the Github source for more details on the datatype and operators used in this library.
Key Features
- Datatype validation
- Key-pair value validation
- Single key-pair validation
- Multi key-pair validation
# Syntax | Model 1
validate(
api.body,
{
key: ”,
value: ”,
operator: ‘==’,
type: ‘string’
}
)
# Syntax | Model 2
validate(
api.body,
{
key: ”,
operator: ‘!=’,
type: ‘boolean’
},
{
key: ‘data->0->post->id’,
operator: ‘contains’,
value: 40,
type: ‘integer’
}
)
JSON response content validation
Content validation is the most recommended validation type for fixed or static JSON responses.
Are you bored of writing too much of assertions for the same API response unit? whew! not anymore… try validate_json(actual_json, expected_json)
Key Benefits
- Validates each and every JSON content value including arrays and hashes
- Minimize writing multiple assertion steps for bulk JSON response body
Other Things to Note
- Replace null with nil in the expected JSON (whenever applicable); because, ruby doesn’t know what null is
# Syntax | Model 1
validate_json(
{
“data”:
{
“id”: 2,
“first_name”: “Prashanth”,
“last_name”: “Sams”,
}
},
{
“data”:
{
“id”: 2,
“first_name”: “Prashanth”,
“last_name”: “Sams”,
}
}
)
# Syntax | Model 2
validate_json(
api.body,
{
“data”:
{
“id”: 2,
“first_name”: “Prashanth”,
“last_name”: “Sams”,
“link”: nil
}
}
)
JSON response headers validation
The header validation is meant to validate any key-pair values in the response headers.
# Syntax | Model 1
validate_headers(
api.response_headers,
{
key: “connection”,
operator: “!=”,
value: “open”
},{
key: “vary”,
operator: “==”,
value: “Origin, Accept-Encoding”
}
)
My Top Tips
I have put together a list of features explained with tiny snippets for a quick understanding of the library in details below.
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 support
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
Response output as JSON template
ClientApi.configure do |config|
…
config.json_output = {‘Dirname’ => ‘./output’, ‘Filename’ => ‘sample’}
end
Logs
ClientApi.configure do |config|
…
config.logger = {‘Dirname’ => ‘./logs’, ‘Filename’ => ‘test’, ‘StoreFilesCount’ => 5}
config.before(:each) do |scenario|
ClientApi::Request.new(scenario)
end
end
Source: https://rubygems.org/gems/client-api
Github: https://github.com/prashanth-sams/client-api
That is it! Thanks for reading
If you liked this article and want to be part of our brilliant team of engineers that produced it, then have a look at our latest vacancies here.