api-tester 0.1.0 → 1.1.1
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 +5 -5
- data/.github/dependabot.yml +15 -0
- data/.github/workflows/push.yml +39 -0
- data/.github/workflows/test.yml +31 -0
- data/.rspec +1 -0
- data/.rubocop.yml +61 -0
- data/Gemfile +2 -0
- data/Guardfile +70 -0
- data/README.md +106 -74
- data/Rakefile +8 -3
- data/api-tester.gemspec +31 -23
- data/changelog.txt +35 -0
- data/lib/api-tester.rb +15 -0
- data/lib/api-tester/config.rb +43 -0
- data/lib/api-tester/definition/boundary_case.rb +16 -0
- data/lib/api-tester/definition/contract.rb +20 -0
- data/lib/api-tester/definition/endpoint.rb +84 -0
- data/lib/api-tester/definition/fields/array_field.rb +47 -0
- data/lib/api-tester/definition/fields/boolean_field.rb +23 -0
- data/lib/api-tester/definition/fields/email_field.rb +25 -0
- data/lib/api-tester/definition/fields/enum_field.rb +32 -0
- data/lib/api-tester/definition/fields/field.rb +50 -0
- data/lib/api-tester/definition/fields/number_field.rb +22 -0
- data/lib/api-tester/definition/fields/object_field.rb +47 -0
- data/lib/api-tester/definition/fields/plain_array_field.rb +25 -0
- data/lib/api-tester/definition/method.rb +22 -0
- data/lib/api-tester/definition/request.rb +96 -0
- data/lib/api-tester/definition/response.rb +39 -0
- data/lib/api-tester/method_case_test.rb +83 -0
- data/lib/api-tester/modules/extra_verbs.rb +53 -0
- data/lib/api-tester/modules/format.rb +47 -0
- data/lib/api-tester/modules/good_case.rb +46 -0
- data/lib/api-tester/modules/injection_module.rb +81 -0
- data/lib/api-tester/modules/required_fields.rb +51 -0
- data/lib/api-tester/modules/server_information.rb +42 -0
- data/lib/api-tester/modules/typo.rb +70 -0
- data/lib/api-tester/modules/unexpected_fields.rb +61 -0
- data/lib/api-tester/modules/unused_fields.rb +31 -0
- data/lib/api-tester/reporter/api_report.rb +47 -0
- data/lib/api-tester/reporter/missing_field_report.rb +24 -0
- data/lib/api-tester/reporter/report.rb +30 -0
- data/lib/api-tester/reporter/status_code_report.rb +21 -0
- data/lib/api-tester/test_helper.rb +12 -0
- data/lib/api-tester/util/response_evaluator.rb +88 -0
- data/lib/api-tester/util/supported_verbs.rb +39 -0
- data/lib/api-tester/version.rb +5 -0
- metadata +159 -42
- data/.travis.yml +0 -6
- data/lib/tester.rb +0 -7
- data/lib/tester/api_tester.rb +0 -50
- data/lib/tester/definition/api_contract.rb +0 -13
- data/lib/tester/definition/api_method.rb +0 -11
- data/lib/tester/definition/boundary_case.rb +0 -11
- data/lib/tester/definition/endpoint.rb +0 -57
- data/lib/tester/definition/fields/array_field.rb +0 -44
- data/lib/tester/definition/fields/boolean_field.rb +0 -18
- data/lib/tester/definition/fields/email_field.rb +0 -20
- data/lib/tester/definition/fields/enum_field.rb +0 -27
- data/lib/tester/definition/fields/field.rb +0 -47
- data/lib/tester/definition/fields/number_field.rb +0 -17
- data/lib/tester/definition/fields/object_field.rb +0 -42
- data/lib/tester/definition/request.rb +0 -49
- data/lib/tester/definition/response.rb +0 -34
- data/lib/tester/method_case_test.rb +0 -67
- data/lib/tester/modules/extra_verbs.rb +0 -25
- data/lib/tester/modules/format.rb +0 -26
- data/lib/tester/modules/good_case.rb +0 -29
- data/lib/tester/modules/module.rb +0 -18
- data/lib/tester/modules/typo.rb +0 -41
- data/lib/tester/modules/unused_fields.rb +0 -22
- data/lib/tester/reporter/api_report.rb +0 -33
- data/lib/tester/reporter/missing_field_report.rb +0 -23
- data/lib/tester/reporter/missing_response_field_report.rb +0 -19
- data/lib/tester/reporter/report.rb +0 -25
- data/lib/tester/reporter/status_code_report.rb +0 -12
- data/lib/tester/test_helper.rb +0 -10
- data/lib/tester/util/response_evaluator.rb +0 -73
- data/lib/tester/util/supported_verbs.rb +0 -34
- data/lib/tester/version.rb +0 -3
data/lib/tester.rb
DELETED
data/lib/tester/api_tester.rb
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
require "tester/modules/format"
|
2
|
-
require 'tester/modules/good_case'
|
3
|
-
require 'tester/modules/unused_fields'
|
4
|
-
require 'tester/modules/typo'
|
5
|
-
require 'rest-client'
|
6
|
-
require 'tester/reporter/api_report'
|
7
|
-
require 'json'
|
8
|
-
|
9
|
-
class ApiTester
|
10
|
-
attr_accessor :report
|
11
|
-
attr_accessor :modules
|
12
|
-
attr_accessor :definition
|
13
|
-
attr_accessor :test_helper
|
14
|
-
|
15
|
-
def initialize(definition)
|
16
|
-
self.report = ApiReport.new
|
17
|
-
self.modules = []
|
18
|
-
self.definition = definition
|
19
|
-
self.test_helper = TestHelper.new
|
20
|
-
end
|
21
|
-
|
22
|
-
def with_module(new_module)
|
23
|
-
self.modules << new_module
|
24
|
-
self
|
25
|
-
end
|
26
|
-
|
27
|
-
def with_reporter(reporter)
|
28
|
-
self.report = reporter
|
29
|
-
self
|
30
|
-
end
|
31
|
-
|
32
|
-
def with_default_modules
|
33
|
-
self.modules << Format.new
|
34
|
-
self.modules << GoodCase.new
|
35
|
-
self.modules << Typo.new
|
36
|
-
self.modules << UnusedFields.new
|
37
|
-
self
|
38
|
-
end
|
39
|
-
|
40
|
-
def go
|
41
|
-
self.definition.endpoints.each do |endpoint|
|
42
|
-
self.modules.sort_by{ |mod| mod.order }.each do |mod|
|
43
|
-
mod.go endpoint, self.report
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
self.report.print
|
48
|
-
self.report.reports.size == 0
|
49
|
-
end
|
50
|
-
end
|
@@ -1,57 +0,0 @@
|
|
1
|
-
require 'tester/definition/response'
|
2
|
-
require 'tester/definition/api_method'
|
3
|
-
|
4
|
-
class Endpoint
|
5
|
-
attr_accessor :name
|
6
|
-
attr_accessor :base_url
|
7
|
-
attr_accessor :path_params
|
8
|
-
attr_accessor :methods
|
9
|
-
attr_accessor :test_helper
|
10
|
-
attr_accessor :bad_request_response
|
11
|
-
attr_accessor :not_allowed_response
|
12
|
-
attr_accessor :not_found_response
|
13
|
-
|
14
|
-
def initialize name, url
|
15
|
-
self.base_url = url
|
16
|
-
self.name = name
|
17
|
-
self.methods = []
|
18
|
-
self.path_params = []
|
19
|
-
self.test_helper = TestHelper.new
|
20
|
-
self.bad_request_response = Response.new 400
|
21
|
-
self.not_allowed_response = Response.new 415
|
22
|
-
self.not_found_response = Response.new 404
|
23
|
-
end
|
24
|
-
|
25
|
-
def url
|
26
|
-
temp_url = self.base_url
|
27
|
-
self.path_params.each do |param|
|
28
|
-
temp_url.sub! "{#{param}}", self.test_helper.retrieve_param(param)
|
29
|
-
end
|
30
|
-
temp_url
|
31
|
-
end
|
32
|
-
|
33
|
-
def call method, payload={}, headers={}
|
34
|
-
self.test_helper.before
|
35
|
-
begin
|
36
|
-
response = RestClient::Request.execute(method: method.verb, url: self.url, payload: payload, headers: headers)
|
37
|
-
rescue RestClient::ExceptionWithResponse => e
|
38
|
-
response = e.response
|
39
|
-
end
|
40
|
-
self.test_helper.after
|
41
|
-
response
|
42
|
-
end
|
43
|
-
|
44
|
-
def add_method verb, response, request=Request.new()
|
45
|
-
self.methods << ApiMethod.new(verb, response, request)
|
46
|
-
self
|
47
|
-
end
|
48
|
-
|
49
|
-
def add_path_param param
|
50
|
-
self.path_params << param
|
51
|
-
self
|
52
|
-
end
|
53
|
-
|
54
|
-
def verbs
|
55
|
-
self.methods.map(&:verb)
|
56
|
-
end
|
57
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
require 'tester/definition/fields/field'
|
2
|
-
|
3
|
-
class ArrayField < Field
|
4
|
-
attr_accessor :fields
|
5
|
-
|
6
|
-
def initialize name
|
7
|
-
super(name)
|
8
|
-
self.fields = []
|
9
|
-
end
|
10
|
-
|
11
|
-
def with_field(newField)
|
12
|
-
self.fields << newField
|
13
|
-
self
|
14
|
-
end
|
15
|
-
|
16
|
-
def has_subfields?
|
17
|
-
true
|
18
|
-
end
|
19
|
-
|
20
|
-
def default_value
|
21
|
-
if self.fields.size == 0
|
22
|
-
return []
|
23
|
-
end
|
24
|
-
|
25
|
-
obj = Hash.new
|
26
|
-
self.fields.each do |field|
|
27
|
-
obj[field.name] = field.default_value
|
28
|
-
end
|
29
|
-
[obj]
|
30
|
-
end
|
31
|
-
|
32
|
-
def negative_boundary_values
|
33
|
-
super +
|
34
|
-
[
|
35
|
-
"string",
|
36
|
-
123,
|
37
|
-
0,
|
38
|
-
1,
|
39
|
-
true,
|
40
|
-
false,
|
41
|
-
{}
|
42
|
-
]
|
43
|
-
end
|
44
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
require 'tester/definition/fields/field'
|
2
|
-
|
3
|
-
class BooleanField < Field
|
4
|
-
def initialize(name, default_value=true)
|
5
|
-
super(name, default_value)
|
6
|
-
end
|
7
|
-
|
8
|
-
def negative_boundary_values
|
9
|
-
super +
|
10
|
-
[
|
11
|
-
"string",
|
12
|
-
123,
|
13
|
-
0,
|
14
|
-
1,
|
15
|
-
{}
|
16
|
-
]
|
17
|
-
end
|
18
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
require 'tester/definition/fields/field'
|
2
|
-
|
3
|
-
class EmailField < Field
|
4
|
-
def initialize(name, default_value="test@test.com")
|
5
|
-
super(name, default_value)
|
6
|
-
end
|
7
|
-
|
8
|
-
def negative_boundary_values
|
9
|
-
super +
|
10
|
-
[
|
11
|
-
"string",
|
12
|
-
123,
|
13
|
-
1,
|
14
|
-
0,
|
15
|
-
true,
|
16
|
-
false,
|
17
|
-
{}
|
18
|
-
]
|
19
|
-
end
|
20
|
-
end
|
@@ -1,27 +0,0 @@
|
|
1
|
-
require 'tester/definition/fields/field'
|
2
|
-
|
3
|
-
class EnumField < Field
|
4
|
-
attr_accessor :acceptable_values
|
5
|
-
|
6
|
-
def initialize name, acceptable_values, default_value=nil
|
7
|
-
if default_value
|
8
|
-
super name, default_value
|
9
|
-
else
|
10
|
-
super name, acceptable_values[0]
|
11
|
-
end
|
12
|
-
|
13
|
-
self.acceptable_values = acceptable_values
|
14
|
-
end
|
15
|
-
|
16
|
-
def negative_boundary_values
|
17
|
-
super +
|
18
|
-
[
|
19
|
-
123,
|
20
|
-
0,
|
21
|
-
1,
|
22
|
-
true,
|
23
|
-
false,
|
24
|
-
{}
|
25
|
-
]
|
26
|
-
end
|
27
|
-
end
|
@@ -1,47 +0,0 @@
|
|
1
|
-
class Field
|
2
|
-
attr_accessor :name
|
3
|
-
attr_accessor :default_value
|
4
|
-
attr_accessor :required
|
5
|
-
attr_accessor :is_seen
|
6
|
-
|
7
|
-
def initialize name, default_value="string"
|
8
|
-
self.name = name
|
9
|
-
self.default_value = default_value
|
10
|
-
self.required = false
|
11
|
-
self.is_seen = 0
|
12
|
-
end
|
13
|
-
|
14
|
-
def is_required
|
15
|
-
self.required = true
|
16
|
-
self
|
17
|
-
end
|
18
|
-
|
19
|
-
def is_not_required
|
20
|
-
self.required = false
|
21
|
-
self
|
22
|
-
end
|
23
|
-
|
24
|
-
def has_subfields?
|
25
|
-
false
|
26
|
-
end
|
27
|
-
|
28
|
-
def fields
|
29
|
-
[]
|
30
|
-
end
|
31
|
-
|
32
|
-
def negative_boundary_values
|
33
|
-
cases = []
|
34
|
-
if self.required
|
35
|
-
cases << nil
|
36
|
-
end
|
37
|
-
cases
|
38
|
-
end
|
39
|
-
|
40
|
-
def seen
|
41
|
-
self.is_seen += 1
|
42
|
-
end
|
43
|
-
|
44
|
-
def display_class
|
45
|
-
self.class
|
46
|
-
end
|
47
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
require 'tester/definition/fields/field'
|
2
|
-
|
3
|
-
class NumberField < Field
|
4
|
-
def initialize(name, default_value=5)
|
5
|
-
super(name, default_value)
|
6
|
-
end
|
7
|
-
|
8
|
-
def negative_boundary_values
|
9
|
-
super +
|
10
|
-
[
|
11
|
-
"string",
|
12
|
-
true,
|
13
|
-
false,
|
14
|
-
{}
|
15
|
-
]
|
16
|
-
end
|
17
|
-
end
|
@@ -1,42 +0,0 @@
|
|
1
|
-
require 'tester/definition/fields/field'
|
2
|
-
|
3
|
-
class ObjectField < Field
|
4
|
-
attr_accessor :fields
|
5
|
-
|
6
|
-
def initialize name
|
7
|
-
super(name)
|
8
|
-
self.fields = []
|
9
|
-
end
|
10
|
-
|
11
|
-
def with_field(newField)
|
12
|
-
self.fields << newField
|
13
|
-
self
|
14
|
-
end
|
15
|
-
|
16
|
-
def has_subfields?
|
17
|
-
true
|
18
|
-
end
|
19
|
-
|
20
|
-
def default_value
|
21
|
-
obj = Hash.new
|
22
|
-
|
23
|
-
self.fields.each do |field|
|
24
|
-
obj[field.name] = field.default_value
|
25
|
-
end
|
26
|
-
|
27
|
-
obj
|
28
|
-
end
|
29
|
-
|
30
|
-
def negative_boundary_values
|
31
|
-
super +
|
32
|
-
[
|
33
|
-
"string",
|
34
|
-
[],
|
35
|
-
123,
|
36
|
-
1,
|
37
|
-
0,
|
38
|
-
true,
|
39
|
-
false
|
40
|
-
]
|
41
|
-
end
|
42
|
-
end
|
@@ -1,49 +0,0 @@
|
|
1
|
-
require 'tester/definition/boundary_case'
|
2
|
-
|
3
|
-
class Request
|
4
|
-
attr_accessor :definition
|
5
|
-
attr_accessor :headers
|
6
|
-
attr_accessor :fields
|
7
|
-
|
8
|
-
def initialize
|
9
|
-
self.fields = []
|
10
|
-
end
|
11
|
-
|
12
|
-
def add_field(new_field)
|
13
|
-
self.fields << new_field
|
14
|
-
self
|
15
|
-
end
|
16
|
-
|
17
|
-
def payload
|
18
|
-
response = Hash.new
|
19
|
-
self.fields.each do |field|
|
20
|
-
response[field.name] = field.default_value
|
21
|
-
end
|
22
|
-
response
|
23
|
-
end
|
24
|
-
|
25
|
-
def default_payload
|
26
|
-
payload
|
27
|
-
end
|
28
|
-
|
29
|
-
def default_headers
|
30
|
-
{content_type: :json, accept: :json}
|
31
|
-
end
|
32
|
-
|
33
|
-
def cases
|
34
|
-
boundary_cases = Array.new
|
35
|
-
self.fields.each do |field|
|
36
|
-
field.negative_boundary_values.each do |value|
|
37
|
-
bcase = BoundaryCase.new("Setting #{field.name} to #{value}", altered_payload(field.name, value), default_headers)
|
38
|
-
boundary_cases.push(bcase)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
boundary_cases
|
42
|
-
end
|
43
|
-
|
44
|
-
def altered_payload field_name, value
|
45
|
-
body = payload
|
46
|
-
body[field_name] = value
|
47
|
-
body
|
48
|
-
end
|
49
|
-
end
|
@@ -1,34 +0,0 @@
|
|
1
|
-
class Response
|
2
|
-
attr_accessor :code
|
3
|
-
attr_accessor :body
|
4
|
-
|
5
|
-
def initialize(status_code=200)
|
6
|
-
self.code = status_code
|
7
|
-
self.body = []
|
8
|
-
end
|
9
|
-
|
10
|
-
def add_field(new_field)
|
11
|
-
self.body << new_field
|
12
|
-
self
|
13
|
-
end
|
14
|
-
|
15
|
-
def to_s
|
16
|
-
des = {}
|
17
|
-
self.body.map do |f|
|
18
|
-
des[f.name] = field_display f
|
19
|
-
end
|
20
|
-
des.to_json
|
21
|
-
end
|
22
|
-
|
23
|
-
def field_display field
|
24
|
-
des = field.display_class
|
25
|
-
if field.has_subfields?
|
26
|
-
des = {}
|
27
|
-
field.fields.map do |f|
|
28
|
-
des[f.name] = field_display f
|
29
|
-
end
|
30
|
-
des.to_json
|
31
|
-
end
|
32
|
-
des
|
33
|
-
end
|
34
|
-
end
|