api-tester 1.1.1 → 1.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/dependabot.yml +29 -0
- data/.github/workflows/push.yml +1 -1
- data/.github/workflows/test.yml +3 -3
- data/.rubocop.yml +136 -26
- data/README.md +1 -1
- data/api-tester.gemspec +3 -3
- data/lib/api-tester/config.rb +1 -2
- data/lib/api-tester/definition/boundary_case.rb +1 -3
- data/lib/api-tester/definition/contract.rb +4 -4
- data/lib/api-tester/definition/endpoint.rb +35 -17
- data/lib/api-tester/definition/fields/array_field.rb +8 -4
- data/lib/api-tester/definition/fields/boolean_field.rb +9 -2
- data/lib/api-tester/definition/fields/email_field.rb +16 -2
- data/lib/api-tester/definition/fields/enum_field.rb +8 -4
- data/lib/api-tester/definition/fields/field.rb +12 -6
- data/lib/api-tester/definition/fields/number_field.rb +13 -2
- data/lib/api-tester/definition/fields/object_field.rb +8 -4
- data/lib/api-tester/definition/fields/plain_array_field.rb +2 -2
- data/lib/api-tester/definition/method.rb +1 -3
- data/lib/api-tester/definition/request.rb +7 -10
- data/lib/api-tester/definition/response.rb +11 -4
- data/lib/api-tester/method_case_test.rb +8 -8
- data/lib/api-tester/modules/benchmark_module.rb +35 -0
- data/lib/api-tester/modules/extra_verbs.rb +7 -1
- data/lib/api-tester/modules/good_case.rb +1 -1
- data/lib/api-tester/modules/good_variations.rb +69 -0
- data/lib/api-tester/modules/injection_module.rb +12 -6
- data/lib/api-tester/modules/missing_resource.rb +64 -0
- data/lib/api-tester/modules/server_information.rb +1 -2
- data/lib/api-tester/modules/typo.rb +3 -1
- data/lib/api-tester/modules/unused_fields.rb +1 -1
- data/lib/api-tester/reporter/api_report.rb +3 -2
- data/lib/api-tester/reporter/missing_field_report.rb +1 -4
- data/lib/api-tester/reporter/report.rb +2 -6
- data/lib/api-tester/reporter/response_time_report.rb +24 -0
- data/lib/api-tester/reporter/status_code_report.rb +1 -2
- data/lib/api-tester/test_helper.rb +2 -0
- data/lib/api-tester/util/response_evaluator.rb +37 -22
- data/lib/api-tester/util/supported_verbs.rb +2 -2
- data/lib/api-tester/version.rb +1 -1
- metadata +14 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 49d90cf3987edaf1eb823c6bb98fda6618ca9caf02a4475913cd9f7fd7a38c8d
|
4
|
+
data.tar.gz: d78b67dd228819bb6a7d9554206679f8b720d41df7acbaa28aef6db5c4bd2253
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8c65fa30cad7b220c5055991385a26b630a293fe05e4fe74841228fe3ca58516ec5f7f9745d984dbdc92a0cdf0125606bddf297187eb9a733da7d54d4eb78f1b
|
7
|
+
data.tar.gz: 9a53c3ce1e5bcd11179f718a231e966e61a536322ab096983e87caa7277223a777ef44505d8f766c50a0d196c83cd61fa0ea71f409cc5e4919f629159c3e1227
|
@@ -0,0 +1,29 @@
|
|
1
|
+
name: Dependabot Auto Merge
|
2
|
+
|
3
|
+
permissions:
|
4
|
+
pull-requests: write
|
5
|
+
contents: write
|
6
|
+
|
7
|
+
on:
|
8
|
+
pull_request:
|
9
|
+
# Allows you to run this workflow manually from the Actions tab
|
10
|
+
workflow_dispatch:
|
11
|
+
|
12
|
+
jobs:
|
13
|
+
dependabot:
|
14
|
+
# The type of runner that the job will run on
|
15
|
+
runs-on: ubuntu-latest
|
16
|
+
if: ${{ github.actor == 'dependabot[bot]' }}
|
17
|
+
# Steps represent a sequence of tasks that will be executed as part of the job
|
18
|
+
steps:
|
19
|
+
- name: Dependabot metadata
|
20
|
+
id: metadata
|
21
|
+
uses: dependabot/fetch-metadata@v1.3.3
|
22
|
+
with:
|
23
|
+
github-token: "${{ secrets.GITHUB_TOKEN }}"
|
24
|
+
|
25
|
+
- name: Enable auto-merge for Dependabot patch update PRs
|
26
|
+
run: gh pr merge --auto --merge "$PR_URL"
|
27
|
+
env:
|
28
|
+
PR_URL: ${{github.event.pull_request.html_url}}
|
29
|
+
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
data/.github/workflows/push.yml
CHANGED
data/.github/workflows/test.yml
CHANGED
@@ -7,7 +7,7 @@
|
|
7
7
|
|
8
8
|
name: Test
|
9
9
|
|
10
|
-
on: [push
|
10
|
+
on: [push]
|
11
11
|
|
12
12
|
jobs:
|
13
13
|
test:
|
@@ -15,12 +15,12 @@ jobs:
|
|
15
15
|
runs-on: ubuntu-latest
|
16
16
|
|
17
17
|
steps:
|
18
|
-
- uses: actions/checkout@
|
18
|
+
- uses: actions/checkout@v3
|
19
19
|
- name: Set up Ruby
|
20
20
|
# To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
|
21
21
|
# change this to (see https://github.com/ruby/setup-ruby#versioning):
|
22
22
|
# uses: ruby/setup-ruby@v1
|
23
|
-
uses: ruby/setup-ruby@
|
23
|
+
uses: ruby/setup-ruby@08245253a76fa4d1e459b7809579c62bd9eb718a
|
24
24
|
with:
|
25
25
|
ruby-version: 2.6
|
26
26
|
- name: Install dependencies
|
data/.rubocop.yml
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
AllCops:
|
2
|
+
NewCops: enable
|
2
3
|
Exclude:
|
3
4
|
- 'Guardfile'
|
4
5
|
- '*.gemspec'
|
@@ -6,56 +7,165 @@ AllCops:
|
|
6
7
|
- '**/*.rake'
|
7
8
|
- 'bin/*'
|
8
9
|
|
10
|
+
Gemspec/RequireMFA:
|
11
|
+
Enabled: true
|
12
|
+
Gemspec/DeprecatedAttributeAssignment: # (new in 1.10)
|
13
|
+
Enabled: true
|
14
|
+
Layout/LineContinuationLeadingSpace:
|
15
|
+
Enabled: true
|
16
|
+
Layout/LineContinuationSpacing:
|
17
|
+
Enabled: true
|
18
|
+
Layout/LineEndStringConcatenationIndentation:
|
19
|
+
Enabled: true
|
20
|
+
Layout/SpaceBeforeBrackets: # (new in 1.7)
|
21
|
+
Enabled: true
|
22
|
+
Lint/AmbiguousAssignment: # (new in 1.7)
|
23
|
+
Enabled: true
|
24
|
+
Lint/DeprecatedConstants: # (new in 1.8)
|
25
|
+
Enabled: true
|
26
|
+
Lint/DuplicateBranch: # (new in 1.3)
|
27
|
+
Enabled: false
|
28
|
+
Lint/DuplicateRegexpCharacterClassElement: # (new in 1.1)
|
29
|
+
Enabled: true
|
30
|
+
Lint/EmptyBlock: # (new in 1.1)
|
31
|
+
Enabled: true
|
32
|
+
Lint/EmptyClass: # (new in 1.3)
|
33
|
+
Enabled: true
|
34
|
+
Lint/LambdaWithoutLiteralBlock: # (new in 1.8)
|
35
|
+
Enabled: true
|
36
|
+
Lint/NoReturnInBeginEndBlocks: # (new in 1.2)
|
37
|
+
Enabled: true
|
38
|
+
Lint/NumberedParameterAssignment: # (new in 1.9)
|
39
|
+
Enabled: true
|
40
|
+
Lint/OrAssignmentToConstant: # (new in 1.9)
|
41
|
+
Enabled: true
|
42
|
+
Lint/RedundantDirGlobSort: # (new in 1.8)
|
43
|
+
Enabled: true
|
44
|
+
Lint/SymbolConversion: # (new in 1.9)
|
45
|
+
Enabled: true
|
46
|
+
Lint/ToEnumArguments: # (new in 1.1)
|
47
|
+
Enabled: true
|
48
|
+
Lint/TripleQuotes: # (new in 1.9)
|
49
|
+
Enabled: true
|
50
|
+
Lint/UnexpectedBlockArity: # (new in 1.5)
|
51
|
+
Enabled: true
|
52
|
+
Lint/UnmodifiedReduceAccumulator: # (new in 1.1)
|
53
|
+
Enabled: true
|
54
|
+
Lint/AmbiguousOperatorPrecedence:
|
55
|
+
Enabled: true
|
56
|
+
Lint/AmbiguousRange:
|
57
|
+
Enabled: true
|
58
|
+
Lint/ConstantOverwrittenInRescue:
|
59
|
+
Enabled: true
|
60
|
+
Lint/EmptyInPattern: # new in 1.16
|
61
|
+
Enabled: true
|
62
|
+
Lint/IncompatibleIoSelectWithFiberScheduler: # new in 1.21
|
63
|
+
Enabled: true
|
64
|
+
Lint/NonAtomicFileOperation: # new in 1.31
|
65
|
+
Enabled: true
|
66
|
+
Lint/RefinementImportMethods: # new in 1.27
|
67
|
+
Enabled: true
|
68
|
+
Lint/RequireRelativeSelfPath: # new in 1.22
|
69
|
+
Enabled: true
|
70
|
+
Lint/UselessRuby2Keywords: # new in 1.23
|
71
|
+
Enabled: true
|
72
|
+
Lint/BooleanSymbol:
|
73
|
+
Enabled: false
|
9
74
|
Metrics/BlockLength:
|
10
75
|
Enabled: false
|
11
|
-
|
12
76
|
Metrics/MethodLength:
|
13
77
|
Enabled: false
|
14
|
-
|
15
|
-
Metrics/LineLength:
|
78
|
+
Layout/LineLength:
|
16
79
|
Enabled: false
|
17
|
-
|
18
80
|
Metrics/AbcSize:
|
19
81
|
Enabled: false
|
20
|
-
|
82
|
+
Metrics/PerceivedComplexity:
|
83
|
+
Enabled: false
|
84
|
+
Metrics/CyclomaticComplexity:
|
85
|
+
Enabled: false
|
21
86
|
Metrics/ParameterLists:
|
22
87
|
Enabled: false
|
23
|
-
|
88
|
+
Naming/BlockForwarding: # new in 1.24
|
89
|
+
Enabled: true
|
24
90
|
Naming/PredicateName:
|
25
91
|
Enabled: false
|
26
|
-
|
92
|
+
Naming/FileName:
|
93
|
+
Enabled: false
|
94
|
+
Security/CompoundHash: # new in 1.28
|
95
|
+
Enabled: true
|
96
|
+
Security/IoMethods: # new in 1.22
|
97
|
+
Enabled: true
|
98
|
+
Style/EnvHome: # new in 1.29
|
99
|
+
Enabled: true
|
100
|
+
Style/FetchEnvVar: # new in 1.28
|
101
|
+
Enabled: true
|
102
|
+
Style/FileRead: # new in 1.24
|
103
|
+
Enabled: true
|
104
|
+
Style/FileWrite: # new in 1.24
|
105
|
+
Enabled: true
|
106
|
+
Style/InPatternThen: # new in 1.16
|
107
|
+
Enabled: true
|
108
|
+
Style/MapCompactWithConditionalBlock: # new in 1.30
|
109
|
+
Enabled: true
|
110
|
+
Style/MapToHash: # new in 1.24
|
111
|
+
Enabled: true
|
112
|
+
Style/MultilineInPatternThen: # new in 1.16
|
113
|
+
Enabled: true
|
114
|
+
Style/NestedFileDirname: # new in 1.26
|
115
|
+
Enabled: true
|
116
|
+
Style/NumberedParameters: # new in 1.22
|
117
|
+
Enabled: true
|
118
|
+
Style/NumberedParametersLimit: # new in 1.22
|
119
|
+
Enabled: true
|
120
|
+
Style/ObjectThen: # new in 1.28
|
121
|
+
Enabled: true
|
122
|
+
Style/OpenStructUse: # new in 1.23
|
123
|
+
Enabled: true
|
124
|
+
Style/QuotedSymbols: # new in 1.16
|
125
|
+
Enabled: true
|
126
|
+
Style/RedundantInitialize: # new in 1.27
|
127
|
+
Enabled: false
|
128
|
+
Style/RedundantSelfAssignmentBranch: # new in 1.19
|
129
|
+
Enabled: true
|
130
|
+
Style/SelectByRegexp: # new in 1.22
|
131
|
+
Enabled: true
|
27
132
|
Style/IfUnlessModifier:
|
28
133
|
Enabled: false
|
29
|
-
|
30
134
|
Style/NilComparison:
|
31
135
|
Enabled: false
|
32
|
-
|
33
136
|
Style/NumericPredicate:
|
34
137
|
Enabled: false
|
35
|
-
|
36
138
|
Style/MultipleComparison:
|
37
139
|
Enabled: false
|
38
|
-
|
39
|
-
Metrics/PerceivedComplexity:
|
40
|
-
Enabled: false
|
41
|
-
|
42
|
-
Metrics/CyclomaticComplexity:
|
43
|
-
Enabled: false
|
44
|
-
|
45
140
|
Style/BlockDelimiters:
|
46
141
|
Enabled: false
|
47
|
-
|
48
142
|
Style/EmptyLiteral:
|
49
143
|
Enabled: false
|
50
|
-
|
51
|
-
Lint/BooleanSymbol:
|
52
|
-
Enabled: false
|
53
|
-
|
54
144
|
Style/GuardClause:
|
55
145
|
Enabled: false
|
56
|
-
|
57
|
-
Naming/FileName:
|
58
|
-
Enabled: false
|
59
|
-
|
60
146
|
Style/FrozenStringLiteralComment:
|
61
147
|
Enabled: false
|
148
|
+
Style/ArgumentsForwarding: # (new in 1.1)
|
149
|
+
Enabled: true
|
150
|
+
Style/CollectionCompact: # (new in 1.2)
|
151
|
+
Enabled: true
|
152
|
+
Style/DocumentDynamicEvalDefinition: # (new in 1.1)
|
153
|
+
Enabled: true
|
154
|
+
Style/EndlessMethod: # (new in 1.8)
|
155
|
+
Enabled: true
|
156
|
+
Style/HashConversion: # (new in 1.10)
|
157
|
+
Enabled: true
|
158
|
+
Style/HashExcept: # (new in 1.7)
|
159
|
+
Enabled: true
|
160
|
+
Style/IfWithBooleanLiteralBranches: # (new in 1.9)
|
161
|
+
Enabled: true
|
162
|
+
Style/NegatedIfElseCondition: # (new in 1.2)
|
163
|
+
Enabled: true
|
164
|
+
Style/NilLambda: # (new in 1.3)
|
165
|
+
Enabled: true
|
166
|
+
Style/RedundantArgument: # (new in 1.4)
|
167
|
+
Enabled: true
|
168
|
+
Style/StringChars: # (new in 1.12)
|
169
|
+
Enabled: true
|
170
|
+
Style/SwapValues:
|
171
|
+
Enabled: true
|
data/README.md
CHANGED
@@ -207,7 +207,7 @@ Bug reports and pull requests are welcome on [GitHub repo](https://github.com/ar
|
|
207
207
|
|
208
208
|
## Future Features Under Development
|
209
209
|
|
210
|
-
Check out our [
|
210
|
+
Check out our [Project Board](https://github.com/araneforseti/api-tester/projects/1) to see progress and where we are headed!
|
211
211
|
Feel free to leave feedback through Github's issue tracker
|
212
212
|
|
213
213
|
- Other Param Testing
|
data/api-tester.gemspec
CHANGED
@@ -31,17 +31,17 @@ Gem::Specification.new do |spec|
|
|
31
31
|
spec.require_paths = ['lib']
|
32
32
|
|
33
33
|
spec.add_development_dependency 'bundler'
|
34
|
-
spec.add_development_dependency 'bundler-audit', '~>0.
|
34
|
+
spec.add_development_dependency 'bundler-audit', '~>0.9.0'
|
35
35
|
spec.add_development_dependency 'guard-rspec', '~> 4.7.3'
|
36
36
|
spec.add_development_dependency 'pry', '~> 0.11'
|
37
37
|
spec.add_development_dependency 'rake', '~> 13.0.1'
|
38
38
|
spec.add_development_dependency 'require_all', '~>3.0.0'
|
39
39
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
40
|
-
spec.add_development_dependency 'rubocop', '~>
|
40
|
+
spec.add_development_dependency 'rubocop', '~> 1.31.0'
|
41
41
|
spec.add_development_dependency 'terminal-notifier', '~> 2.0.0'
|
42
42
|
spec.add_development_dependency 'terminal-notifier-guard', '~> 1.7.0'
|
43
43
|
spec.add_development_dependency 'webmock', '~> 3.4'
|
44
44
|
|
45
|
-
spec.add_runtime_dependency 'injection_vulnerability_library', '0.
|
45
|
+
spec.add_runtime_dependency 'injection_vulnerability_library', '0.1.3'
|
46
46
|
spec.add_runtime_dependency 'rest-client', '~> 2.0'
|
47
47
|
end
|
data/lib/api-tester/config.rb
CHANGED
@@ -5,8 +5,7 @@ require 'api-tester/reporter/api_report'
|
|
5
5
|
module ApiTester
|
6
6
|
# Config class for changing how the tool operates
|
7
7
|
class Config
|
8
|
-
attr_accessor :reporter
|
9
|
-
attr_accessor :modules
|
8
|
+
attr_accessor :reporter, :modules
|
10
9
|
|
11
10
|
def initialize(reporter: ApiTester::ApiReport.new)
|
12
11
|
self.reporter = reporter
|
@@ -3,9 +3,7 @@
|
|
3
3
|
module ApiTester
|
4
4
|
# Holds data necessary for tests
|
5
5
|
class BoundaryCase
|
6
|
-
attr_accessor :payload
|
7
|
-
attr_accessor :headers
|
8
|
-
attr_accessor :description
|
6
|
+
attr_accessor :payload, :headers, :description
|
9
7
|
|
10
8
|
def initialize(description:, payload:, headers:)
|
11
9
|
self.description = description
|
@@ -3,14 +3,14 @@
|
|
3
3
|
module ApiTester
|
4
4
|
# Class to define the whole contract
|
5
5
|
class Contract
|
6
|
-
attr_accessor :name
|
7
|
-
attr_accessor :endpoints
|
8
|
-
attr_accessor :base_url
|
6
|
+
attr_accessor :name, :endpoints, :base_url, :max_time, :required_headers
|
9
7
|
|
10
|
-
def initialize(name:, base_url:)
|
8
|
+
def initialize(name:, base_url:, max_time: 500)
|
11
9
|
self.name = name
|
12
10
|
self.endpoints = []
|
13
11
|
self.base_url = base_url
|
12
|
+
self.max_time = max_time
|
13
|
+
self.required_headers = {}
|
14
14
|
end
|
15
15
|
|
16
16
|
def add_endpoint(endpoint)
|
@@ -3,36 +3,38 @@
|
|
3
3
|
require 'api-tester/definition/response'
|
4
4
|
require 'api-tester/definition/method'
|
5
5
|
require 'api-tester/test_helper'
|
6
|
+
require 'benchmark'
|
6
7
|
require 'rest-client'
|
7
8
|
require 'json'
|
9
|
+
require 'pry'
|
8
10
|
|
9
11
|
module ApiTester
|
10
12
|
# Class for defining and interacting with endpoints in a contract
|
11
13
|
class Endpoint
|
12
|
-
attr_accessor :name
|
13
|
-
attr_accessor :relative_url
|
14
|
-
attr_accessor :path_params
|
15
|
-
attr_accessor :methods
|
16
|
-
attr_accessor :test_helper
|
17
|
-
attr_accessor :bad_request_response
|
18
|
-
attr_accessor :not_allowed_response
|
19
|
-
attr_accessor :not_found_response
|
14
|
+
attr_accessor :name, :relative_url, :path_params, :methods, :test_helper, :bad_request_response, :not_allowed_response, :not_found_response, :longest_time, :required_headers
|
20
15
|
|
21
16
|
def initialize(name:, relative_url:)
|
22
17
|
self.relative_url = relative_url
|
23
18
|
self.name = name
|
24
19
|
self.methods = []
|
25
20
|
self.path_params = []
|
26
|
-
self.
|
21
|
+
self.longest_time = { time: 0 }
|
22
|
+
self.test_helper = ApiTester::TestHelper.new ''
|
27
23
|
self.bad_request_response = ApiTester::Response.new status_code: 400
|
28
24
|
self.not_allowed_response = ApiTester::Response.new status_code: 415
|
29
25
|
self.not_found_response = ApiTester::Response.new status_code: 404
|
26
|
+
self.required_headers = {}
|
27
|
+
end
|
28
|
+
|
29
|
+
def display_url
|
30
|
+
relative_url
|
30
31
|
end
|
31
32
|
|
32
33
|
def url
|
33
|
-
temp_url = relative_url
|
34
|
+
temp_url = relative_url.clone
|
34
35
|
path_params.each do |param|
|
35
|
-
|
36
|
+
value = test_helper.retrieve_param(param).to_s
|
37
|
+
temp_url = relative_url.sub "{#{param}}", value
|
36
38
|
end
|
37
39
|
temp_url
|
38
40
|
end
|
@@ -42,7 +44,15 @@ module ApiTester
|
|
42
44
|
method_defaults = methods[0].default_request
|
43
45
|
method_defaults[:url] = "#{base_url}#{url}"
|
44
46
|
begin
|
45
|
-
response =
|
47
|
+
response = nil
|
48
|
+
time = Benchmark.measure {
|
49
|
+
response = RestClient::Request.execute(method_defaults)
|
50
|
+
}
|
51
|
+
if time.real > longest_time[:time] && longest_time[:time] > 0
|
52
|
+
longest_time[:time] = time.real
|
53
|
+
longest_time[:payload] = payload.to_json
|
54
|
+
longest_time[:verb] = method.verb
|
55
|
+
end
|
46
56
|
rescue RestClient::ExceptionWithResponse => e
|
47
57
|
response = e.response
|
48
58
|
end
|
@@ -52,12 +62,20 @@ module ApiTester
|
|
52
62
|
|
53
63
|
def call(base_url:, method:, query: '', payload: {}, headers: {})
|
54
64
|
test_helper.before
|
55
|
-
|
65
|
+
call_url = query ? "#{base_url}#{url}?#{query}" : "#{base_url}#{url}"
|
56
66
|
begin
|
57
|
-
response =
|
58
|
-
|
59
|
-
|
60
|
-
|
67
|
+
response = nil
|
68
|
+
time = Benchmark.measure {
|
69
|
+
response = RestClient::Request.execute(method: method.verb,
|
70
|
+
url: call_url,
|
71
|
+
payload: payload.to_json,
|
72
|
+
headers: headers)
|
73
|
+
}
|
74
|
+
if time.real > longest_time[:time]
|
75
|
+
longest_time[:time] = time.real
|
76
|
+
longest_time[:payload] = payload.to_json
|
77
|
+
longest_time[:verb] = method.verb
|
78
|
+
end
|
61
79
|
rescue RestClient::ExceptionWithResponse => e
|
62
80
|
response = e.response
|
63
81
|
end
|
@@ -7,8 +7,8 @@ module ApiTester
|
|
7
7
|
class ArrayField < Field
|
8
8
|
attr_accessor :fields
|
9
9
|
|
10
|
-
def initialize(name:, required: false)
|
11
|
-
super name: name, required: required
|
10
|
+
def initialize(name:, required: false, has_key: true)
|
11
|
+
super name: name, required: required, has_key: has_key
|
12
12
|
self.fields = []
|
13
13
|
end
|
14
14
|
|
@@ -21,12 +21,16 @@ module ApiTester
|
|
21
21
|
true
|
22
22
|
end
|
23
23
|
|
24
|
-
def
|
24
|
+
def type
|
25
|
+
'array'
|
26
|
+
end
|
27
|
+
|
28
|
+
def default
|
25
29
|
return [] if fields.size.zero?
|
26
30
|
|
27
31
|
obj = {}
|
28
32
|
fields.each do |field|
|
29
|
-
obj[field.name] = field.
|
33
|
+
obj[field.name] = field.default
|
30
34
|
end
|
31
35
|
[obj]
|
32
36
|
end
|
@@ -5,8 +5,8 @@ require 'api-tester/definition/fields/field'
|
|
5
5
|
module ApiTester
|
6
6
|
# Class for defining booleans in contract
|
7
7
|
class BooleanField < Field
|
8
|
-
def initialize(name:,
|
9
|
-
super name: name,
|
8
|
+
def initialize(name:, default: true, required: false)
|
9
|
+
super name: name, default: default, required: required
|
10
10
|
end
|
11
11
|
|
12
12
|
def negative_boundary_values
|
@@ -19,5 +19,12 @@ module ApiTester
|
|
19
19
|
{}
|
20
20
|
]
|
21
21
|
end
|
22
|
+
|
23
|
+
def good_cases
|
24
|
+
[
|
25
|
+
true,
|
26
|
+
false
|
27
|
+
]
|
28
|
+
end
|
22
29
|
end
|
23
30
|
end
|
@@ -1,12 +1,26 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'securerandom'
|
4
|
+
|
3
5
|
require 'api-tester/definition/fields/field'
|
4
6
|
|
5
7
|
module ApiTester
|
6
8
|
# Class for defining email fields in contract
|
7
9
|
class EmailField < Field
|
8
|
-
|
9
|
-
|
10
|
+
attr_accessor :randomize
|
11
|
+
|
12
|
+
def initialize(name:, default: 'test@test.com', required: false, randomize: false)
|
13
|
+
super name: name, default: default, required: required
|
14
|
+
self.randomize = randomize
|
15
|
+
end
|
16
|
+
|
17
|
+
def default
|
18
|
+
# Since many APIs have unique email checks, this allows us to generate hopefully unique emails
|
19
|
+
if randomize
|
20
|
+
"test#{SecureRandom.hex(10)}@test.com"
|
21
|
+
else
|
22
|
+
super
|
23
|
+
end
|
10
24
|
end
|
11
25
|
|
12
26
|
def negative_boundary_values
|
@@ -7,11 +7,11 @@ module ApiTester
|
|
7
7
|
class EnumField < Field
|
8
8
|
attr_accessor :acceptable_values
|
9
9
|
|
10
|
-
def initialize(name:, acceptable_values:,
|
11
|
-
if
|
12
|
-
super name: name,
|
10
|
+
def initialize(name:, acceptable_values:, default: nil, required: false)
|
11
|
+
if default
|
12
|
+
super name: name, default: default, required: required
|
13
13
|
else
|
14
|
-
super name: name,
|
14
|
+
super name: name, default: acceptable_values[0], required: required
|
15
15
|
end
|
16
16
|
|
17
17
|
self.acceptable_values = acceptable_values
|
@@ -28,5 +28,9 @@ module ApiTester
|
|
28
28
|
{}
|
29
29
|
]
|
30
30
|
end
|
31
|
+
|
32
|
+
def good_cases
|
33
|
+
acceptable_values
|
34
|
+
end
|
31
35
|
end
|
32
36
|
end
|
@@ -3,16 +3,18 @@
|
|
3
3
|
module ApiTester
|
4
4
|
# Base class for field definitions
|
5
5
|
class Field
|
6
|
-
attr_accessor :name
|
7
|
-
attr_accessor :default_value
|
8
|
-
attr_accessor :required
|
9
|
-
attr_accessor :is_seen
|
6
|
+
attr_accessor :name, :default, :required, :is_seen, :has_key
|
10
7
|
|
11
|
-
def initialize(name:, required: false,
|
8
|
+
def initialize(name:, required: false, has_key: true, default: 'string')
|
12
9
|
self.name = name
|
13
|
-
self.
|
10
|
+
self.default = default
|
14
11
|
self.required = required
|
15
12
|
self.is_seen = 0
|
13
|
+
self.has_key = has_key
|
14
|
+
end
|
15
|
+
|
16
|
+
def type
|
17
|
+
'field'
|
16
18
|
end
|
17
19
|
|
18
20
|
def is_required
|
@@ -39,6 +41,10 @@ module ApiTester
|
|
39
41
|
cases
|
40
42
|
end
|
41
43
|
|
44
|
+
def good_cases
|
45
|
+
[]
|
46
|
+
end
|
47
|
+
|
42
48
|
def seen
|
43
49
|
self.is_seen += 1
|
44
50
|
end
|
@@ -5,8 +5,8 @@ require 'api-tester/definition/fields/field'
|
|
5
5
|
module ApiTester
|
6
6
|
# Class for defining numeric fields in contracts
|
7
7
|
class NumberField < Field
|
8
|
-
def initialize(name:,
|
9
|
-
super name: name,
|
8
|
+
def initialize(name:, default: 5, required: false)
|
9
|
+
super name: name, default: default, required: required
|
10
10
|
end
|
11
11
|
|
12
12
|
def negative_boundary_values
|
@@ -18,5 +18,16 @@ module ApiTester
|
|
18
18
|
{}
|
19
19
|
]
|
20
20
|
end
|
21
|
+
|
22
|
+
def good_cases
|
23
|
+
[
|
24
|
+
-1,
|
25
|
+
0,
|
26
|
+
1,
|
27
|
+
100,
|
28
|
+
9999,
|
29
|
+
12_345_678_901_234_567_890
|
30
|
+
]
|
31
|
+
end
|
21
32
|
end
|
22
33
|
end
|
@@ -7,8 +7,8 @@ module ApiTester
|
|
7
7
|
class ObjectField < Field
|
8
8
|
attr_accessor :fields
|
9
9
|
|
10
|
-
def initialize(name:, required: false)
|
11
|
-
super name: name, required: required
|
10
|
+
def initialize(name:, required: false, has_key: true)
|
11
|
+
super name: name, required: required, has_key: has_key
|
12
12
|
self.fields = []
|
13
13
|
end
|
14
14
|
|
@@ -21,11 +21,15 @@ module ApiTester
|
|
21
21
|
true
|
22
22
|
end
|
23
23
|
|
24
|
-
def
|
24
|
+
def type
|
25
|
+
'object'
|
26
|
+
end
|
27
|
+
|
28
|
+
def default
|
25
29
|
obj = {}
|
26
30
|
|
27
31
|
fields.each do |field|
|
28
|
-
obj[field.name] = field.
|
32
|
+
obj[field.name] = field.default
|
29
33
|
end
|
30
34
|
|
31
35
|
obj
|
@@ -5,8 +5,8 @@ require 'api-tester/definition/fields/field'
|
|
5
5
|
module ApiTester
|
6
6
|
# Class for defining plain arrays
|
7
7
|
class PlainArrayField < Field
|
8
|
-
def initialize(name:,
|
9
|
-
super name: name,
|
8
|
+
def initialize(name:, default: [], required: false)
|
9
|
+
super name: name, default: default, required: required
|
10
10
|
end
|
11
11
|
|
12
12
|
def negative_boundary_values
|
@@ -3,9 +3,7 @@
|
|
3
3
|
module ApiTester
|
4
4
|
# Class for defining methods as part of an endpoint
|
5
5
|
class Method
|
6
|
-
attr_accessor :request
|
7
|
-
attr_accessor :expected_response
|
8
|
-
attr_accessor :verb
|
6
|
+
attr_accessor :request, :expected_response, :verb
|
9
7
|
|
10
8
|
def initialize(verb:, response:, request:)
|
11
9
|
self.verb = verb
|