api-tester 1.0.0 → 1.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +5 -5
  2. data/.github/dependabot.yml +15 -0
  3. data/.github/workflows/dependabot.yml +29 -0
  4. data/.github/workflows/push.yml +39 -0
  5. data/.github/workflows/test.yml +31 -0
  6. data/.rubocop.yml +171 -0
  7. data/Gemfile +2 -0
  8. data/Guardfile +70 -0
  9. data/README.md +65 -61
  10. data/Rakefile +8 -3
  11. data/api-tester.gemspec +28 -24
  12. data/changelog.txt +10 -0
  13. data/lib/api-tester/config.rb +17 -15
  14. data/lib/api-tester/definition/boundary_case.rb +5 -4
  15. data/lib/api-tester/definition/contract.rb +10 -5
  16. data/lib/api-tester/definition/endpoint.rb +58 -32
  17. data/lib/api-tester/definition/fields/array_field.rb +26 -21
  18. data/lib/api-tester/definition/fields/boolean_field.rb +17 -7
  19. data/lib/api-tester/definition/fields/email_field.rb +28 -11
  20. data/lib/api-tester/definition/fields/enum_field.rb +19 -12
  21. data/lib/api-tester/definition/fields/field.rb +52 -45
  22. data/lib/api-tester/definition/fields/number_field.rb +20 -6
  23. data/lib/api-tester/definition/fields/object_field.rb +37 -30
  24. data/lib/api-tester/definition/fields/plain_array_field.rb +25 -0
  25. data/lib/api-tester/definition/method.rb +8 -5
  26. data/lib/api-tester/definition/request.rb +43 -19
  27. data/lib/api-tester/definition/response.rb +35 -25
  28. data/lib/api-tester/method_case_test.rb +68 -54
  29. data/lib/api-tester/modules/benchmark_module.rb +35 -0
  30. data/lib/api-tester/modules/extra_verbs.rb +36 -10
  31. data/lib/api-tester/modules/format.rb +23 -7
  32. data/lib/api-tester/modules/good_case.rb +25 -10
  33. data/lib/api-tester/modules/good_variations.rb +69 -0
  34. data/lib/api-tester/modules/injection_module.rb +44 -23
  35. data/lib/api-tester/modules/missing_resource.rb +63 -0
  36. data/lib/api-tester/modules/required_fields.rb +51 -0
  37. data/lib/api-tester/modules/server_information.rb +14 -12
  38. data/lib/api-tester/modules/typo.rb +39 -14
  39. data/lib/api-tester/modules/unexpected_fields.rb +59 -0
  40. data/lib/api-tester/modules/unused_fields.rb +13 -7
  41. data/lib/api-tester/reporter/api_report.rb +25 -16
  42. data/lib/api-tester/reporter/missing_field_report.rb +11 -15
  43. data/lib/api-tester/reporter/report.rb +12 -13
  44. data/lib/api-tester/reporter/response_time_report.rb +24 -0
  45. data/lib/api-tester/reporter/status_code_report.rb +10 -4
  46. data/lib/api-tester/test_helper.rb +8 -6
  47. data/lib/api-tester/util/response_evaluator.rb +84 -56
  48. data/lib/api-tester/util/supported_verbs.rb +8 -5
  49. data/lib/api-tester/version.rb +3 -1
  50. data/lib/api-tester.rb +6 -3
  51. metadata +92 -27
  52. data/.travis.yml +0 -6
  53. data/lib/api-tester/reporter/missing_response_field_report.rb +0 -21
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ApiTester
4
+ # Report used for when response took too long
5
+ class ResponseTimeReport
6
+ attr_accessor :url, :verb, :payload, :max_time, :actual_time, :description
7
+
8
+ def initialize(url:, verb:, payload:, max_time:, actual_time:, description:)
9
+ self.url = url
10
+ self.verb = verb
11
+ self.payload = payload
12
+ self.max_time = max_time
13
+ self.actual_time = actual_time
14
+ self.description = description
15
+ end
16
+
17
+ def print
18
+ puts "#{description}:"
19
+ puts " #{verb} #{url} took #{actual_time}ms, the max time is #{max_time}ms:"
20
+ puts ' Payload:'
21
+ puts " #{payload}"
22
+ end
23
+ end
24
+ end
@@ -1,12 +1,18 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'api-tester/reporter/report'
2
4
 
