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
 
| 
         @@ -0,0 +1,22 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'api-tester/definition/fields/field'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module ApiTester
         
     | 
| 
      
 6 
     | 
    
         
            +
              # Class for defining numeric fields in contracts
         
     | 
| 
      
 7 
     | 
    
         
            +
              class NumberField < Field
         
     | 
| 
      
 8 
     | 
    
         
            +
                def initialize(name:, default_value: 5, required: false)
         
     | 
| 
      
 9 
     | 
    
         
            +
                  super name: name, default_value: default_value, required: required
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                def negative_boundary_values
         
     | 
| 
      
 13 
     | 
    
         
            +
                  super +
         
     | 
| 
      
 14 
     | 
    
         
            +
                    [
         
     | 
| 
      
 15 
     | 
    
         
            +
                      'string',
         
     | 
| 
      
 16 
     | 
    
         
            +
                      true,
         
     | 
| 
      
 17 
     | 
    
         
            +
                      false,
         
     | 
| 
      
 18 
     | 
    
         
            +
                      {}
         
     | 
| 
      
 19 
     | 
    
         
            +
                    ]
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,47 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'api-tester/definition/fields/field'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module ApiTester
         
     | 
| 
      
 6 
     | 
    
         
            +
              # Class for defining objects in a contract
         
     | 
| 
      
 7 
     | 
    
         
            +
              class ObjectField < Field
         
     | 
| 
      
 8 
     | 
    
         
            +
                attr_accessor :fields
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                def initialize(name:, required: false)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  super name: name, required: required
         
     | 
| 
      
 12 
     | 
    
         
            +
                  self.fields = []
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                def with_field(new_field)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  fields << new_field
         
     | 
| 
      
 17 
     | 
    
         
            +
                  self
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                def subfields?
         
     | 
| 
      
 21 
     | 
    
         
            +
                  true
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                def default_value
         
     | 
| 
      
 25 
     | 
    
         
            +
                  obj = {}
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  fields.each do |field|
         
     | 
| 
      
 28 
     | 
    
         
            +
                    obj[field.name] = field.default_value
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  obj
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                def negative_boundary_values
         
     | 
| 
      
 35 
     | 
    
         
            +
                  super +
         
     | 
| 
      
 36 
     | 
    
         
            +
                    [
         
     | 
| 
      
 37 
     | 
    
         
            +
                      'string',
         
     | 
| 
      
 38 
     | 
    
         
            +
                      [],
         
     | 
| 
      
 39 
     | 
    
         
            +
                      123,
         
     | 
| 
      
 40 
     | 
    
         
            +
                      1,
         
     | 
| 
      
 41 
     | 
    
         
            +
                      0,
         
     | 
| 
      
 42 
     | 
    
         
            +
                      true,
         
     | 
| 
      
 43 
     | 
    
         
            +
                      false
         
     | 
| 
      
 44 
     | 
    
         
            +
                    ]
         
     | 
| 
      
 45 
     | 
    
         
            +
                end
         
     | 
| 
      
 46 
     | 
    
         
            +
              end
         
     | 
| 
      
 47 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,25 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'api-tester/definition/fields/field'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module ApiTester
         
     | 
| 
      
 6 
     | 
    
         
            +
              # Class for defining plain arrays
         
     | 
| 
      
 7 
     | 
    
         
            +
              class PlainArrayField < Field
         
     | 
| 
      
 8 
     | 
    
         
            +
                def initialize(name:, default_value: [], required: false)
         
     | 
| 
      
 9 
     | 
    
         
            +
                  super name: name, default_value: default_value, required: required
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                def negative_boundary_values
         
     | 
| 
      
 13 
     | 
    
         
            +
                  super +
         
     | 
| 
      
 14 
     | 
    
         
            +
                    [
         
     | 
| 
      
 15 
     | 
    
         
            +
                      'string',
         
     | 
| 
      
 16 
     | 
    
         
            +
                      123,
         
     | 
| 
      
 17 
     | 
    
         
            +
                      0,
         
     | 
| 
      
 18 
     | 
    
         
            +
                      1,
         
     | 
| 
      
 19 
     | 
    
         
            +
                      {},
         
     | 
| 
      
 20 
     | 
    
         
            +
                      true,
         
     | 
| 
      
 21 
     | 
    
         
            +
                      false
         
     | 
| 
      
 22 
     | 
    
         
            +
                    ]
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,22 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module ApiTester
         
     | 
