api-tester 0.3.1 → 1.1.2
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/dependabot.yml +29 -0
- data/.github/workflows/push.yml +39 -0
- data/.github/workflows/test.yml +31 -0
- data/.rspec +1 -0
- data/.rubocop.yml +171 -0
- data/Gemfile +2 -0
- data/Guardfile +70 -0
- data/README.md +67 -63
- data/Rakefile +8 -3
- data/api-tester.gemspec +29 -23
- data/changelog.txt +19 -0
- data/lib/api-tester/config.rb +17 -15
- data/lib/api-tester/definition/boundary_case.rb +5 -4
- data/lib/api-tester/definition/contract.rb +10 -5
- data/lib/api-tester/definition/endpoint.rb +59 -32
- data/lib/api-tester/definition/fields/array_field.rb +26 -21
- data/lib/api-tester/definition/fields/boolean_field.rb +17 -7
- data/lib/api-tester/definition/fields/email_field.rb +28 -11
- data/lib/api-tester/definition/fields/enum_field.rb +19 -12
- data/lib/api-tester/definition/fields/field.rb +52 -45
- data/lib/api-tester/definition/fields/number_field.rb +20 -6
- data/lib/api-tester/definition/fields/object_field.rb +37 -30
- data/lib/api-tester/definition/fields/plain_array_field.rb +25 -0
- data/lib/api-tester/definition/method.rb +8 -5
- data/lib/api-tester/definition/request.rb +55 -13
- data/lib/api-tester/definition/response.rb +35 -25
- data/lib/api-tester/method_case_test.rb +68 -54
- data/lib/api-tester/modules/benchmark_module.rb +35 -0
- data/lib/api-tester/modules/extra_verbs.rb +37 -10
- data/lib/api-tester/modules/format.rb +23 -8
- data/lib/api-tester/modules/good_case.rb +25 -10
- data/lib/api-tester/modules/good_variations.rb +69 -0
- data/lib/api-tester/modules/injection_module.rb +44 -23
- data/lib/api-tester/modules/missing_resource.rb +64 -0
- data/lib/api-tester/modules/required_fields.rb +51 -0
- data/lib/api-tester/modules/server_information.rb +14 -12
- data/lib/api-tester/modules/typo.rb +39 -14
- data/lib/api-tester/modules/unexpected_fields.rb +61 -0
- data/lib/api-tester/modules/unused_fields.rb +13 -7
- data/lib/api-tester/reporter/api_report.rb +25 -16
- data/lib/api-tester/reporter/missing_field_report.rb +11 -15
- data/lib/api-tester/reporter/report.rb +12 -13
- data/lib/api-tester/reporter/response_time_report.rb +24 -0
- data/lib/api-tester/reporter/status_code_report.rb +10 -4
- data/lib/api-tester/test_helper.rb +8 -6
- data/lib/api-tester/util/response_evaluator.rb +84 -56
- data/lib/api-tester/util/supported_verbs.rb +8 -5
- data/lib/api-tester/version.rb +3 -1
- data/lib/api-tester.rb +6 -3
- metadata +117 -24
- data/.travis.yml +0 -6
- data/lib/api-tester/reporter/missing_response_field_report.rb +0 -21
data/api-tester.gemspec
CHANGED
@@ -4,38 +4,44 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
require 'api-tester/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
7
|
+
spec.name = 'api-tester'
|
8
8
|
spec.version = ApiTester::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
9
|
+
spec.authors = ['arane']
|
10
|
+
spec.email = ['arane9@gmail.com']
|
11
11
|
|
12
|
-
spec.summary =
|
13
|
-
spec.description =
|
14
|
-
spec.homepage =
|
15
|
-
spec.license =
|
12
|
+
spec.summary = 'Tool to help test APIs'
|
13
|
+
spec.description = 'Tool to test APIs which will eventually do boundary testing and other sorts of testing automatically given a contract'
|
14
|
+
spec.homepage = 'https://github.com/araneforseti/api-tester'
|
15
|
+
spec.license = 'MIT'
|
16
16
|
|
17
17
|
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
18
18
|
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
19
|
-
if spec.respond_to?(:metadata)
|
20
|
-
spec.metadata['allowed_push_host'] = 'https://rubygems.org/'
|
21
|
-
else
|
22
|
-
raise
|
23
|
-
|
24
|
-
end
|
19
|
+
# if spec.respond_to?(:metadata)
|
20
|
+
# spec.metadata['allowed_push_host'] = 'https://rubygems.org/'
|
21
|
+
# else
|
22
|
+
# raise 'RubyGems 2.0 or newer is required to protect against ' \
|
23
|
+
# 'public gem pushes.'
|
24
|
+
# end
|
25
25
|
|
26
|
-
spec.files
|
26
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
27
27
|
f.match(%r{^(test|spec|features)/})
|
28
28
|
end
|
29
|
-
spec.bindir =
|
29
|
+
spec.bindir = 'exe'
|
30
30
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
31
|
-
spec.require_paths = [
|
31
|
+
spec.require_paths = ['lib']
|
32
32
|
|
33
|
-
spec.add_development_dependency
|
34
|
-
spec.add_development_dependency
|
35
|
-
spec.add_development_dependency
|
36
|
-
spec.add_development_dependency
|
37
|
-
spec.add_development_dependency
|
33
|
+
spec.add_development_dependency 'bundler'
|
34
|
+
spec.add_development_dependency 'bundler-audit', '~>0.9.0'
|
35
|
+
spec.add_development_dependency 'guard-rspec', '~> 4.7.3'
|
36
|
+
spec.add_development_dependency 'pry', '~> 0.11'
|
37
|
+
spec.add_development_dependency 'rake', '~> 13.0.1'
|
38
|
+
spec.add_development_dependency 'require_all', '~>3.0.0'
|
39
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
40
|
+
spec.add_development_dependency 'rubocop', '~> 1.31.0'
|
41
|
+
spec.add_development_dependency 'terminal-notifier', '~> 2.0.0'
|
42
|
+
spec.add_development_dependency 'terminal-notifier-guard', '~> 1.7.0'
|
43
|
+
spec.add_development_dependency 'webmock', '~> 3.4'
|
38
44
|
|
39
|
-
spec.add_runtime_dependency
|
40
|
-
spec.add_runtime_dependency
|
45
|
+
spec.add_runtime_dependency 'injection_vulnerability_library', '0.1.3'
|
46
|
+
spec.add_runtime_dependency 'rest-client', '~> 2.0'
|
41
47
|
end
|
data/changelog.txt
CHANGED
@@ -1,3 +1,22 @@
|
|
1
|
+
2.0.0
|
2
|
+
|
3
|
+
- Added Required Fields module
|
4
|
+
- Added Unexpected Fields module
|
5
|
+
- Adding query params to definition
|
6
|
+
- Moved base_url to contract
|
7
|
+
- Changed endpoints to be relative urls
|
8
|
+
- Removed missing field report as it was unused
|
9
|
+
- Changing everything with more than one parameter to named parameters
|
10
|
+
|
11
|
+
1.0.0
|
12
|
+
|
13
|
+
- Switching to using named variables to make future changes less breaky
|
14
|
+
|
15
|
+
0.3.2
|
16
|
+
|
17
|
+
- Fixing some issues with how config adds modules
|
18
|
+
- Fixing README for same module issue as config
|
19
|
+
|
1
20
|
0.3.1
|
2
21
|
|
3
22
|
- Adding ability to change headers for request objects
|
data/lib/api-tester/config.rb
CHANGED
@@ -1,39 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'api-tester/reporter/api_report'
|
2
4
|
|
3
5
|
module ApiTester
|
6
|
+
# Config class for changing how the tool operates
|
4
7
|
class Config
|
5
|
-
attr_accessor :reporter
|
6
|
-
attr_accessor :modules
|
8
|
+
attr_accessor :reporter, :modules
|
7
9
|
|
8
|
-
def initialize
|
10
|
+
def initialize(reporter: ApiTester::ApiReport.new)
|
9
11
|
self.reporter = reporter
|
10
12
|
self.modules = []
|
11
13
|
end
|
12
14
|
|
13
|
-
def with_reporter
|
15
|
+
def with_reporter(reporter)
|
14
16
|
self.reporter = reporter
|
15
17
|
self
|
16
18
|
end
|
17
19
|
|
18
|
-
def with_module
|
19
|
-
|
20
|
+
def with_module(new_module)
|
21
|
+
modules << new_module
|
20
22
|
self
|
21
23
|
end
|
22
24
|
|
23
25
|
def with_default_modules
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
26
|
+
modules << Format
|
27
|
+
modules << GoodCase
|
28
|
+
modules << Typo
|
29
|
+
modules << UnusedFields
|
28
30
|
self
|
29
31
|
end
|
30
32
|
|
31
33
|
def with_all_modules
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
34
|
+
modules << Format
|
35
|
+
modules << ExtraVerbs
|
36
|
+
modules << GoodCase
|
37
|
+
modules << Typo
|
38
|
+
modules << UnusedFields
|
37
39
|
self
|
38
40
|
end
|
39
41
|
end
|
@@ -1,10 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ApiTester
|
4
|
+
# Holds data necessary for tests
|
2
5
|
class BoundaryCase
|
3
|
-
attr_accessor :payload
|
4
|
-
attr_accessor :headers
|
5
|
-
attr_accessor :description
|
6
|
+
attr_accessor :payload, :headers, :description
|
6
7
|
|
7
|
-
def initialize
|
8
|
+
def initialize(description:, payload:, headers:)
|
8
9
|
self.description = description
|
9
10
|
self.payload = payload
|
10
11
|
self.headers = headers
|
@@ -1,15 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ApiTester
|
4
|
+
# Class to define the whole contract
|
2
5
|
class Contract
|
3
|
-
attr_accessor :name
|
4
|
-
attr_accessor :endpoints
|
6
|
+
attr_accessor :name, :endpoints, :base_url, :max_time, :required_headers
|
5
7
|
|
6
|
-
def initialize
|
8
|
+
def initialize(name:, base_url:, max_time: 500)
|
7
9
|
self.name = name
|
8
10
|
self.endpoints = []
|
11
|
+
self.base_url = base_url
|
12
|
+
self.max_time = max_time
|
13
|
+
self.required_headers = {}
|
9
14
|
end
|
10
15
|
|
11
|
-
def add_endpoint
|
12
|
-
|
16
|
+
def add_endpoint(endpoint)
|
17
|
+
endpoints << endpoint
|
13
18
|
end
|
14
19
|
end
|
15
20
|
end
|
@@ -1,75 +1,102 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'api-tester/definition/response'
|
2
4
|
require 'api-tester/definition/method'
|
3
5
|
require 'api-tester/test_helper'
|
6
|
+
require 'benchmark'
|
4
7
|
require 'rest-client'
|
5
8
|
require 'json'
|
9
|
+
require 'pry'
|
6
10
|
|
7
11
|
module ApiTester
|
12
|
+
# Class for defining and interacting with endpoints in a contract
|
8
13
|
class Endpoint
|
9
|
-
attr_accessor :name
|
10
|
-
attr_accessor :base_url
|
11
|
-
attr_accessor :path_params
|
12
|
-
attr_accessor :methods
|
13
|
-
attr_accessor :test_helper
|
14
|
-
attr_accessor :bad_request_response
|
15
|
-
attr_accessor :not_allowed_response
|
16
|
-
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
|
17
15
|
|
18
|
-
def initialize
|
19
|
-
self.
|
16
|
+
def initialize(name:, relative_url:)
|
17
|
+
self.relative_url = relative_url
|
20
18
|
self.name = name
|
21
19
|
self.methods = []
|
22
20
|
self.path_params = []
|
23
|
-
self.
|
24
|
-
self.
|
25
|
-
self.
|
26
|
-
self.
|
21
|
+
self.longest_time = { time: 0 }
|
22
|
+
self.test_helper = ApiTester::TestHelper.new ''
|
23
|
+
self.bad_request_response = ApiTester::Response.new status_code: 400
|
24
|
+
self.not_allowed_response = ApiTester::Response.new status_code: 415
|
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
|
27
31
|
end
|
28
32
|
|
29
33
|
def url
|
30
|
-
temp_url =
|
31
|
-
|
32
|
-
|
34
|
+
temp_url = relative_url.clone
|
35
|
+
path_params.each do |param|
|
36
|
+
value = test_helper.retrieve_param(param).to_s
|
37
|
+
temp_url = relative_url.sub "{#{param}}", value
|
33
38
|
end
|
34
39
|
temp_url
|
35
40
|
end
|
36
41
|
|
37
|
-
def default_call
|
38
|
-
|
39
|
-
method_defaults =
|
40
|
-
method_defaults[:url] =
|
42
|
+
def default_call(base_url)
|
43
|
+
test_helper.before
|
44
|
+
method_defaults = methods[0].default_request
|
45
|
+
method_defaults[:url] = "#{base_url}#{url}"
|
41
46
|
begin
|
42
|
-
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
|
43
56
|
rescue RestClient::ExceptionWithResponse => e
|
44
57
|
response = e.response
|
45
58
|
end
|
46
|
-
|
59
|
+
test_helper.after
|
47
60
|
response
|
48
61
|
end
|
49
62
|
|
50
|
-
def call method, payload
|
51
|
-
|
63
|
+
def call(base_url:, method:, query: '', payload: {}, headers: {})
|
64
|
+
test_helper.before
|
65
|
+
call_url = query ? "#{base_url}#{url}?#{query}" : "#{base_url}#{url}"
|
52
66
|
begin
|
53
|
-
response =
|
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
|
54
79
|
rescue RestClient::ExceptionWithResponse => e
|
55
80
|
response = e.response
|
56
81
|
end
|
57
|
-
|
82
|
+
test_helper.after
|
58
83
|
response
|
59
84
|
end
|
60
85
|
|
61
|
-
def add_method
|
62
|
-
|
86
|
+
def add_method(verb:, response:, request: Request.new)
|
87
|
+
methods << ApiTester::Method.new(verb: verb,
|
88
|
+
response: response,
|
89
|
+
request: request)
|
63
90
|
self
|
64
91
|
end
|
65
92
|
|
66
|
-
def add_path_param
|
67
|
-
|
93
|
+
def add_path_param(param)
|
94
|
+
path_params << param
|
68
95
|
self
|
69
96
|
end
|
70
97
|
|
71
98
|
def verbs
|
72
|
-
|
99
|
+
methods.map(&:verb)
|
73
100
|
end
|
74
101
|
end
|
75
102
|
end
|
@@ -1,46 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'api-tester/definition/fields/field'
|
2
4
|
|
3
5
|
module ApiTester
|
6
|
+
# Class used for defining array fields
|
4
7
|
class ArrayField < Field
|
5
8
|
attr_accessor :fields
|
6
9
|
|
7
|
-
def initialize
|
8
|
-
super
|
10
|
+
def initialize(name:, required: false, has_key: true)
|
11
|
+
super name: name, required: required, has_key: has_key
|
9
12
|
self.fields = []
|
10
13
|
end
|
11
14
|
|
12
|
-
def with_field(
|
13
|
-
|
15
|
+
def with_field(new_field)
|
16
|
+
fields << new_field
|
14
17
|
self
|
15
18
|
end
|
16
19
|
|
17
|
-
def
|
20
|
+
def subfields?
|
18
21
|
true
|
19
22
|
end
|
20
23
|
|
21
|
-
def
|
22
|
-
|
23
|
-
|
24
|
-
|
24
|
+
def type
|
25
|
+
'array'
|
26
|
+
end
|
27
|
+
|
28
|
+
def default
|
29
|
+
return [] if fields.size.zero?
|
25
30
|
|
26
|
-
obj =
|
27
|
-
|
28
|
-
obj[field.name] = field.
|
31
|
+
obj = {}
|
32
|
+
fields.each do |field|
|
33
|
+
obj[field.name] = field.default
|
29
34
|
end
|
30
35
|
[obj]
|
31
36
|
end
|
32
37
|
|
33
38
|
def negative_boundary_values
|
34
39
|
super +
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
40
|
+
[
|
41
|
+
'string',
|
42
|
+
123,
|
43
|
+
0,
|
44
|
+
1,
|
45
|
+
true,
|
46
|
+
false,
|
47
|
+
{}
|
48
|
+
]
|
44
49
|
end
|
45
50
|
end
|
46
51
|
end
|
@@ -1,19 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'api-tester/definition/fields/field'
|
2
4
|
|
3
5
|
module ApiTester
|
6
|
+
# Class for defining booleans in contract
|
4
7
|
class BooleanField < Field
|
5
|
-
def initialize(name,
|
6
|
-
super
|
8
|
+
def initialize(name:, default: true, required: false)
|
9
|
+
super name: name, default: default, required: required
|
7
10
|
end
|
8
11
|
|
9
12
|
def negative_boundary_values
|
10
13
|
super +
|
14
|
+
[
|
15
|
+
'string',
|
16
|
+
123,
|
17
|
+
0,
|
18
|
+
1,
|
19
|
+
{}
|
20
|
+
]
|
21
|
+
end
|
22
|
+
|
23
|
+
def good_cases
|
11
24
|
[
|
12
|
-
|
13
|
-
|
14
|
-
0,
|
15
|
-
1,
|
16
|
-
{}
|
25
|
+
true,
|
26
|
+
false
|
17
27
|
]
|
18
28
|
end
|
19
29
|
end
|
@@ -1,22 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'securerandom'
|
4
|
+
|
1
5
|
require 'api-tester/definition/fields/field'
|
2
6
|
|
3
7
|
module ApiTester
|
8
|
+
# Class for defining email fields in contract
|
4
9
|
class EmailField < Field
|
5
|
-
|
6
|
-
|
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
|
7
24
|
end
|
8
25
|
|
9
26
|
def negative_boundary_values
|
10
27
|
super +
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
28
|
+
[
|
29
|
+
'string',
|
30
|
+
123,
|
31
|
+
1,
|
32
|
+
0,
|
33
|
+
true,
|
34
|
+
false,
|
35
|
+
{}
|
36
|
+
]
|
20
37
|
end
|
21
38
|
end
|
22
39
|
end
|
@@ -1,14 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'api-tester/definition/fields/field'
|
2
4
|
|
3
5
|
module ApiTester
|
6
|
+
# Class for defining enumerators
|
4
7
|
class EnumField < Field
|
5
8
|
attr_accessor :acceptable_values
|
6
9
|
|
7
|
-
def initialize
|
8
|
-
if
|
9
|
-
super name,
|
10
|
+
def initialize(name:, acceptable_values:, default: nil, required: false)
|
11
|
+
if default
|
12
|
+
super name: name, default: default, required: required
|
10
13
|
else
|
11
|
-
super name, acceptable_values[0]
|
14
|
+
super name: name, default: acceptable_values[0], required: required
|
12
15
|
end
|
13
16
|
|
14
17
|
self.acceptable_values = acceptable_values
|
@@ -16,14 +19,18 @@ module ApiTester
|
|
16
19
|
|
17
20
|
def negative_boundary_values
|
18
21
|
super +
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
22
|
+
[
|
23
|
+
123,
|
24
|
+
0,
|
25
|
+
1,
|
26
|
+
true,
|
27
|
+
false,
|
28
|
+
{}
|
29
|
+
]
|
30
|
+
end
|
31
|
+
|
32
|
+
def good_cases
|
33
|
+
acceptable_values
|
27
34
|
end
|
28
35
|
end
|
29
36
|
end
|
@@ -1,49 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ApiTester
|
4
|
+
# Base class for field definitions
|
2
5
|
class Field
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
6
|
+
attr_accessor :name, :default, :required, :is_seen, :has_key
|
7
|
+
|
8
|
+
def initialize(name:, required: false, has_key: true, default: 'string')
|
9
|
+
self.name = name
|
10
|
+
self.default = default
|
11
|
+
self.required = required
|
12
|
+
self.is_seen = 0
|
13
|
+
self.has_key = has_key
|
14
|
+
end
|
15
|
+
|
16
|
+
def type
|
17
|
+
'field'
|
18
|
+
end
|
19
|
+
|
20
|
+
def is_required
|
21
|
+
self.required = true
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
def is_not_required
|
26
|
+
self.required = false
|
27
|
+
self
|
28
|
+
end
|
29
|
+
|
30
|
+
def subfields?
|
31
|
+
false
|
32
|
+
end
|
33
|
+
|
34
|
+
def fields
|
35
|
+
[]
|
36
|
+
end
|
37
|
+
|
38
|
+
def negative_boundary_values
|
39
|
+
cases = []
|
40
|
+
cases << nil if required
|
41
|
+
cases
|
42
|
+
end
|
43
|
+
|
44
|
+
def good_cases
|
45
|
+
[]
|
46
|
+
end
|
47
|
+
|
48
|
+
def seen
|
49
|
+
self.is_seen += 1
|
50
|
+
end
|
51
|
+
|
52
|
+
def display_class
|
53
|
+
self.class
|
54
|
+
end
|
48
55
|
end
|
49
56
|
end
|