client-api 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/client-api.rb +17 -0
- data/lib/client-api/base.rb +72 -0
- data/lib/client-api/loggers.rb +22 -0
- data/lib/client-api/request.rb +74 -0
- data/lib/client-api/settings.rb +35 -0
- data/lib/client-api/validator.rb +180 -0
- data/lib/client-api/version.rb +3 -0
- metadata +125 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 354bd06d34542ca2e3010787df486062955a1bed02e442085dad030bb93fa8fd
|
4
|
+
data.tar.gz: 7992b72abafc9da352d16ae1a8e47f84daaa21b41b79b6954b3bea5ec1f3fc97
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5efb106c06984cc6544c846dc66eacca7af085576b285ca71f00802498f9fd75057fa4ffc299e1238f7ee7adb5d75162014f81db5fa6283c325740cdf26324b4
|
7
|
+
data.tar.gz: 9d9132ed137314a0b828fa56073efdca4a437abeda66731faecea9ada65dbabe23d822bc34b9a3a7cfa0f92d6533c0e1ef396ae63e8606277803337ea2bf129e
|
data/lib/client-api.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require "client-api/version"
|
2
|
+
require "client-api/settings"
|
3
|
+
require "client-api/base"
|
4
|
+
require "client-api/request"
|
5
|
+
require "client-api/validator"
|
6
|
+
require "client-api/loggers"
|
7
|
+
|
8
|
+
RSpec.configure do |config|
|
9
|
+
config.add_setting :base_url
|
10
|
+
config.add_setting :headers
|
11
|
+
config.add_setting :basic_auth
|
12
|
+
config.add_setting :json_output
|
13
|
+
config.add_setting :time_out
|
14
|
+
config.include ClientApi
|
15
|
+
end
|
16
|
+
|
17
|
+
include Loggers
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require_relative 'request'
|
2
|
+
|
3
|
+
module ClientApi
|
4
|
+
|
5
|
+
class Api < ClientApi::Request
|
6
|
+
|
7
|
+
include ClientApi
|
8
|
+
|
9
|
+
def get(url, headers = nil)
|
10
|
+
@output = get_request(url, :headers => headers)
|
11
|
+
post_logger if $logger
|
12
|
+
end
|
13
|
+
|
14
|
+
def post(url, body, headers = nil)
|
15
|
+
@output = post_request(url, :body => body, :headers => headers)
|
16
|
+
post_logger if $logger
|
17
|
+
end
|
18
|
+
|
19
|
+
def delete(url, headers = nil)
|
20
|
+
@output = delete_request(url, :headers => headers)
|
21
|
+
post_logger if $logger
|
22
|
+
end
|
23
|
+
|
24
|
+
def put(url, body, headers = nil)
|
25
|
+
@output = put_request(url, :body => body, :headers => headers)
|
26
|
+
post_logger if $logger
|
27
|
+
end
|
28
|
+
|
29
|
+
def patch(url, body, headers = nil)
|
30
|
+
@output = patch_request(url, :body => body, :headers => headers)
|
31
|
+
post_logger if $logger
|
32
|
+
end
|
33
|
+
|
34
|
+
def status
|
35
|
+
@output.code.to_i
|
36
|
+
end
|
37
|
+
|
38
|
+
def body
|
39
|
+
if [200, 201, 204].include? status
|
40
|
+
unless json_output['Dirname'] == nil
|
41
|
+
FileUtils.mkdir_p "#{json_output['Dirname']}"
|
42
|
+
File.open("./output/#{json_output['Filename']}.json", "wb") {|file| file.puts JSON.pretty_generate(JSON.parse(@output.body))}
|
43
|
+
end
|
44
|
+
JSON.parse(@output.body)
|
45
|
+
else
|
46
|
+
JSON.parse(@output.message)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def message
|
51
|
+
@output.message
|
52
|
+
end
|
53
|
+
|
54
|
+
def post_logger
|
55
|
+
(@output.body.nil? || @output.body == "{}") ? res_body = 'empty response body' : res_body = body
|
56
|
+
|
57
|
+
$logger.debug("Response code == #{@output.code.to_i}")
|
58
|
+
$logger.debug("Response body == #{res_body}")
|
59
|
+
$logger.debug("=====================================================================================")
|
60
|
+
end
|
61
|
+
|
62
|
+
alias :code :status
|
63
|
+
alias :resp :body
|
64
|
+
end
|
65
|
+
|
66
|
+
def payload(path)
|
67
|
+
JSON.parse(File.read(path))
|
68
|
+
end
|
69
|
+
|
70
|
+
alias :schema_from_json :payload
|
71
|
+
|
72
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
module Loggers
|
4
|
+
|
5
|
+
def logger=(logs)
|
6
|
+
output_logs_dir = logs['Dirname']
|
7
|
+
output_logs_filename = logs['Filename']
|
8
|
+
|
9
|
+
now = (Time.now.to_f * 1000).to_i
|
10
|
+
$logger = Logger.new(STDOUT)
|
11
|
+
$logger.datetime_format = '%Y-%m-%d %H:%M:%S'
|
12
|
+
Dir.mkdir("./#{output_logs_dir}") unless File.exist?("./#{output_logs_dir}")
|
13
|
+
|
14
|
+
if logs['StoreFilesCount'] && (logs['StoreFilesCount'] != nil || logs['StoreFilesCount'] != {} || logs['StoreFilesCount'] != empty)
|
15
|
+
file_count = Dir["./#{output_logs_dir}/*.log"].length
|
16
|
+
Dir["./#{output_logs_dir}/*.log"].sort_by {|f| File.ctime(f)}.reverse.last(file_count - "#{logs['StoreFilesCount']}".to_i).map {|junk_file| File.delete(junk_file)} if file_count > logs['StoreFilesCount']
|
17
|
+
end
|
18
|
+
|
19
|
+
$logger = Logger.new(File.new("#{output_logs_dir}/#{output_logs_filename}_#{now}.log", 'w'))
|
20
|
+
$logger.level = Logger::DEBUG
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module ClientApi
|
2
|
+
|
3
|
+
class Request
|
4
|
+
|
5
|
+
include ClientApi
|
6
|
+
|
7
|
+
def get_request(url, options = {})
|
8
|
+
connect(url)
|
9
|
+
pre_logger(:log_url => uri(url), :log_header => header(options), :log_method => 'GET') if $logger
|
10
|
+
@http.get(uri(url).request_uri, initheader = header(options))
|
11
|
+
end
|
12
|
+
|
13
|
+
def post_request(url, options = {})
|
14
|
+
body = options[:body] || {}
|
15
|
+
connect(url)
|
16
|
+
pre_logger(:log_url => uri(url), :log_header => header(options), :log_body => body, :log_method => 'POST') if $logger
|
17
|
+
@http.post(uri(url).path, body.to_json, initheader = header(options))
|
18
|
+
end
|
19
|
+
|
20
|
+
def delete_request(url, options = {})
|
21
|
+
connect(url)
|
22
|
+
pre_logger(:log_url => uri(url), :log_header => header(options), :log_method => 'DELETE') if $logger
|
23
|
+
@http.delete(uri(url).path, initheader = header(options))
|
24
|
+
end
|
25
|
+
|
26
|
+
def put_request(url, options = {})
|
27
|
+
body = options[:body] || {}
|
28
|
+
connect(url)
|
29
|
+
pre_logger(:log_url => uri(url), :log_header => header(options), :log_body => body, :log_method => 'PUT') if $logger
|
30
|
+
@http.put(uri(url).path, body.to_json, initheader = header(options))
|
31
|
+
end
|
32
|
+
|
33
|
+
def patch_request(url, options = {})
|
34
|
+
body = options[:body] || {}
|
35
|
+
connect(url)
|
36
|
+
pre_logger(:log_url => uri(url), :log_header => header(options), :log_body => body, :log_method => 'PATCH') if $logger
|
37
|
+
@http.patch(uri(url).path, body.to_json, initheader = header(options))
|
38
|
+
end
|
39
|
+
|
40
|
+
def uri(args)
|
41
|
+
%w[http://, https://].any? {|protocol| args.include? protocol} ? URI.parse(args) : URI.parse(base_url + args)
|
42
|
+
end
|
43
|
+
|
44
|
+
def connect(args)
|
45
|
+
http = Net::HTTP.new(uri(args).host, uri(args).port)
|
46
|
+
|
47
|
+
if uri(args).scheme == "https"
|
48
|
+
http.use_ssl = true
|
49
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
50
|
+
http.read_timeout = time_out.to_i
|
51
|
+
@http = http
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def basic_encode(options = {})
|
56
|
+
'Basic ' + ["#{options[:username]}:#{options[:password]}"].pack('m0')
|
57
|
+
end
|
58
|
+
|
59
|
+
def header(options = {})
|
60
|
+
mod_headers = options[:headers] || {}
|
61
|
+
headers['Authorization'] = basic_encode(:username => basic_auth['Username'], :password => basic_auth['Password'])
|
62
|
+
headers.merge(mod_headers)
|
63
|
+
end
|
64
|
+
|
65
|
+
def pre_logger(options = {})
|
66
|
+
options[:log_body] = 'not available' if options[:log_body].nil?
|
67
|
+
$logger.debug("Requested method == #{options[:log_method]}")
|
68
|
+
$logger.debug("Requested url == #{options[:log_url]}")
|
69
|
+
$logger.debug("Requested headers == #{options[:log_header]}")
|
70
|
+
$logger.debug("Requested body == #{options[:log_body]}")
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
module ClientApi
|
4
|
+
|
5
|
+
def self.configure
|
6
|
+
RSpec.configure do |config|
|
7
|
+
yield config
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.configuration
|
12
|
+
RSpec.configuration
|
13
|
+
end
|
14
|
+
|
15
|
+
def base_url
|
16
|
+
ClientApi.configuration.base_url || ''
|
17
|
+
end
|
18
|
+
|
19
|
+
def headers
|
20
|
+
ClientApi.configuration.headers || ''
|
21
|
+
end
|
22
|
+
|
23
|
+
def basic_auth
|
24
|
+
ClientApi.configuration.basic_auth || ''
|
25
|
+
end
|
26
|
+
|
27
|
+
def json_output
|
28
|
+
ClientApi.configuration.json_output || ''
|
29
|
+
end
|
30
|
+
|
31
|
+
def time_out
|
32
|
+
ClientApi.configuration.time_out || ''
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,180 @@
|
|
1
|
+
require "json-schema"
|
2
|
+
|
3
|
+
module ClientApi
|
4
|
+
|
5
|
+
def validate(res, *options)
|
6
|
+
options.map do |data|
|
7
|
+
raise_error('key (or) operator is not given!') if data[:key].nil? && data[:operator].nil?
|
8
|
+
raise_error('value (or) type is not given!') if data[:value].nil? && data[:type].nil?
|
9
|
+
|
10
|
+
@resp = res
|
11
|
+
key = data[:key].split("->")
|
12
|
+
|
13
|
+
key.map do |method|
|
14
|
+
method = method.to_i if is_num?(method)
|
15
|
+
@resp = @resp.send(:[], method)
|
16
|
+
end
|
17
|
+
|
18
|
+
value ||= data[:value]
|
19
|
+
operator = data[:operator]
|
20
|
+
type = data[:type] if data[:type] || data[:type] != {} || !data[:type].empty?
|
21
|
+
|
22
|
+
case operator
|
23
|
+
when '=', '==', 'eql?', 'equal', 'equal?'
|
24
|
+
# value validation
|
25
|
+
expect(value).to eq(@resp) if value != nil
|
26
|
+
|
27
|
+
# datatype validation
|
28
|
+
if (type == "boolean" || type == "bool") && value.nil?
|
29
|
+
expect(%w[TrueClass, FalseClass].any? {|bool| @resp.class.to_s.include? bool}).to be true
|
30
|
+
else
|
31
|
+
expect(datatype(type, value)).to eq(@resp.class)
|
32
|
+
end
|
33
|
+
|
34
|
+
when '!', '!=', '!eql?', 'not equal', '!equal?'
|
35
|
+
# value validation
|
36
|
+
expect(value).not_to eq(@resp) if value != nil
|
37
|
+
|
38
|
+
# datatype validation
|
39
|
+
if (type == "boolean" || type == "bool") && value.nil?
|
40
|
+
expect(%w[TrueClass, FalseClass].any? {|bool| @resp.class.to_s.include? bool}).not_to be true
|
41
|
+
else
|
42
|
+
expect(datatype(type, value)).not_to eq(@resp.class)
|
43
|
+
end
|
44
|
+
else
|
45
|
+
raise_error('operator not matching')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def validate_schema(param1, param2)
|
51
|
+
expected_schema = JSON::Validator.validate(param1, param2)
|
52
|
+
expect(expected_schema).to be true
|
53
|
+
end
|
54
|
+
|
55
|
+
def datatype(type, value)
|
56
|
+
if (type.downcase == 'string') || (type.downcase.== 'str')
|
57
|
+
String
|
58
|
+
elsif (type.downcase.== 'integer') || (type.downcase.== 'int')
|
59
|
+
Integer
|
60
|
+
elsif (type.downcase == 'symbol') || (type.downcase == 'sym')
|
61
|
+
Symbol
|
62
|
+
elsif (type.downcase == 'array') || (type.downcase == 'arr')
|
63
|
+
Array
|
64
|
+
elsif (type.downcase == 'object') || (type.downcase == 'obj')
|
65
|
+
Object
|
66
|
+
elsif (type.downcase == 'boolean') || (type.downcase == 'bool')
|
67
|
+
value === true ? TrueClass : FalseClass
|
68
|
+
elsif type.downcase == 'float'
|
69
|
+
Float
|
70
|
+
elsif type.downcase == 'hash'
|
71
|
+
Hash
|
72
|
+
elsif type.downcase == 'complex'
|
73
|
+
Complex
|
74
|
+
elsif type.downcase == 'rational'
|
75
|
+
Rational
|
76
|
+
elsif type.downcase == 'fixnum'
|
77
|
+
Fixnum
|
78
|
+
elsif type.downcase == 'falseclass'
|
79
|
+
FalseClass
|
80
|
+
elsif type.downcase == 'trueclass'
|
81
|
+
TrueClass
|
82
|
+
elsif type.downcase == 'bignum'
|
83
|
+
Bignum
|
84
|
+
else
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def is_num?(str)
|
89
|
+
if Float(str)
|
90
|
+
true
|
91
|
+
end
|
92
|
+
rescue ArgumentError, TypeError
|
93
|
+
false
|
94
|
+
end
|
95
|
+
|
96
|
+
def validate_json(actual, expected)
|
97
|
+
param1 = JSON.parse(actual.to_json)
|
98
|
+
param2 = JSON.parse(expected.to_json)
|
99
|
+
|
100
|
+
@actual_key, @actual_value = [], []
|
101
|
+
deep_traverse(param2) do |path, value|
|
102
|
+
if !value.is_a?(Hash)
|
103
|
+
key_path = path.map! {|k| k}
|
104
|
+
@actual_key << key_path.join("->").to_s
|
105
|
+
@actual_value << value
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
Hash[@actual_key.zip(@actual_value)].map do |data|
|
110
|
+
@resp = param1
|
111
|
+
key = data[0].split("->")
|
112
|
+
|
113
|
+
key.map do |method|
|
114
|
+
method = method.to_i if is_num?(method)
|
115
|
+
@resp = @resp.send(:[], method)
|
116
|
+
end
|
117
|
+
|
118
|
+
value = data[1]
|
119
|
+
@assert, @final_assert, @overall = [], [], []
|
120
|
+
|
121
|
+
if !value.is_a?(Array)
|
122
|
+
expect(value).to eq(@resp)
|
123
|
+
else
|
124
|
+
@resp.each_with_index do |resp, i|
|
125
|
+
value.to_a.each_with_index do |val1, j|
|
126
|
+
val1.to_a.each_with_index do |val2, k|
|
127
|
+
if resp.to_a.include? val2
|
128
|
+
@assert << true
|
129
|
+
else
|
130
|
+
@assert << false
|
131
|
+
end
|
132
|
+
end
|
133
|
+
@final_assert << @assert
|
134
|
+
@assert = []
|
135
|
+
|
136
|
+
if @resp.count == @final_assert.count
|
137
|
+
@final_assert.each_with_index do |result, i|
|
138
|
+
if result.count(true) == val1.count
|
139
|
+
@overall << true
|
140
|
+
break
|
141
|
+
elsif @final_assert.count == i+1
|
142
|
+
expect(value).to eq(@resp)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
@final_assert = []
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
if @overall.count(true) == value.count
|
152
|
+
return
|
153
|
+
else
|
154
|
+
expect(value).to eq(@resp)
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def deep_traverse(hash, &block)
|
162
|
+
stack = hash.map {|k, v| [[k], v]}
|
163
|
+
|
164
|
+
while not stack.empty?
|
165
|
+
key, value = stack.pop
|
166
|
+
yield(key, value)
|
167
|
+
if value.is_a? Hash
|
168
|
+
value.each do |k, v|
|
169
|
+
if v.is_a?(String) then
|
170
|
+
if v.empty? then
|
171
|
+
v = nil
|
172
|
+
end
|
173
|
+
end
|
174
|
+
stack.push [key.dup << k, v]
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
end
|
metadata
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: client-api
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- prashanth-sams
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-10-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: json-schema
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '2.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '2.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: logger
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.0'
|
83
|
+
description: client-api helps you write api tests quickly using rspec with different
|
84
|
+
levels of validations
|
85
|
+
email:
|
86
|
+
- sams.prashanth@gmail.com
|
87
|
+
executables: []
|
88
|
+
extensions: []
|
89
|
+
extra_rdoc_files: []
|
90
|
+
files:
|
91
|
+
- lib/client-api.rb
|
92
|
+
- lib/client-api/base.rb
|
93
|
+
- lib/client-api/loggers.rb
|
94
|
+
- lib/client-api/request.rb
|
95
|
+
- lib/client-api/settings.rb
|
96
|
+
- lib/client-api/validator.rb
|
97
|
+
- lib/client-api/version.rb
|
98
|
+
homepage: https://github.com/prashanth-sams/client-api
|
99
|
+
licenses:
|
100
|
+
- MIT
|
101
|
+
metadata:
|
102
|
+
homepage_uri: https://github.com/prashanth-sams/client-api
|
103
|
+
source_code_uri: https://github.com/prashanth-sams/client-api
|
104
|
+
documentation_uri: https://www.rubydoc.info/github/prashanth-sams/client-api/master
|
105
|
+
bug_tracker_uri: https://github.com/prashanth-sams/client-api/issues
|
106
|
+
post_install_message:
|
107
|
+
rdoc_options: []
|
108
|
+
require_paths:
|
109
|
+
- lib
|
110
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - ">="
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: '0'
|
115
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - ">="
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '0'
|
120
|
+
requirements: []
|
121
|
+
rubygems_version: 3.0.4
|
122
|
+
signing_key:
|
123
|
+
specification_version: 4
|
124
|
+
summary: HTTP Rest API client for RSpec Api Test framework
|
125
|
+
test_files: []
|