| 
      
 4 
     | 
    
         
            +
              # Class for defining methods as part of an endpoint
         
     | 
| 
      
 5 
     | 
    
         
            +
              class Method
         
     | 
| 
      
 6 
     | 
    
         
            +
                attr_accessor :request
         
     | 
| 
      
 7 
     | 
    
         
            +
                attr_accessor :expected_response
         
     | 
| 
      
 8 
     | 
    
         
            +
                attr_accessor :verb
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                def initialize(verb:, response:, request:)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  self.verb = verb
         
     | 
| 
      
 12 
     | 
    
         
            +
                  self.request = request
         
     | 
| 
      
 13 
     | 
    
         
            +
                  self.expected_response = response
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                def default_request
         
     | 
| 
      
 17 
     | 
    
         
            +
                  { method: verb,
         
     | 
| 
      
 18 
     | 
    
         
            +
                    payload: request.default_payload,
         
     | 
| 
      
 19 
     | 
    
         
            +
                    headers: request.default_headers }
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,96 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'api-tester/definition/boundary_case'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module ApiTester
         
     | 
| 
      
 6 
     | 
    
         
            +
              # Class for defining requests in a contract
         
     | 
| 
      
 7 
     | 
    
         
            +
              class Request
         
     | 
| 
      
 8 
     | 
    
         
            +
                attr_accessor :definition
         
     | 
| 
      
 9 
     | 
    
         
            +
                attr_accessor :header_fields
         
     | 
| 
      
 10 
     | 
    
         
            +
                attr_accessor :fields
         
     | 
| 
      
 11 
     | 
    
         
            +
                attr_accessor :query_params
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                def initialize
         
     | 
| 
      
 14 
     | 
    
         
            +
                  self.fields = []
         
     | 
| 
      
 15 
     | 
    
         
            +
                  self.header_fields = []
         
     | 
| 
      
 16 
     | 
    
         
            +
                  self.query_params = []
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                def add_field(new_field)
         
     | 
| 
      
 20 
     | 
    
         
            +
                  fields << new_field
         
     | 
| 
      
 21 
     | 
    
         
            +
                  self
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                def add_query_param(new_query_param)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  query_params << new_query_param
         
     | 
| 
      
 26 
     | 
    
         
            +
                  self
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                def default_query
         
     | 
| 
      
 30 
     | 
    
         
            +
                  query_params.map { |param| "#{param.name}=#{param.default_value}" }.join('&')
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                def add_header_field(new_header)
         
     | 
| 
      
 34 
     | 
    
         
            +
                  header_fields << new_header
         
     | 
| 
      
 35 
     | 
    
         
            +
                  self
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                def payload
         
     | 
| 
      
 39 
     | 
    
         
            +
                  response = {}
         
     | 
| 
      
 40 
     | 
    
         
            +
                  fields.each do |field|
         
     | 
| 
      
 41 
     | 
    
         
            +
                    if field.required == true
         
     | 
| 
      
 42 
     | 
    
         
            +
                      response[field.name] = field.default_value
         
     | 
| 
      
 43 
     | 
    
         
            +
                    end
         
     | 
| 
      
 44 
     | 
    
         
            +
                  end
         
     | 
| 
      
 45 
     | 
    
         
            +
                  response
         
     | 
| 
      
 46 
     | 
    
         
            +
                end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                def default_payload
         
     | 
| 
      
 49 
     | 
    
         
            +
                  payload
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                def default_headers
         
     | 
| 
      
 53 
     | 
    
         
            +
                  if header_fields != []
         
     | 
| 
      
 54 
     | 
    
         
            +
                    headers
         
     | 
| 
      
 55 
     | 
    
         
            +
                  else
         
     | 
| 
      
 56 
     | 
    
         
            +
                    { content_type: :json, accept: :json }
         
     | 
