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.
Files changed (79) hide show
  1. checksums.yaml +5 -5
  2. data/.github/dependabot.yml +15 -0
  3. data/.github/workflows/push.yml +39 -0
  4. data/.github/workflows/test.yml +31 -0
  5. data/.rspec +1 -0
  6. data/.rubocop.yml +61 -0
  7. data/Gemfile +2 -0
  8. data/Guardfile +70 -0
  9. data/README.md +106 -74
  10. data/Rakefile +8 -3
  11. data/api-tester.gemspec +31 -23
  12. data/changelog.txt +35 -0
  13. data/lib/api-tester.rb +15 -0
  14. data/lib/api-tester/config.rb +43 -0
  15. data/lib/api-tester/definition/boundary_case.rb +16 -0
  16. data/lib/api-tester/definition/contract.rb +20 -0
  17. data/lib/api-tester/definition/endpoint.rb +84 -0
  18. data/lib/api-tester/definition/fields/array_field.rb +47 -0
  19. data/lib/api-tester/definition/fields/boolean_field.rb +23 -0
  20. data/lib/api-tester/definition/fields/email_field.rb +25 -0
  21. data/lib/api-tester/definition/fields/enum_field.rb +32 -0
  22. data/lib/api-tester/definition/fields/field.rb +50 -0
  23. data/lib/api-tester/definition/fields/number_field.rb +22 -0
  24. data/lib/api-tester/definition/fields/object_field.rb +47 -0
  25. data/lib/api-tester/definition/fields/plain_array_field.rb +25 -0
  26. data/lib/api-tester/definition/method.rb +22 -0
  27. data/lib/api-tester/definition/request.rb +96 -0
  28. data/lib/api-tester/definition/response.rb +39 -0
  29. data/lib/api-tester/method_case_test.rb +83 -0
  30. data/lib/api-tester/modules/extra_verbs.rb +53 -0
  31. data/lib/api-tester/modules/format.rb +47 -0
  32. data/lib/api-tester/modules/good_case.rb +46 -0
  33. data/lib/api-tester/modules/injection_module.rb +81 -0
  34. data/lib/api-tester/modules/required_fields.rb +51 -0
  35. data/lib/api-tester/modules/server_information.rb +42 -0
  36. data/lib/api-tester/modules/typo.rb +70 -0
  37. data/lib/api-tester/modules/unexpected_fields.rb +61 -0
  38. data/lib/api-tester/modules/unused_fields.rb +31 -0
  39. data/lib/api-tester/reporter/api_report.rb +47 -0
  40. data/lib/api-tester/reporter/missing_field_report.rb +24 -0
  41. data/lib/api-tester/reporter/report.rb +30 -0
  42. data/lib/api-tester/reporter/status_code_report.rb +21 -0
  43. data/lib/api-tester/test_helper.rb +12 -0
  44. data/lib/api-tester/util/response_evaluator.rb +88 -0
  45. data/lib/api-tester/util/supported_verbs.rb +39 -0
  46. data/lib/api-tester/version.rb +5 -0
  47. metadata +159 -42
  48. data/.travis.yml +0 -6
  49. data/lib/tester.rb +0 -7
  50. data/lib/tester/api_tester.rb +0 -50
  51. data/lib/tester/definition/api_contract.rb +0 -13
  52. data/lib/tester/definition/api_method.rb +0 -11
  53. data/lib/tester/definition/boundary_case.rb +0 -11
  54. data/lib/tester/definition/endpoint.rb +0 -57
  55. data/lib/tester/definition/fields/array_field.rb +0 -44
  56. data/lib/tester/definition/fields/boolean_field.rb +0 -18
  57. data/lib/tester/definition/fields/email_field.rb +0 -20
  58. data/lib/tester/definition/fields/enum_field.rb +0 -27
  59. data/lib/tester/definition/fields/field.rb +0 -47
  60. data/lib/tester/definition/fields/number_field.rb +0 -17
  61. data/lib/tester/definition/fields/object_field.rb +0 -42
  62. data/lib/tester/definition/request.rb +0 -49
  63. data/lib/tester/definition/response.rb +0 -34
  64. data/lib/tester/method_case_test.rb +0 -67
  65. data/lib/tester/modules/extra_verbs.rb +0 -25
  66. data/lib/tester/modules/format.rb +0 -26
  67. data/lib/tester/modules/good_case.rb +0 -29
  68. data/lib/tester/modules/module.rb +0 -18
  69. data/lib/tester/modules/typo.rb +0 -41
  70. data/lib/tester/modules/unused_fields.rb +0 -22
  71. data/lib/tester/reporter/api_report.rb +0 -33
  72. data/lib/tester/reporter/missing_field_report.rb +0 -23
  73. data/lib/tester/reporter/missing_response_field_report.rb +0 -19
  74. data/lib/tester/reporter/report.rb +0 -25
  75. data/lib/tester/reporter/status_code_report.rb +0 -12
  76. data/lib/tester/test_helper.rb +0 -10
  77. data/lib/tester/util/response_evaluator.rb +0 -73
  78. data/lib/tester/util/supported_verbs.rb +0 -34
  79. data/lib/tester/version.rb +0 -3