3
5
  module ApiTester
6
+ # Report for when status code is different than expected
4
7
  class StatusCodeReport < Report
5
- attr_accessor :expected_status_code
6
- attr_accessor :actual_status_code
8
+ attr_accessor :expected_status_code, :actual_status_code
7
9
 
8
- def initialize description, url, request, expected_status_code, actual_status_code
9
- super description, url, request, expected_status_code, actual_status_code
10
+ def initialize(description:, url:, request:, expected_status_code:, actual_status_code:)
11
+ super description: description,
12
+ url: url,
13
+ request: request,
14
+ expected_response: expected_status_code,
15
+ actual_response: actual_status_code
10
16
  self.expected_status_code = expected_status_code
11
17
  self.actual_status_code = actual_status_code
12
18
  end
@@ -1,12 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ApiTester
4
+ # Interface for when things need to be done before or after an api call
2
5
  class TestHelper
3
- def before
4
- end
6
+ def initialize(url); end
7
+
8
+ def before; end
5
9
 
6
- def retrieve_param key
7
- end
10
+ def retrieve_param(key); end
8
11
 
9
- def after
10
- end
12
+ def after; end
11
13
  end
12
14
  end
@@ -1,75 +1,103 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ApiTester
4
+ # Class for evaluating responses against what is expected
2
5
  class ResponseEvaluator
3
- attr_accessor :response_body
4
- attr_accessor :expected_response
6
+ attr_accessor :response_body, :expected_response, :expected_fields_hash
5
7
 
6
- def initialize(actual_response_body, expected_response_fields)
7
- self.response_body = actual_response_body
8
- self.expected_response = expected_response_fields
9
- end
8
+ def initialize(actual_body:, expected_fields:)
9
+ self.response_body = actual_body
10
+ self.expected_response = expected_fields
11
+ self.expected_fields_hash = expected_field_array(expected_response.body)
12
+ end
10
13
 
11
- def response_field_array
12
- field_array self.response_body
13
- end
14
+ def response_field_array
15
+ field_array response_body
16
+ end
14
17
 
15
- def expected_fields
16
- expected_fields_hash.keys
17
- end
18
+ def expected_fields
19
+ expected_fields_hash.keys
20
+ end
18
21
 
19
- def seen_fields
20
- seen = []
21
- fields = response_field_array - extra_fields
22
- expected = expected_fields_hash
23
- fields.each do |field_key|
24
- seen << expected[field_key]
25
- end
26
- seen
22
+ def seen_fields
23
+ seen = []
24
+ fields = response_field_array - extra_fields
25
+ expected = expected_fields_hash
26
+ fields.each do |field_key|
27
+ seen << expected[field_key]
27
28
  end
29
+ seen
30
+ end
28
31
 
29
- def expected_fields_hash
30
- expected_field_array self.expected_response.body
31
- end
32
+ def extra_fields
33
+ response_field_array - expected_fields
34
+ end
32
35
 
33
- def extra_fields
34
- response_field_array - expected_fields
35
- end
36
+ def missing_fields
37
+ expected_fields - response_field_array
38
+ end
36
39
 
37
- def missing_fields
38
- expected_fields - response_field_array
40
+ def expected_field_array(expected_fields)
41
+ fields = {}
42
+ expected_fields.each do |field|
43
+ field_name = field.name
44
+ if field.has_key
45
+ fields[field.name] = field
46
+ else
47
+ field_name = field.type
48
+ end
49
+ fields = fields.merge inner_expected_field(expected_fields: field.fields,
50
+ name: field_name)
39
51
  end
52
+ fields
53
+ end
40
54
 
41
- def expected_field_array expected_fields
42
- fields = {}
43
- expected_fields.each do |field|
44
- fields[field.name] = field
45
- fields = fields.merge inner_expected_field(field.fields, field.name)
46
- end
47
- fields
55
+ def inner_expected_field(expected_fields:, name:)
56
+ fields = {}
57
+ expected_fields.each do |field|
58
+ inner_name = "#{name}.#{field.name}"
59
+ if field.has_key
60
+ fields[inner_name] = field
61
+ else
62
+ inner_name = "#{name}.#{field.type}"
63
+ end
64
+ fields = fields.merge inner_expected_field(expected_fields: field.fields,
65
+ name: inner_name)
48
66
  end