| 
      
 57 
     | 
    
         
            +
                  end
         
     | 
| 
      
 58 
     | 
    
         
            +
                end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                def headers
         
     | 
| 
      
 61 
     | 
    
         
            +
                  header_response = {}
         
     | 
| 
      
 62 
     | 
    
         
            +
                  header_fields.each do |header_field|
         
     | 
| 
      
 63 
     | 
    
         
            +
                    header_response[header_field.name] = header_field.default_value
         
     | 
| 
      
 64 
     | 
    
         
            +
                  end
         
     | 
| 
      
 65 
     | 
    
         
            +
                  header_response
         
     | 
| 
      
 66 
     | 
    
         
            +
                end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                def cases
         
     | 
| 
      
 69 
     | 
    
         
            +
                  boundary_cases = []
         
     | 
| 
      
 70 
     | 
    
         
            +
                  fields.each do |field|
         
     | 
| 
      
 71 
     | 
    
         
            +
                    field.negative_boundary_values.each do |value|
         
     | 
| 
      
 72 
     | 
    
         
            +
                      bcase = BoundaryCase.new description: "Setting #{field.name} to #{value}",
         
     | 
| 
      
 73 
     | 
    
         
            +
                                               payload: altered_payload(field_name: field.name,
         
     | 
| 
      
 74 
     | 
    
         
            +
                                                                        value: value),
         
     | 
| 
      
 75 
     | 
    
         
            +
                                               headers: default_headers
         
     | 
| 
      
 76 
     | 
    
         
            +
                      boundary_cases.push bcase
         
     | 
| 
      
 77 
     | 
    
         
            +
                    end
         
     | 
| 
      
 78 
     | 
    
         
            +
                  end
         
     | 
| 
      
 79 
     | 
    
         
            +
                  boundary_cases
         
     | 
| 
      
 80 
     | 
    
         
            +
                end
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                def altered_payload(field_name:, value:)
         
     | 
| 
      
 83 
     | 
    
         
            +
                  body = payload
         
     | 
| 
      
 84 
     | 
    
         
            +
                  body[field_name] = value
         
     | 
| 
      
 85 
     | 
    
         
            +
                  body
         
     | 
| 
      
 86 
     | 
    
         
            +
                end
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                def altered_payload_with(fields)
         
     | 
| 
      
 89 
     | 
    
         
            +
                  body = payload
         
     | 
| 
      
 90 
     | 
    
         
            +
                  fields.each do |field|
         
     | 
| 
      
 91 
     | 
    
         
            +
                    body[field[:name]] = field[:value]
         
     | 
| 
      
 92 
     | 
    
         
            +
                  end
         
     | 
| 
      
 93 
     | 
    
         
            +
                  body
         
     | 
| 
      
 94 
     | 
    
         
            +
                end
         
     | 
| 
      
 95 
     | 
    
         
            +
              end
         
     | 
| 
      
 96 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,39 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module ApiTester
         
     | 
| 
      
 4 
     | 
    
         
            +
              # Class for defining expected responses
         
     | 
| 
      
 5 
     | 
    
         
            +
              class Response
         
     | 
| 
      
 6 
     | 
    
         
            +
                attr_accessor :code
         
     | 
| 
      
 7 
     | 
    
         
            +
                attr_accessor :body
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                def initialize(status_code: 200)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  self.code = status_code
         
     | 
| 
      
 11 
     | 
    
         
            +
                  self.body = []
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                def add_field(new_field)
         
     | 
| 
      
 15 
     | 
    
         
            +
                  body << new_field
         
     | 
| 
      
 16 
     | 
    
         
            +
                  self
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                def to_s
         
     | 
| 
      
 20 
     | 
    
         
            +
                  des = {}
         
     | 
| 
      
 21 
     | 
    
         
            +
                  body.map do |f|
         
     | 
| 
      
 22 
     | 
    
         
            +
                    des[f.name] = field_display f
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
                  des.to_json
         
     | 
| 
      
 25 
     | 
    
         
            +
                end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                def field_display(field)
         
     | 
| 
      
 28 
     | 
    
         
            +
                  des = field.display_class
         
     | 