@@ -1,67 +0,0 @@
1
- require 'tester/util/response_evaluator.rb'
2
-
3
- class MethodCaseTest
4
- attr_accessor :expected_response
5
- attr_accessor :payload
6
- attr_accessor :response
7
- attr_accessor :reports
8
- attr_accessor :url
9
- attr_accessor :module_name
10
-
11
- def initialize response, payload, expected_response, url, verb, module_name
12
- self.payload = payload
13
- self.response = response
14
- self.expected_response = expected_response
15
- self.reports = []
16
- self.url = "#{verb} #{url}"
17
- self.module_name = module_name
18
- end
19
-
20
- def response_code_report
21
- report = StatusCodeReport.new "#{module_name} - Incorrect response code", self.url, self.payload, self.expected_response.code, self.response.code
22
- self.reports << report
23
- nil
24
- end
25
-
26
- def missing_field_report field
27
- report = Report.new "#{module_name} - Missing field #{field}", self.url, self.payload, self.expected_response, self.response
28
- self.reports << report
29
- nil
30
- end
31
-
32
- def extra_field_report field
33
- report = Report.new "#{module_name} - Found extra field #{field}", self.url, self.payload, self.expected_response, self.response
34
- self.reports << report
35
- nil
36
- end
37
-
38
- def check
39
- if check_response_code
40
- evaluator = ResponseEvaluator.new json_parse(self.response.body), self.expected_response
41
- evaluator.missing_fields.map{|field| missing_field_report(field)}
42
- evaluator.extra_fields.map{|field| extra_field_report(field)}
43
- increment_fields evaluator.seen_fields
44
- end
45
- return self.reports
46
- end
47
-
48
- def check_response_code
49
- if response.code != expected_response.code
50
- response_code_report
51
- return false
52
- end
53
- return true
54
- end
55
-
56
- def increment_fields seen_fields
57
- seen_fields.each do |field|
58
- field.seen
59
- end
60
- end
61
-
62
- def json_parse body
63
- JSON.parse!(body)
64
- rescue JSON::ParserError
65
- body
66
- end
67
- end
@@ -1,25 +0,0 @@
1
- require 'tester/modules/module'
2
- require 'tester/util/supported_verbs'
3
-
4
- class ExtraVerbs < Module
5
- def go(endpoint, report)
6
- super
7
-
8
- extras = SupportedVerbs.all - endpoint.verbs
9
- extras.each do |verb|
10
- verb_case = BoundaryCase.new("Verb check with #{verb} for #{endpoint.name}", {}, {})
11
- method = ApiMethod.new verb, Response.new, Request.new
12
- response = endpoint.call method, verb_case.payload, verb_case.headers
13
- test = VerbClass.new response, verb_case.payload, endpoint.not_allowed_response, endpoint.url, verb
14
- reports = test.check
15
- self.report.reports.concat reports
16
- end
17
- self.report.reports == []
18
- end
19
- end
20
-
21
- class VerbClass < MethodCaseTest
22
- def initialize response, payload, expected_response, url, verb
23
- super response, payload, expected_response, url, verb, "VerbModule"
24
- end
25
- end
@@ -1,26 +0,0 @@
1
- require 'tester/reporter/status_code_report'
2
- require 'tester/modules/module'
3
- require 'tester/method_case_test'
4
-
5
- class Format < Module
6
- def go definition, report
7
- super
8
-
9
- definition.methods.each do |method|
10
- cases = method.request.cases
11
- cases.each do |format_case|
12
- response = definition.call method, format_case.payload, format_case.headers
13
- test = FormatTest.new response, format_case.payload, definition.bad_request_response, definition.url, method.verb
14
- self.report.reports.concat test.check
15
- end
16
- end
17
-
18
- report.reports == []
19
- end
20
- end
21
-
22
- class FormatTest < MethodCaseTest
23
- def initialize response, payload, expected_response, url, verb
24
- super response, payload, expected_response, url, verb, "FormatModule"
25
- end
26
- end
@@ -1,29 +0,0 @@
1
- require 'tester/reporter/status_code_report'
2
- require 'tester/modules/module'
3
- require 'tester/method_case_test'
4
-
5
- class GoodCase < Module
6
- def go endpoint, report
7
- super
8
-
9
- endpoint.methods.each do |method|
10
- default_case = BoundaryCase.new endpoint.url, method.request.default_payload, method.request.default_headers
11
- response = endpoint.call method, default_case.payload, default_case.headers
12
- test = GoodCaseTest.new response, endpoint.url, method
13
- self.report.reports.concat test.check
14
- end
15
-
16
- self.report.reports == []
17
- end
18
-
19
- def order
20
- 1
21
- end
22
- end
23
-
24
-
25
- class GoodCaseTest < MethodCaseTest
26
- def initialize response, url, method
27
- super response, method.request.default_payload, method.expected_response, url, method.verb, "GoodCaseModule"
28
- end
29
- end
@@ -1,18 +0,0 @@
1
- require 'tester/reporter/status_code_report'
2
- require 'tester/test_helper'
3
-
4
- class Module
5
- attr_accessor :report
6
-
7
- def set_report report
8
- self.report = report
9
- end
10
-
11
- def go definition, report
12
- set_report report
13
- end
14
-
15
- def order
16
- 5
17
- end
18
- end
@@ -1,41 +0,0 @@
1
- require 'tester/reporter/status_code_report'
2
- require 'tester/modules/module'
3
- require 'tester/util/supported_verbs'
4
-
5
- class Typo < Module
6
- def go(endpoint, report)
7
- super
8
-
9
- allowances(endpoint).each do |verbs|
10
- check_typo_url endpoint
11
- end
12
-
13
- report.reports == []
14
- end
15
-
16
- def check_typo_url endpoint
17
- bad_url = "#{endpoint.url}gibberishadsfasdf"
18
- bad_endpoint = Endpoint.new "Bad URL", bad_url
19
- typo_case = BoundaryCase.new("Typo URL check", {}, {})
20
- method = ApiMethod.new SupportedVerbs::GET, Response.new(200), Request.new
21
- response = bad_endpoint.call method, typo_case.payload, typo_case.headers
22
-
23
- test = TypoClass.new response, typo_case.payload, endpoint.not_found_response, bad_url, SupportedVerbs::GET
24
- reports = test.check
25
- self.report.reports.concat reports
26
- end
27
-
28
- def allowances(endpoint)
29
- allowances = []
30
- endpoint.methods.each do |method|
31
- allowances << method.verb
32
- end
33
- allowances.uniq
34
- end
35
- end
36
-
37
- class TypoClass < MethodCaseTest
38
- def initialize response, payload, expected_response, url, verb
39
- super response, payload, expected_response, url, verb, "TypoModule"
40
- end
41
- end
@@ -1,22 +0,0 @@
1
- require 'tester/reporter/missing_response_field_report'
2
- require 'tester/modules/module'
3
-
4
- class UnusedFields < Module
5
- def go definition, report
6
- super
7
-
8
- definition.methods.each do |method|
9
- method.expected_response.body.each do |field|
10
- if field.is_seen == 0
11
- report.add_new_report MissingResponseFieldReport.new(definition.url, method.verb, field.name, "UnusedFieldsModule")
12
- end
13
- end
14
- end
15
-
16
- report.reports == []
17
- end
18
-
19
- def order
20
- 99
21
- end
22
- end
@@ -1,33 +0,0 @@
1
- require 'tester/reporter/report'
2
-
3
- class ApiReport
4
- attr_accessor :reports
5
-
6
- def initialize
7
- self.reports = []
8
- end
9
-
10
- def add_new url, request, expected_response, actual_response, description="A case"
11
- report = Report.new description, url, request, expected_response, actual_response
12
- self.reports << report
13
- end
14
-
15
- def add_new_report report
16
- self.reports << report
17
- end
18
-
19
- def print
20
- if self.reports.size > 0
21
- puts "Issues discovered: #{self.reports.size}"
22
- self.reports.each do |report|
23
- report.print
24
- puts "\n"
25
- puts "\n"
26
- end
27
- puts ""
28
- puts "Issues discovered: #{self.reports.size}"
29
- else
30
- puts "No issues found"
31
- end
32
- end
33
- end
@@ -1,23 +0,0 @@
1
- class MissingFieldReport
2
- attr_accessor :description
3
- attr_accessor :url
4
- attr_accessor :request
5
- attr_accessor :expected_field
6
- attr_accessor :actual_response
7
-
8
- def initialize(description, url, request, expected_field)
9
- self.description = description
10
- self.url = url
11
- self.request = request
12
- self.expected_field = expected_field
13
- self.actual_response = ''
14
- end
15
-
16
- def print
17
- puts "#{self.description}: "
18
- puts " Requested #{self.url} with payload:"
19
- puts " #{self.request}"
20
- puts ' Missing field: '
21
- puts " #{self.expected_field}"
22
- end
23
- end
@@ -1,19 +0,0 @@
1
- class MissingResponseFieldReport
2
- attr_accessor :url
3
- attr_accessor :verb
4
- attr_accessor :expected_field
5
- attr_accessor :description
6
-
7
- def initialize(url, verb, expected_field, description)
8
- self.url = url
9
- self.verb = verb
10
- self.expected_field = expected_field
11
- self.description = description
12
- end
13
-
14
- def print
15
- puts "#{self.description}:"
16
- puts " #{self.verb} #{self.url} is missing response field:"
17
- puts " #{self.expected_field}"
18
- end
19
- end
@@ -1,25 +0,0 @@
1
- class Report
2
- attr_accessor :description
3
- attr_accessor :url
4
- attr_accessor :request
5
- attr_accessor :expected_response
6
- attr_accessor :actual_response
7
-
8
- def initialize description, url, request, expected_response, actual_response
9
- self.description = description
10
- self.url = url
11
- self.request = request
12
- self.expected_response = expected_response
13
- self.actual_response = actual_response
14
- end
15
-
16
- def print
17
- puts "#{self.description}: "
18
- puts " Requested #{self.url} with payload:"
19
- puts " #{self.request.to_json}"
20
- puts " Expecting: "
21
- puts " " + self.expected_response.to_s
22
- puts " Receiving: "
23
- puts " #{self.actual_response}"
24
- end
25
- end
@@ -1,12 +0,0 @@
1
- require 'tester/reporter/report'
2
-
3
- class StatusCodeReport < Report
4
- attr_accessor :expected_status_code
5
- attr_accessor :actual_status_code
6
-
7
- def initialize description, url, request, expected_status_code, actual_status_code
8
- super description, url, request, expected_status_code, actual_status_code
9
- self.expected_status_code = expected_status_code
10
- self.actual_status_code = actual_status_code
11
- end
12
- end
@@ -1,10 +0,0 @@
1
- class TestHelper
2
- def before
3
- end
4
-
5
- def retrieve_param key
6
- end
7
-
8
- def after
9
- end
10
- end
@@ -1,73 +0,0 @@
1
- class ResponseEvaluator
2
- attr_accessor :response_body
3
- attr_accessor :expected_response
4
-
5
- def initialize(actual_response_body, expected_response_fields)
6
- self.response_body = actual_response_body
7
- self.expected_response = expected_response_fields
8
- end
9
-
10
- def response_field_array
11
- field_array self.response_body
12
- end
13
-
14
- def expected_fields
15
- expected_fields_hash.keys
16
- end
17
-
18
- def seen_fields
19
- seen = []
20
- fields = response_field_array - extra_fields
21
- expected = expected_fields_hash
22
- fields.each do |field_key|
23
- seen << expected[field_key]
24
- end
25
- seen
26
- end
27
-
28
- def expected_fields_hash
29
- expected_field_array self.expected_response.body
30
- end
31
-
32
- def extra_fields
33
- response_field_array - expected_fields
34
- end
35
-
36
- def missing_fields
37
- expected_fields - response_field_array
38
- end
39
-
40
- def expected_field_array expected_fields
41
- fields = {}
42
- expected_fields.each do |field|
43
- fields[field.name] = field
44
- fields = fields.merge inner_expected_field(field.fields, field.name)
45
- end
46
- fields
47
- end
48
-
49
- def inner_expected_field expected_fields, name
50
- fields = {}
51
- expected_fields.each do |field|
52
- inner_name = "#{name}.#{field.name}"
53
- fields[inner_name] = field
54
- fields = fields.merge inner_expected_field(field.fields, inner_name)
55
- end
56
- fields
57
- end
58
-
59
- def field_array object
60
- fields = []
61
- object.each do |key, value|
62
- if(value)
63
- fields << key.to_s
64
- fields.concat(field_array(value).map{|i| "#{key}.#{i}"})
65
- else
66
- fields.concat(field_array(key))
67
- end
68
- end
69
- fields
70
- rescue NoMethodError
71
- fields
72
- end
73
- end
@@ -1,34 +0,0 @@
1
- class SupportedVerbs
2
- def SupportedVerbs.add_item(key, value)
3
- @hash ||= {}
4
- @hash[key] = value
5
- end
6
-
7
- def SupportedVerbs.const_missing(key)
8
- @hash[key]
9
- end
10
-
11
- def SupportedVerbs.each
12
- @hash.each {|key,value| yield(key,value)}
13
- end
14
-
15
- def SupportedVerbs.all
16
- @hash.values
17
- end
18
-
19
- SupportedVerbs.add_item :COPY, :copy
20
- SupportedVerbs.add_item :DELETE, :delete
21
- SupportedVerbs.add_item :GET, :get
22
- SupportedVerbs.add_item :HEAD, :head
23
- SupportedVerbs.add_item :LOCK, :lock
24
- SupportedVerbs.add_item :MKCOL, :mkcol
25
- SupportedVerbs.add_item :MOVE, :move
26
- SupportedVerbs.add_item :OPTIONS, :options
27
- SupportedVerbs.add_item :PATCH, :patch
28
- SupportedVerbs.add_item :POST, :post
29
- SupportedVerbs.add_item :PROPFIND, :propfind
30
- SupportedVerbs.add_item :PROPPATCH, :proppatch
31
- SupportedVerbs.add_item :PUT, :put
32
- SupportedVerbs.add_item :TRACE, :trace
33
- SupportedVerbs.add_item :UNLOCK, :unlock
34
- end