67
+ fields
68
+ end
49
69
 
50
- def inner_expected_field expected_fields, name
51
- fields = {}
52
- expected_fields.each do |field|
53
- inner_name = "#{name}.#{field.name}"
54
- fields[inner_name] = field
55
- fields = fields.merge inner_expected_field(field.fields, inner_name)
56
- end
57
- fields
58
- end
70
+ def field_array(object)
71
+ fields = []
59
72
 
60
- def field_array object
61
- fields = []
62
- object.each do |key, value|
63
- if(value)
64
- fields << key.to_s
65
- fields.concat(field_array(value).map{|i| "#{key}.#{i}"})
66
- else
67
- fields.concat(field_array(key))
68
- end
73
+ if object.instance_of?(Array)
74
+ name = 'array'
75
+ fields.concat(field_array(object[0]).map { |i| "#{name}.#{i}" })
76
+ else
77
+ object.each do |key, value|
78
+ if key.respond_to?('each')
79
+ fields.concat(field_array(key))
80
+ elsif value == nil || value == 0 || value == false
81
+ fields << key.to_s
82
+ fields.concat(field_array(value).map { |i| "#{key}.#{i}" })
83
+ elsif value.to_s[0] == '[' && value.to_s[-1] == ']' && !value.to_s.include?('=>')
84
+ fields << key.to_s
85
+ elsif value
86
+ passed_value = value
87
+ fields << key.to_s
88
+ if value.instance_of?(Array)
89
+ passed_value = value[0]
90
+ end
91
+ fields.concat(field_array(passed_value).map { |i| "#{key}.#{i}" })
92
+ else
93
+ fields.concat(field_array(key))
69
94
  end
70
- fields
71
- rescue NoMethodError
72
- fields
95
+ end
73
96
  end
97
+
98
+ fields
99
+ rescue NoMethodError
100
+ fields
101
+ end
74
102
  end
75
103
  end
@@ -1,19 +1,22 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ApiTester
4
+ # Class defining the verbs this tool supports
2
5
  class SupportedVerbs
3
- def SupportedVerbs.add_item(key, value)
6
+ def self.add_item(key, value)
4
7
  @hash ||= {}
5
8
  @hash[key] = value
6
9
  end
7
10
 
8
- def SupportedVerbs.const_missing(key)
11
+ def self.const_missing(key)
9
12
  @hash[key]
10
13
  end
11
14
 
12
- def SupportedVerbs.each
13
- @hash.each {|key,value| yield(key,value)}
15
+ def self.each(&block)
16
+ @hash.each(&block)
14
17
  end
15
18
 
16
- def SupportedVerbs.all
19
+ def self.all
17
20
  @hash.values
18
21
  end
19
22
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ApiTester
2
- VERSION = "1.0.0"
4
+ VERSION = '1.1.3'
3
5
  end
data/lib/api-tester.rb CHANGED
@@ -1,12 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Tool for testing through API definitions
1
4
  module ApiTester
2
- def self.go contract, config
5
+ def self.go(contract, config)
3
6
  reporter = config.reporter
4
7
 
5
- config.modules.sort_by{ |mod| mod.order }.each do |mod|
8
+ config.modules.sort_by(&:order).each do |mod|
6
9
  reporter.add_reports mod.go contract
7
10
  end
8
11
 
9
12
  reporter.print
10
- reporter.reports.size == 0
13
+ reporter.reports.size.zero?
11
14
  end
12
15
  end
metadata CHANGED
@@ -1,43 +1,85 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: api-tester
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - arane
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-06-08 00:00:00.000000000 Z
11
+ date: 2022-07-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler-audit
15
29
  requirement: !ruby/object:Gem::Requirement
16
30
  requirements:
17
31
  - - "~>"
18
32
  - !ruby/object:Gem::Version
19
- version: '1.13'
33
+ version: 0.9.0
20
34
  type: :development
21
35
  prerelease: false
22
36
  version_requirements: !ruby/object:Gem::Requirement
23
37
  requirements:
24
38
  - - "~>"
25
39
  - !ruby/object:Gem::Version
26
- version: '1.13'
40
+ version: 0.9.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: guard-rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 4.7.3
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 4.7.3
27
55
  - !ruby/object:Gem::Dependency