| 
      
 29 
     | 
    
         
            +
                  if field.subfields?
         
     | 
| 
      
 30 
     | 
    
         
            +
                    des = {}
         
     | 
| 
      
 31 
     | 
    
         
            +
                    field.fields.map do |f|
         
     | 
| 
      
 32 
     | 
    
         
            +
                      des[f.name] = field_display f
         
     | 
| 
      
 33 
     | 
    
         
            +
                    end
         
     | 
| 
      
 34 
     | 
    
         
            +
                    des.to_json
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
                  des
         
     | 
| 
      
 37 
     | 
    
         
            +
                end
         
     | 
| 
      
 38 
     | 
    
         
            +
              end
         
     | 
| 
      
 39 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,83 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'api-tester/util/response_evaluator.rb'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module ApiTester
         
     | 
| 
      
 6 
     | 
    
         
            +
              # Class for testing methods
         
     | 
| 
      
 7 
     | 
    
         
            +
              class MethodCaseTest
         
     | 
| 
      
 8 
     | 
    
         
            +
                attr_accessor :expected_response
         
     | 
| 
      
 9 
     | 
    
         
            +
                attr_accessor :payload
         
     | 
| 
      
 10 
     | 
    
         
            +
                attr_accessor :response
         
     | 
| 
      
 11 
     | 
    
         
            +
                attr_accessor :reports
         
     | 
| 
      
 12 
     | 
    
         
            +
                attr_accessor :url
         
     | 
| 
      
 13 
     | 
    
         
            +
                attr_accessor :module_name
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                def initialize(response:, payload:, expected_response:, url:, verb:, module_name:)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  self.payload = payload
         
     | 
| 
      
 17 
     | 
    
         
            +
                  self.response = response
         
     | 
| 
      
 18 
     | 
    
         
            +
                  self.expected_response = expected_response
         
     | 
| 
      
 19 
     | 
    
         
            +
                  self.reports = []
         
     | 
| 
      
 20 
     | 
    
         
            +
                  self.url = "#{verb} #{url}"
         
     | 
| 
      
 21 
     | 
    
         
            +
                  self.module_name = module_name
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                def response_code_report
         
     | 
| 
      
 25 
     | 
    
         
            +
                  report = StatusCodeReport.new description: "#{module_name} - Incorrect response code",
         
     | 
| 
      
 26 
     | 
    
         
            +
                                                url: url,
         
     | 
| 
      
 27 
     | 
    
         
            +
                                                request: payload,
         
     | 
| 
      
 28 
     | 
    
         
            +
                                                expected_status_code: expected_response.code,
         
     | 
| 
      
 29 
     | 
    
         
            +
                                                actual_status_code: "#{response.code} : #{response.body}"
         
     | 
| 
      
 30 
     | 
    
         
            +
                  reports << report
         
     | 
| 
      
 31 
     | 
    
         
            +
                  nil
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                def missing_field_report(field)
         
     | 
| 
      
 35 
     | 
    
         
            +
                  report = Report.new description: "#{module_name} - Missing field #{field}",
         
     | 
| 
      
 36 
     | 
    
         
            +
                                      url: url,
         
     | 
| 
      
 37 
     | 
    
         
            +
                                      request: payload,
         
     | 
| 
      
 38 
     | 
    
         
            +
                                      expected_response: expected_response,
         
     | 
| 
      
 39 
     | 
    
         
            +
                                      actual_response: response
         
     | 
| 
      
 40 
     | 
    
         
            +
                  reports << report
         
     | 
| 
      
 41 
     | 
    
         
            +
                  nil
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                def extra_field_report(field)
         
     | 
| 
      
 45 
     | 
    
         
            +
                  report = Report.new description: "#{module_name} - Found extra field #{field}",
         
     | 
| 
      
 46 
     | 
    
         
            +
                                      url: url,
         
     | 
| 
      
 47 
     | 
    
         
            +
                                      request: payload,
         
     | 
| 
      
 48 
     | 
    
         
            +
                                      expected_response: expected_response,
         
     | 
| 
      
 49 
     | 
    
         
            +
                                      actual_response: response
         
     | 
