client-api 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -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
@@ -0,0 +1,3 @@
1
+ module ClientApi
2
+ VERSION = "0.1.0".freeze
3
+ 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: []