28
56
  name: rake
29
57
  requirement: !ruby/object:Gem::Requirement
30
58
  requirements:
31
59
  - - "~>"
32
60
  - !ruby/object:Gem::Version
33
- version: '10.0'
61
+ version: 13.0.1
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 13.0.1
69
+ - !ruby/object:Gem::Dependency
70
+ name: require_all
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 3.0.0
34
76
  type: :development
35
77
  prerelease: false
36
78
  version_requirements: !ruby/object:Gem::Requirement
37
79
  requirements:
38
80
  - - "~>"
39
81
  - !ruby/object:Gem::Version
40
- version: '10.0'
82
+ version: 3.0.0
41
83
  - !ruby/object:Gem::Dependency
42
84
  name: rspec
43
85
  requirement: !ruby/object:Gem::Requirement
@@ -53,75 +95,89 @@ dependencies:
53
95
  - !ruby/object:Gem::Version
54
96
  version: '3.0'
55
97
  - !ruby/object:Gem::Dependency
56
- name: webmock
98
+ name: rubocop
57
99
  requirement: !ruby/object:Gem::Requirement
58
100
  requirements:
59
101
  - - "~>"
60
102
  - !ruby/object:Gem::Version
61
- version: '3.4'
103
+ version: 1.31.0
62
104
  type: :development
63
105
  prerelease: false
64
106
  version_requirements: !ruby/object:Gem::Requirement
65
107
  requirements:
66
108
  - - "~>"
67
109
  - !ruby/object:Gem::Version
68
- version: '3.4'
110
+ version: 1.31.0
69
111
  - !ruby/object:Gem::Dependency
70
- name: pry
112
+ name: terminal-notifier
71
113
  requirement: !ruby/object:Gem::Requirement
72
114
  requirements:
73
115
  - - "~>"
74
116
  - !ruby/object:Gem::Version
75
- version: '0.11'
117
+ version: 2.0.0
76
118
  type: :development
77
119
  prerelease: false
78
120
  version_requirements: !ruby/object:Gem::Requirement
79
121
  requirements:
80
122
  - - "~>"
81
123
  - !ruby/object:Gem::Version
82
- version: '0.11'
124
+ version: 2.0.0
83
125
  - !ruby/object:Gem::Dependency
84
- name: require_all
126
+ name: terminal-notifier-guard
85
127
  requirement: !ruby/object:Gem::Requirement
86
128
  requirements:
87
129
  - - "~>"
88
130
  - !ruby/object:Gem::Version
89
- version: 2.0.0
131
+ version: 1.7.0
90
132
  type: :development
91
133
  prerelease: false
92
134
  version_requirements: !ruby/object:Gem::Requirement
93
135
  requirements:
94
136
  - - "~>"
95
137
  - !ruby/object:Gem::Version
96
- version: 2.0.0
138
+ version: 1.7.0
97
139
  - !ruby/object:Gem::Dependency
98
- name: rest-client
140
+ name: webmock
99
141
  requirement: !ruby/object:Gem::Requirement
100
142
  requirements:
101
143
  - - "~>"
102
144
  - !ruby/object:Gem::Version
103
- version: '2.0'
104
- type: :runtime
145
+ version: '3.4'
146
+ type: :development
105
147
  prerelease: false
106
148
  version_requirements: !ruby/object:Gem::Requirement
107
149
  requirements:
108
150
  - - "~>"
109
151
  - !ruby/object:Gem::Version
110
- version: '2.0'
152
+ version: '3.4'
111
153
  - !ruby/object:Gem::Dependency
112
154
  name: injection_vulnerability_library
113
155
  requirement: !ruby/object:Gem::Requirement
114
156
  requirements:
115
157
  - - '='
116
158
  - !ruby/object:Gem::Version
117
- version: 0.0.2
159
+ version: 0.1.3
118
160
  type: :runtime
119
161
  prerelease: false
120
162
  version_requirements: !ruby/object:Gem::Requirement
121
163
  requirements:
122
164
  - - '='
123
165
  - !ruby/object:Gem::Version