| 
      
 50 
     | 
    
         
            +
                  reports << report
         
     | 
| 
      
 51 
     | 
    
         
            +
                  nil
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                def check
         
     | 
| 
      
 55 
     | 
    
         
            +
                  if check_response_code
         
     | 
| 
      
 56 
     | 
    
         
            +
                    evaluator = ApiTester::ResponseEvaluator.new actual_body: json_parse(response.body),
         
     | 
| 
      
 57 
     | 
    
         
            +
                                                                 expected_fields: expected_response
         
     | 
| 
      
 58 
     | 
    
         
            +
                    evaluator.missing_fields.map { |field| missing_field_report(field) }
         
     | 
| 
      
 59 
     | 
    
         
            +
                    evaluator.extra_fields.map { |field| extra_field_report(field) }
         
     | 
| 
      
 60 
     | 
    
         
            +
                    increment_fields evaluator.seen_fields
         
     | 
| 
      
 61 
     | 
    
         
            +
                  end
         
     | 
| 
      
 62 
     | 
    
         
            +
                  reports
         
     | 
| 
      
 63 
     | 
    
         
            +
                end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                def check_response_code
         
     | 
| 
      
 66 
     | 
    
         
            +
                  if response.code != expected_response.code
         
     | 
| 
      
 67 
     | 
    
         
            +
                    response_code_report
         
     | 
| 
      
 68 
     | 
    
         
            +
                    return false
         
     | 
| 
      
 69 
     | 
    
         
            +
                  end
         
     | 
| 
      
 70 
     | 
    
         
            +
                  true
         
     | 
| 
      
 71 
     | 
    
         
            +
                end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                def increment_fields(seen_fields)
         
     | 
| 
      
 74 
     | 
    
         
            +
                  seen_fields.each(&:seen)
         
     | 
| 
      
 75 
     | 
    
         
            +
                end
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                def json_parse(body)
         
     | 
| 
      
 78 
     | 
    
         
            +
                  JSON.parse!(body)
         
     | 
| 
      
 79 
     | 
    
         
            +
                rescue JSON::ParserError
         
     | 
| 
      
 80 
     | 
    
         
            +
                  body
         
     | 
| 
      
 81 
     | 
    
         
            +
                end
         
     | 
| 
      
 82 
     | 
    
         
            +
              end
         
     | 
| 
      
 83 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,53 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'api-tester/util/supported_verbs'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module ApiTester
         
     | 
| 
      
 6 
     | 
    
         
            +
              # Check verbs not explicitly defined in contract
         
     | 
| 
      
 7 
     | 
    
         
            +
              module ExtraVerbs
         
     | 
| 
      
 8 
     | 
    
         
            +
                def self.go(contract)
         
     | 
| 
      
 9 
     | 
    
         
            +
                  reports = []
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  contract.endpoints.each do |endpoint|
         
     | 
| 
      
 12 
     | 
    
         
            +
                    extras = ApiTester::SupportedVerbs.all - endpoint.verbs
         
     | 
| 
      
 13 
     | 
    
         
            +
                    headers = endpoint.methods[0].request.default_headers
         
     | 
| 
      
 14 
     | 
    
         
            +
                    extras.each do |verb|
         
     | 
| 
      
 15 
     | 
    
         
            +
                      verb_case = BoundaryCase.new description: "Verb check with #{verb} for #{endpoint.name}",
         
     | 
| 
      
 16 
     | 
    
         
            +
                                                   payload: {},
         
     | 
| 
      
 17 
     | 
    
         
            +
                                                   headers: headers
         
     | 
| 
      
 18 
     | 
    
         
            +
                      method = ApiTester::Method.new verb: verb,
         
     | 
| 
      
 19 
     | 
    
         
            +
                                                     response: ApiTester::Response.new,
         
     | 
| 
      
 20 
     | 
    
         
            +
                                                     request: ApiTester::Request.new
         
     | 
| 
      
 21 
     | 
    
         
            +
                      response = endpoint.call base_url: contract.base_url,
         
     | 
| 
      
 22 
     | 
    
         
            +
                                               method: method,
         
     | 