124
- version: 0.0.2
166
+ version: 0.1.3
167
+ - !ruby/object:Gem::Dependency
168
+ name: rest-client
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: '2.0'
174
+ type: :runtime
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - "~>"
179
+ - !ruby/object:Gem::Version
180
+ version: '2.0'
125
181
  description: Tool to test APIs which will eventually do boundary testing and other
126
182
  sorts of testing automatically given a contract
127
183
  email:
@@ -130,10 +186,15 @@ executables: []
130
186
  extensions: []
131
187
  extra_rdoc_files: []
132
188
  files:
189
+ - ".github/dependabot.yml"
190
+ - ".github/workflows/dependabot.yml"
191
+ - ".github/workflows/push.yml"
192
+ - ".github/workflows/test.yml"
133
193
  - ".gitignore"
134
194
  - ".rspec"
135
- - ".travis.yml"
195
+ - ".rubocop.yml"
136
196
  - Gemfile
197
+ - Guardfile
137
198
  - LICENSE.txt
138
199
  - README.md
139
200
  - Rakefile
@@ -153,21 +214,27 @@ files:
153
214
  - lib/api-tester/definition/fields/field.rb
154
215
  - lib/api-tester/definition/fields/number_field.rb
155
216
  - lib/api-tester/definition/fields/object_field.rb
217
+ - lib/api-tester/definition/fields/plain_array_field.rb
156
218
  - lib/api-tester/definition/method.rb
157
219
  - lib/api-tester/definition/request.rb
158
220
  - lib/api-tester/definition/response.rb
159
221
  - lib/api-tester/method_case_test.rb
222
+ - lib/api-tester/modules/benchmark_module.rb
160
223
  - lib/api-tester/modules/extra_verbs.rb
161
224
  - lib/api-tester/modules/format.rb
162
225
  - lib/api-tester/modules/good_case.rb
226
+ - lib/api-tester/modules/good_variations.rb
163
227
  - lib/api-tester/modules/injection_module.rb
228
+ - lib/api-tester/modules/missing_resource.rb
229
+ - lib/api-tester/modules/required_fields.rb
164
230
  - lib/api-tester/modules/server_information.rb
165
231
  - lib/api-tester/modules/typo.rb
232
+ - lib/api-tester/modules/unexpected_fields.rb
166
233
  - lib/api-tester/modules/unused_fields.rb
167
234
  - lib/api-tester/reporter/api_report.rb
168
235
  - lib/api-tester/reporter/missing_field_report.rb
169
- - lib/api-tester/reporter/missing_response_field_report.rb
170
236
  - lib/api-tester/reporter/report.rb
237
+ - lib/api-tester/reporter/response_time_report.rb
171
238
  - lib/api-tester/reporter/status_code_report.rb
172
239
  - lib/api-tester/test_helper.rb
173
240
  - lib/api-tester/util/response_evaluator.rb
@@ -176,8 +243,7 @@ files:
176
243
  homepage: https://github.com/araneforseti/api-tester
177
244
  licenses:
178
245
  - MIT
179
- metadata:
180
- allowed_push_host: https://rubygems.org/
246
+ metadata: {}
181
247
  post_install_message:
182
248
  rdoc_options: []
183
249
  require_paths:
@@ -193,8 +259,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
193
259
  - !ruby/object:Gem::Version
194
260
  version: '0'
195
261
  requirements: []
196
- rubyforge_project:
197
- rubygems_version: 2.6.12
262
+ rubygems_version: 3.0.3.1
198
263
  signing_key:
199
264
  specification_version: 4
200
265
  summary: Tool to help test APIs
data/.travis.yml DELETED
@@ -1,6 +0,0 @@
1
- language: ruby
2
-
3
- rvm:
4
- - 2.2.1
5
-
6
- before_install: gem install bundler -v 1.13.6
@@ -1,21 +0,0 @@
1
- module ApiTester
2
- class MissingResponseFieldReport
3
- attr_accessor :url
4
- attr_accessor :verb
5
- attr_accessor :expected_field
6
- attr_accessor :description
7
-
8
- def initialize(url, verb, expected_field, description)
9
- self.url = url
10
- self.verb = verb
11
- self.expected_field = expected_field
12
- self.description = description
13
- end
14
-
15
- def print
16
- puts "#{self.description}:"
17
- puts " #{self.verb} #{self.url} is missing response field:"
18
- puts " #{self.expected_field}"
19
- end
20
- end
21
- end