| 
      
 23 
     | 
    
         
            +
                                               payload: verb_case.payload,
         
     | 
| 
      
 24 
     | 
    
         
            +
                                               headers: verb_case.headers
         
     | 
| 
      
 25 
     | 
    
         
            +
                      test = VerbClass.new response: response,
         
     | 
| 
      
 26 
     | 
    
         
            +
                                           payload: verb_case.payload,
         
     | 
| 
      
 27 
     | 
    
         
            +
                                           expected_response: endpoint.not_allowed_response,
         
     | 
| 
      
 28 
     | 
    
         
            +
                                           url: endpoint.url,
         
     | 
| 
      
 29 
     | 
    
         
            +
                                           verb: verb
         
     | 
| 
      
 30 
     | 
    
         
            +
                      reports.concat test.check
         
     | 
| 
      
 31 
     | 
    
         
            +
                    end
         
     | 
| 
      
 32 
     | 
    
         
            +
                  end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                  reports
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                def self.order
         
     | 
| 
      
 38 
     | 
    
         
            +
                  3
         
     | 
| 
      
 39 
     | 
    
         
            +
                end
         
     | 
| 
      
 40 
     | 
    
         
            +
              end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
              # Test template used for module
         
     | 
| 
      
 43 
     | 
    
         
            +
              class VerbClass < MethodCaseTest
         
     | 
| 
      
 44 
     | 
    
         
            +
                def initialize(response:, payload:, expected_response:, url:, verb:)
         
     | 
| 
      
 45 
     | 
    
         
            +
                  super response: response,
         
     | 
| 
      
 46 
     | 
    
         
            +
                        payload: payload,
         
     | 
| 
      
 47 
     | 
    
         
            +
                        expected_response: expected_response,
         
     | 
| 
      
 48 
     | 
    
         
            +
                        url: url,
         
     | 
| 
      
 49 
     | 
    
         
            +
                        verb: verb,
         
     | 
| 
      
 50 
     | 
    
         
            +
                        module_name: 'VerbModule'
         
     | 
| 
      
 51 
     | 
    
         
            +
                end
         
     | 
| 
      
 52 
     | 
    
         
            +
              end
         
     | 
| 
      
 53 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,47 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'api-tester/reporter/status_code_report'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'api-tester/method_case_test'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            module ApiTester
         
     | 
| 
      
 7 
     | 
    
         
            +
              # Checks the format constraints defined in contract
         
     | 
| 
      
 8 
     | 
    
         
            +
              module Format
         
     | 
| 
      
 9 
     | 
    
         
            +
                def self.go(contract)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  reports = []
         
     | 
| 
      
 11 
     | 
    
         
            +
                  contract.endpoints.each do |endpoint|
         
     | 
| 
      
 12 
     | 
    
         
            +
                    endpoint.methods.each do |method|
         
     | 
| 
      
 13 
     | 
    
         
            +
                      cases = method.request.cases
         
     | 
| 
      
 14 
     | 
    
         
            +
                      cases.each do |format_case|
         
     | 
| 
      
 15 
     | 
    
         
            +
                        response = endpoint.call base_url: contract.base_url,
         
     | 
| 
      
 16 
     | 
    
         
            +
                                                 method: method,
         
     | 
| 
      
 17 
     | 
    
         
            +
                                                 payload: format_case.payload,
         
     | 
| 
      
 18 
     | 
    
         
            +
                                                 headers: format_case.headers
         
     | 
| 
      
 19 
     | 
    
         
            +
                        test = FormatTest.new response: response,
         
     | 
| 
      
 20 
     | 
    
         
            +
                                              payload: format_case.payload,
         
     | 
| 
      
 21 
     | 
    
         
            +
                                              expected_response: endpoint.bad_request_response,
         
     | 
| 
      
 22 
     | 
    
         
            +
                                              url: endpoint.url,
         
     | 
| 
      
 23 
     | 
    
         
            +
                                              verb: method.verb
         
     | 
| 
      
 24 
     | 
    
         
            +
                        reports.concat test.check
         
     | 
| 
      
 25 
     | 
    
         
            +
                      end
         
     | 
| 
      
 26 
     | 
    
         
            +
                    end
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
                  reports
         
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                def self.order
         
     | 
| 
      
 32 
     | 
    
         
            +
                  2
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
      
 34 
     | 
    
         
            +
              end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
              # Test layout used by Format module
         
     | 
| 
      
 37 
     | 
    
         
            +
              class FormatTest < MethodCaseTest
         
     | 
| 
      
 38 
     | 
    
         
            +
                def initialize(response:, payload:, expected_response:, url:, verb:)
         
     | 
| 
      
 39 
     | 
    
         
            +
                  super response: response,
         
     | 
| 
      
 40 
     | 
    
         
            +
                        payload: payload,
         
     | 
| 
      
 41 
     | 
    
         
            +
                        expected_response: expected_response,
         
     | 
| 
      
 42 
     | 
    
         
            +
                        url: url,
         
     | 
| 
      
 43 
     | 
    
         
            +
                        verb: verb,
         
     | 
| 
      
 44 
     | 
    
         
            +
                        module_name: 'FormatModule'
         
     | 
| 
      
 45 
     | 
    
         
            +
                end
         
     | 
| 
      
 46 
     | 
    
         
            +
              end
         
     | 
| 
      
 47 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,46 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'api-tester/reporter/status_code_report'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'api-tester/method_case_test'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            module ApiTester
         
     | 
| 
      
 7 
     | 
    
         
            +
              # Checks the good case as defined in contract
         
     | 
| 
      
 8 
     | 
    
         
            +
              module GoodCase
         
     | 
| 
      
 9 
     | 
    
         
            +
                def self.go(contract)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  reports = []
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  contract.endpoints.each do |endpoint|
         
     | 
| 
      
 13 
     | 
    
         
            +
                    endpoint.methods.each do |method|
         
     | 
| 
      
 14 
     | 
    
         
            +
                      default_case = BoundaryCase.new description: contract.base_url + endpoint.url,
         
     | 
| 
      
 15 
     | 
    
         
            +
                                                      payload: method.request.default_payload,
         
     | 
| 
      
 16 
     | 
    
         
            +
                                                      headers: method.request.default_headers
         
     | 
| 
      
 17 
     | 
    
         
            +
                      response = endpoint.call base_url: contract.base_url,
         
     | 
| 
      
 18 
     | 
    
         
            +
                                               method: method,
         
     | 
| 
      
 19 
     | 
    
         
            +
                                               payload: default_case.payload,
         
     | 
| 
      
 20 
     | 
    
         
            +
                                               headers: default_case.headers
         
     | 
| 
      
 21 
     | 
    
         
            +
                      test = GoodCaseTest.new response: response,
         
     | 
| 
      
 22 
     | 
    
         
            +
                                              url: contract.base_url + endpoint.url,
         
     | 
| 
      
 23 
     | 
    
         
            +
                                              method: method
         
     | 
| 
      
 24 
     | 
    
         
            +
                      reports.concat test.check
         
     | 
| 
      
 25 
     | 
    
         
            +
                    end
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
                  reports
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                def self.order
         
     | 
| 
      
 31 
     | 
    
         
            +
                  1
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
              end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
              # Test layout used by module
         
     | 
| 
      
 36 
     | 
    
         
            +
              class GoodCaseTest < MethodCaseTest
         
     | 
| 
      
 37 
     | 
    
         
            +
                def initialize(response:, url:, method:)
         
     | 
| 
      
 38 
     | 
    
         
            +
                  super response: response,
         
     | 
| 
      
 39 
     | 
    
         
            +
                        payload: method.request.default_payload,
         
     | 
| 
      
 40 
     | 
    
         
            +
                        expected_response: method.expected_response,
         
     | 
| 
      
 41 
     | 
    
         
            +
                        url: url,
         
     | 
| 
      
 42 
     | 
    
         
            +
                        verb: method.verb,
         
     | 
| 
      
 43 
     | 
    
         
            +
                        module_name: 'GoodCaseModule'
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
              end
         
     | 
| 
      
 46 
     | 
    
         
            +
            end
         
     |