fitting 3.0.2 → 4.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.ruby-version +1 -1
  4. data/CHANGELOG.md +16 -0
  5. data/README.md +327 -108
  6. data/fitting.gemspec +2 -2
  7. data/images/b1.png +0 -0
  8. data/images/b2.png +0 -0
  9. data/images/w1.png +0 -0
  10. data/images/w2.png +0 -0
  11. data/lib/fitting/action.rb +105 -0
  12. data/lib/fitting/cover/json_schema.rb +2 -2
  13. data/lib/fitting/cover/json_schema_one_of.rb +4 -2
  14. data/lib/fitting/debug.rb +47 -0
  15. data/lib/fitting/doc/action.rb +141 -0
  16. data/lib/fitting/doc/code.rb +53 -0
  17. data/lib/fitting/doc/combination_enum.rb +110 -0
  18. data/lib/fitting/doc/combination_one_of.rb +61 -0
  19. data/lib/fitting/doc/combination_optional.rb +54 -0
  20. data/lib/fitting/doc/combination_step.rb +48 -0
  21. data/lib/fitting/doc/content_type.rb +152 -0
  22. data/lib/fitting/doc/json_schema.rb +112 -0
  23. data/lib/fitting/doc/step.rb +102 -0
  24. data/lib/fitting/doc.rb +107 -0
  25. data/lib/fitting/host.rb +37 -0
  26. data/lib/fitting/log.rb +102 -0
  27. data/lib/fitting/nocov.rb +68 -0
  28. data/lib/fitting/prefix.rb +62 -0
  29. data/lib/fitting/railtie.rb +0 -1
  30. data/lib/fitting/records/spherical/request.rb +7 -4
  31. data/lib/fitting/records/spherical/response.rb +22 -16
  32. data/lib/fitting/records/tested/request.rb +6 -1
  33. data/lib/fitting/records/tested/response.rb +6 -1
  34. data/lib/fitting/rep/html.rb +32 -0
  35. data/lib/fitting/rep.rb +24 -0
  36. data/lib/fitting/report/action.rb +9 -15
  37. data/lib/fitting/report/actions.rb +22 -33
  38. data/lib/fitting/report/combination.rb +10 -6
  39. data/lib/fitting/report/combinations.rb +9 -29
  40. data/lib/fitting/report/prefix.rb +7 -24
  41. data/lib/fitting/report/prefixes.rb +11 -25
  42. data/lib/fitting/report/response.rb +12 -22
  43. data/lib/fitting/report/responses.rb +23 -27
  44. data/lib/fitting/report/tests.rb +4 -8
  45. data/lib/fitting/skip/action.rb +44 -0
  46. data/lib/fitting/skip/api.rb +29 -0
  47. data/lib/fitting/skip.rb +21 -0
  48. data/lib/fitting/version.rb +1 -1
  49. data/lib/fitting.rb +12 -28
  50. data/lib/tasks/fitting.rake +23 -84
  51. data/lib/templates/htmlcss/bootstrap-nightshade.min.css +12 -0
  52. data/lib/templates/htmlcss/bootstrap.min.js +7 -0
  53. data/lib/templates/htmlcss/darkmode.min.js +6 -0
  54. data/lib/templates/htmlcss/fitting.html +196 -0
  55. data/lib/templates/htmlcss/jquery-3.6.0.min.js +2 -0
  56. metadata +40 -39
  57. data/lib/fitting/configuration.rb +0 -17
  58. data/lib/fitting/records/spherical/requests.rb +0 -25
  59. data/lib/fitting/storage/responses.rb +0 -21
  60. data/lib/fitting/tests.rb +0 -31
  61. data/lib/tasks/fitting_outgoing.rake +0 -91
  62. data/lib/templates/bomboniere/.gitignore +0 -21
  63. data/lib/templates/bomboniere/.tool-versions +0 -1
  64. data/lib/templates/bomboniere/README.md +0 -19
  65. data/lib/templates/bomboniere/dist/css/app.aa2bcd8a.css +0 -1
  66. data/lib/templates/bomboniere/dist/css/chunk-vendors.ec5f6c3f.css +0 -1
  67. data/lib/templates/bomboniere/dist/favicon.ico +0 -0
  68. data/lib/templates/bomboniere/dist/index.html +0 -1
  69. data/lib/templates/bomboniere/dist/js/app.e5f1a5ec.js +0 -2
  70. data/lib/templates/bomboniere/dist/js/app.e5f1a5ec.js.map +0 -1
  71. data/lib/templates/bomboniere/dist/js/chunk-vendors.0f99b670.js +0 -13
  72. data/lib/templates/bomboniere/dist/js/chunk-vendors.0f99b670.js.map +0 -1
  73. data/lib/templates/bomboniere/package-lock.json +0 -9292
  74. data/lib/templates/bomboniere/package.json +0 -27
  75. data/lib/templates/bomboniere/public/favicon.ico +0 -0
  76. data/lib/templates/bomboniere/public/index.html +0 -17
  77. data/lib/templates/bomboniere/src/App.vue +0 -102
  78. data/lib/templates/bomboniere/src/assets/logo.png +0 -0
  79. data/lib/templates/bomboniere/src/components/HelloWorld.vue +0 -204
  80. data/lib/templates/bomboniere/src/main.js +0 -10
  81. data/lib/templates/bomboniere/src/router/index.js +0 -31
  82. data/lib/templates/bomboniere/src/views/About.vue +0 -5
  83. data/lib/templates/bomboniere/src/views/Action.vue +0 -173
  84. data/lib/templates/bomboniere/src/views/Home.vue +0 -17
  85. data/lib/templates/bomboniere/vue.config.js +0 -3
@@ -0,0 +1,105 @@
1
+ require 'fitting/host'
2
+ require 'fitting/prefix'
3
+ require 'fitting/report/prefixes'
4
+
5
+ module Fitting
6
+ class Action
7
+ class Skip < RuntimeError; end
8
+ class Empty < RuntimeError; end
9
+ class NotFound < RuntimeError
10
+ attr_reader :log
11
+
12
+ def initialize(msg, log)
13
+ @log = log
14
+ super(msg)
15
+ end
16
+ end
17
+
18
+ def initialize(action)
19
+ @action = action
20
+ end
21
+
22
+ def action
23
+ @action
24
+ end
25
+
26
+ def self.all
27
+ []
28
+ end
29
+
30
+ def self.find!(actions, log)
31
+ host = Fitting::Host.find!(log)
32
+ host.cover!
33
+
34
+ prefix = Fitting::Prefix.find(host: host, log: log)
35
+ prefix.cover!
36
+
37
+ new(prefix.actions.find!(log))
38
+ rescue Fitting::Report::Actions::Empty,
39
+ Fitting::Host::Skip,
40
+ Fitting::Prefix::Skip
41
+ raise Skip
42
+ rescue Fitting::Report::Combinations::Empty,
43
+ Fitting::Report::Combinations::NotFound
44
+ raise Skip
45
+ rescue Fitting::Host::NotFound,
46
+ Fitting::Prefix::NotFound,
47
+ Fitting::Report::Actions::NotFound,
48
+ Fitting::Report::Responses::NotFound => e
49
+ raise NotFound.new(e.message, log)
50
+ end
51
+
52
+ def cover!(log)
53
+ action.cover!
54
+
55
+ response = action.responses.find!(log)
56
+ response.cover!
57
+
58
+ combination = response.combinations.find!(log)
59
+ combination.cover!
60
+
61
+ print "\e[32m.\e[0m"
62
+ rescue Fitting::Report::Actions::Empty,
63
+ Fitting::Host::Skip,
64
+ Fitting::Prefix::Skip
65
+ rescue Fitting::Report::Combinations::Empty,
66
+ Fitting::Report::Combinations::NotFound
67
+ rescue Fitting::Host::NotFound,
68
+ Fitting::Prefix::NotFound,
69
+ Fitting::Report::Actions::NotFound,
70
+ Fitting::Report::Responses::NotFound => e
71
+ end
72
+
73
+ def self.report(actions)
74
+ all = 0
75
+ cover = 0
76
+
77
+ # prefixes.to_a.map do |prefix|
78
+ # all += 1
79
+ # break unless prefix.cover?
80
+ # cover += 1
81
+ # prefix.actions.to_a.map do |action|
82
+ # all += 1
83
+ # break unless action.cover?
84
+ # cover += 1
85
+ # action.responses.to_a.map do |response|
86
+ # all += 1
87
+ # break unless action.cover?
88
+ # cover += 1
89
+ # response.combinations.to_a.map do |combination|
90
+ # all += 1
91
+ # break unless combination.cover?
92
+ # cover += 1
93
+ # end
94
+ # end
95
+ # end
96
+ # end
97
+
98
+ puts
99
+ puts "Coverage #{(cover.to_f / all.to_f * 100).round(2)}%"
100
+ exit 1 unless false
101
+
102
+ exit 0
103
+ end
104
+ end
105
+ end
@@ -17,12 +17,12 @@ module Fitting
17
17
 
18
18
  def inception(json_schema, combinations)
19
19
  json_schema.each do |key, value|
20
- if (key == 'properties') && (json_schema['required'] != value.keys)
20
+ if (key == 'properties') && value && (json_schema['required'] != value.keys)
21
21
  schema = json_schema.dup
22
22
  one_of = schema.delete('required') || []
23
23
  schema['properties'].each_key do |property|
24
24
  next if one_of.include?(property)
25
-
25
+ next if property == 'type' || property == 'properties'
26
26
  combinations.push([schema.merge('required' => one_of + [property]), "required.#{property}"])
27
27
  end
28
28
  elsif value.is_a?(Hash)
@@ -10,7 +10,7 @@ module Fitting
10
10
 
11
11
  def combi
12
12
  inception(json_schema, combinations).each do |combination|
13
- combination[0] = json_schema.merge(combination[0])
13
+ combination[0] = combination[0]
14
14
  combination[1] = ['one_of', combination[1]]
15
15
  end
16
16
  end
@@ -21,7 +21,9 @@ module Fitting
21
21
  schema = json_schema.dup
22
22
  one_of = schema.delete('oneOf')
23
23
  one_of.each_index do |index|
24
- combinations.push([schema.merge('oneOf' => [one_of[index]]), "oneOf.#{index}"])
24
+ schema_new = json_schema.dup
25
+ schema_new.delete('oneOf')
26
+ combinations.push([schema_new.merge(one_of[index]), "oneOf.#{index}"])
25
27
  end
26
28
  elsif value.is_a?(Hash)
27
29
  com = inception(value, [])
@@ -0,0 +1,47 @@
1
+ module Fitting
2
+ class Debug
3
+ attr_accessor :host, :method, :path, :status, :content_type
4
+
5
+ def initialize(host, method, path, code, content_type)
6
+ @host = host
7
+ @method = method
8
+ @path = path
9
+ @status = code.to_s
10
+ @content_type = content_type
11
+ end
12
+
13
+ def self.save!(docs, yaml)
14
+ return unless yaml['Debug']
15
+ yaml['Debug'].map do |action|
16
+ debug = new(action['host'], action['method'], action['path'], action['code'], action['content-type'])
17
+ res = Fitting::Doc.debug(docs, debug)
18
+ index = res.next_steps.first.index_before
19
+ next_steps_first = res.next_steps.first
20
+ res_debug = report(index, next_steps_first, res.logs)
21
+ File.open('coverage/.fitting.debug.yml', 'w') { |file| file.write(YAML.dump(res_debug)) }
22
+ end
23
+ end
24
+
25
+ def self.report(index, next_steps_first, res_logs)
26
+ return {} if index.nil?
27
+ combinations = []
28
+ next_steps_first.next_steps.each do |next_step|
29
+ combinations.push(
30
+ next_step.debug_report(index)
31
+ )
32
+ end
33
+ res_debug = {
34
+ "json_schema" => next_steps_first.to_hash,
35
+ "jsons" => res_logs,
36
+ "valid_jsons" => next_steps_first.logs,
37
+ "index_before" => next_steps_first.index_before - index,
38
+ "index_medium" => next_steps_first.index_medium - index,
39
+ "index_after" => next_steps_first.index_after - index,
40
+ "res_before" => next_steps_first.res_before.map{|r| r ? r : "null"}[index..-1],
41
+ "res_medium" => next_steps_first.res_medium.map{|r| r ? r : "null"}[index..-1],
42
+ "res_after" => next_steps_first.res_after.map{|r| r ? r : "null"}[index..-1],
43
+ "combinations" => combinations
44
+ }
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,141 @@
1
+ require 'fitting/doc/code'
2
+ require 'fitting/debug'
3
+
4
+ module Fitting
5
+ class Doc
6
+ class Action
7
+ attr_accessor :host, :prefix, :path, :method, :responses
8
+
9
+ class NotFound < RuntimeError; end
10
+
11
+ def initialize(host, prefix, method, path, responses)
12
+ @host = host
13
+ @prefix = prefix
14
+ @method = method
15
+ @path = path
16
+ @path.slice!(prefix)
17
+ @responses = []
18
+ responses.group_by { |response| response['status'] }.each do |code, value|
19
+ @responses.push(Code.new(code, value))
20
+ end
21
+ @key = "#{method} #{host}#{prefix}#{path}"
22
+
23
+ @host_cover = 0
24
+ @prefix_cover = 0
25
+ @path_cover = 0
26
+ @method_cover = 0
27
+ end
28
+
29
+ def to_hash_lock
30
+ res = YAML.dump(
31
+ {
32
+ host => {
33
+ prefix => {
34
+ path => {
35
+ method => @responses.inject({}) { |sum, response| sum.merge!(response) }
36
+ }
37
+ }
38
+ }
39
+ }
40
+ ).split("\n")
41
+ { @key => res[1..-1] }
42
+ end
43
+
44
+ def to_hash
45
+ res = [
46
+ @host_cover,
47
+ @prefix_cover,
48
+ @path_cover,
49
+ @method_cover
50
+ ]
51
+ (to_hash_lock[@key].size - 4).times { res.push(nil) }
52
+
53
+ if @method_cover != nil && @method_cover != 0
54
+ code_index = 4
55
+ @responses.each do |code|
56
+ res, code_index = code.report(res, code_index)
57
+ end
58
+ end
59
+
60
+ { @key => res }
61
+ end
62
+
63
+ def cover!(log)
64
+ unless log.host == host
65
+ return
66
+ end
67
+ @host_cover += 1
68
+
69
+ unless prefix.size == 0 || log.path[0..prefix.size - 1] == prefix
70
+ return
71
+ end
72
+ @prefix_cover += 1
73
+
74
+ unless path_match(log.path)
75
+ return
76
+ end
77
+ @path_cover += 1
78
+
79
+ unless log.method == method
80
+ return
81
+ end
82
+ @method_cover += 1
83
+
84
+ @responses.each { |response| response.cover!(log) }
85
+
86
+ true
87
+ rescue Fitting::Doc::Code::NotFound => e
88
+ raise NotFound.new "\n\ntype: #{@type}\n"\
89
+ "host: #{@host}\n" \
90
+ "prefix: #{@prefix}\n" \
91
+ "method: #{@method}\n" \
92
+ "path: #{@path}\n" \
93
+ "#{e.message}"
94
+ end
95
+
96
+ def debug(debug)
97
+ unless debug.host == host
98
+ return nil
99
+ end
100
+
101
+ unless prefix.size == 0 || debug.path[0..prefix.size - 1] == prefix
102
+ return nil
103
+ end
104
+
105
+ unless path_match(debug.path)
106
+ return nil
107
+ end
108
+
109
+ unless debug.method == method
110
+ return nil
111
+ end
112
+
113
+ @responses.each do |response|
114
+ res = response.debug(debug)
115
+ return res if res
116
+ end
117
+ nil
118
+ end
119
+
120
+ def nocover!
121
+ @host_cover = nil
122
+ @prefix_cover = nil
123
+ @path_cover = nil
124
+ @method_cover = nil
125
+ end
126
+
127
+ def path_match(find_path)
128
+ regexp =~ find_path
129
+ end
130
+
131
+ def regexp
132
+ return @regexp if @regexp
133
+
134
+ str = Regexp.escape(@prefix + path)
135
+ str = str.gsub(/\\{\w+\\}/, '[^&=\/]+')
136
+ str = "\\A#{str}\\z"
137
+ @regexp = Regexp.new(str)
138
+ end
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,53 @@
1
+ require 'fitting/doc/step'
2
+ require 'fitting/doc/content_type'
3
+
4
+ module Fitting
5
+ class Doc
6
+ class Code < Step
7
+ class NotFound < RuntimeError; end
8
+
9
+ def initialize(code, value)
10
+ @step_cover_size = 0
11
+ @step_key = code
12
+ @next_steps = []
13
+ value.group_by { |val| val['content-type'] }.each do |content_type, subvalue|
14
+ break if content_type == nil
15
+ @next_steps.push(ContentType.new(content_type, subvalue))
16
+ end
17
+ end
18
+
19
+ def to_hash
20
+ if @next_steps.size == 1 && @next_steps[0].step_key == nil
21
+ {
22
+ @step_key => {}
23
+ }
24
+ else
25
+ {
26
+ @step_key => @next_steps.inject({}) { |sum, value| sum.merge!(value) }
27
+ }
28
+ end
29
+ end
30
+
31
+ def cover!(log)
32
+ if @step_key == log.status
33
+ @step_cover_size += 1
34
+ @next_steps.each { |content_type| content_type.cover!(log) }
35
+ end
36
+ rescue Fitting::Doc::ContentType::NotFound => e
37
+ raise NotFound.new "code: #{@step_key}\n\n"\
38
+ "#{e.message}"
39
+ end
40
+
41
+ def debug(debug)
42
+ if @step_key == debug.status
43
+ @next_steps.each do |content_type|
44
+ res = content_type.debug(debug)
45
+ return res if res
46
+ end
47
+ nil
48
+ end
49
+ nil
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,110 @@
1
+ require 'fitting/doc/combination_step'
2
+ require 'fitting/cover/json_schema_enum'
3
+
4
+ module Fitting
5
+ class Doc
6
+ class CombinationEnum < CombinationStep
7
+ def cover!(log)
8
+ error = JSON::Validator.fully_validate(@json_schema, log.body)
9
+ if error == []
10
+ @step_cover_size += 1
11
+ @logs.push(log.body)
12
+ nil
13
+ else
14
+ bodies = custom_body(log.body)
15
+ errors = []
16
+ bodies.each do |body|
17
+ error = JSON::Validator.fully_validate(@json_schema, body)
18
+ if error == []
19
+ @step_cover_size += 1
20
+ @logs.push(body)
21
+ nil
22
+ else
23
+ errors.push(
24
+ {
25
+ combination: @step_key,
26
+ type: @type,
27
+ json_schema: @json_schema,
28
+ error: error,
29
+ body: body
30
+ })
31
+ end
32
+ end
33
+
34
+ if errors.size == bodies.size
35
+ errors
36
+ else
37
+ nil
38
+ end
39
+ end
40
+ end
41
+
42
+ def find_keys
43
+ new_keys = []
44
+ if YAML.dump(@json_schema).include?("array")
45
+ res = @json_schema
46
+ @step_key.split('.').each do |key|
47
+ if res[key].class == Hash && res[key] != nil
48
+ if res[key].class == Hash && res[key]['type'] == 'array'
49
+ new_keys.push(key)
50
+ return new_keys
51
+ else
52
+ if key != 'properties'
53
+ new_keys.push(key)
54
+ end
55
+ res = res[key]
56
+ end
57
+ end
58
+ end
59
+ end
60
+ []
61
+ end
62
+
63
+ def custom_body(body)
64
+ bodies = []
65
+ keys = find_keys
66
+ if keys != []
67
+ if keys.size == 1
68
+ if body[keys[0]].size == 1
69
+ return body
70
+ else
71
+ body[keys[0]].each do |bb|
72
+ new_body = body.dup
73
+ new_body.delete(keys[0])
74
+ bodies.push(new_body.merge(keys[0] => bb))
75
+ end
76
+ end
77
+ end
78
+ return bodies
79
+ end
80
+ [body]
81
+ end
82
+
83
+ def report(res, index)
84
+ @index_before = index
85
+ @res_before = [] + res
86
+ @index_medium = index
87
+ @res_medium = [] + res
88
+
89
+ combinations = @step_key.split('.')
90
+ elements = YAML.dump(@source_json_schema).split("\n")[1..-1]
91
+
92
+ res_index = 0
93
+ element_index = 0
94
+ elements.each_with_index do |element, i|
95
+ if element.include?(combinations[element_index])
96
+ element_index += 1
97
+ end
98
+ if combinations.size == element_index
99
+ res_index = i
100
+ break
101
+ end
102
+ end
103
+ res[res_index + index] = @step_cover_size
104
+ @index_after = res_index + index
105
+ @res_after = [] + res
106
+ [res, index]
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,61 @@
1
+ require 'fitting/doc/combination_step'
2
+ require 'fitting/cover/json_schema_enum'
3
+ require 'fitting/doc/combination_enum'
4
+ require 'fitting/cover/json_schema'
5
+ require 'fitting/doc/combination_optional'
6
+
7
+ module Fitting
8
+ class Doc
9
+ class CombinationOneOf < CombinationStep
10
+ def initialize_combinations(combination, json_schema)
11
+ combinations = Fitting::Cover::JSONSchemaEnum.new(@json_schema).combi
12
+ if combinations.size > 1
13
+ combinations.each do |comb|
14
+ @next_steps.push(CombinationEnum.new(comb[0], "#{comb[1][0]}", "#{comb[1][1]}", json_schema))
15
+ end
16
+ end
17
+
18
+ combinations = Fitting::Cover::JSONSchema.new(@json_schema).combi
19
+ combinations.each do |comb|
20
+ @next_steps.push(CombinationOptional.new(comb[0], "#{type}.#{comb[1][0]}", "#{combination}.#{comb[1][1]}", json_schema))
21
+ end
22
+ end
23
+
24
+ def cover!(log)
25
+ if JSON::Validator.fully_validate(@json_schema, log.body) == []
26
+ @step_cover_size += 1
27
+ @logs.push(log.body)
28
+ errors = @next_steps.inject([]) do |sum, combination|
29
+ sum.push(combination.cover!(log))
30
+ end.flatten.compact
31
+
32
+ return if @next_steps.size == 0
33
+ return unless @next_steps.size == errors.size
34
+
35
+ error_message = ""
36
+ errors.each do |error|
37
+ error_message += "combination: #{error[:combination]}\n"\
38
+ "combination type: #{error[:type]}\n"\
39
+ "combination json-schema: #{::JSON.pretty_generate(error[:json_schema])}\n"\
40
+ "combination error #{::JSON.pretty_generate(error[:error])}\n"\
41
+ "combination body #{::JSON.pretty_generate(error[:body])}\n"
42
+ end
43
+
44
+ # raise NotFound.new "#{error_message}\n"\
45
+ # "source body: #{::JSON.pretty_generate(log.body)}"
46
+ end
47
+ end
48
+
49
+ def mark_range(index, res)
50
+ res[index + 1] = @step_cover_size
51
+ if @json_schema && @json_schema["required"]
52
+ mark_required(index + 1, res, @json_schema)
53
+ end
54
+ end
55
+
56
+ def index_offset
57
+ YAML.dump(@json_schema['properties']).split("\n").size + YAML.dump(@json_schema['required']).split("\n").size
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,54 @@
1
+ require 'fitting/doc/combination_step'
2
+ require 'fitting/cover/json_schema_enum'
3
+
4
+ module Fitting
5
+ class Doc
6
+ class CombinationOptional < CombinationStep
7
+ def cover!(log)
8
+ error = JSON::Validator.fully_validate(@json_schema, log.body)
9
+ if error == []
10
+ @step_cover_size += 1
11
+ @logs.push(log.body)
12
+ nil
13
+ end
14
+ end
15
+
16
+ def report(res, index)
17
+ @index_before = index
18
+ @res_before = [] + res
19
+ @index_medium = index
20
+ @res_medium = [] + res
21
+
22
+ combinations = @step_key.split('.')
23
+ elements = YAML.dump(@source_json_schema).split("\n")[1..-1]
24
+ res_index = 0
25
+ elements.each_with_index do |element, i|
26
+ if element.include?(combinations[-1])
27
+ res_index = i
28
+ break
29
+ end
30
+ end
31
+
32
+ res[res_index + index] = @step_cover_size
33
+ res[res_index + index + 1] = @step_cover_size
34
+
35
+ if @source_json_schema["properties"][combinations[-1]] && @source_json_schema["properties"][combinations[-1]].class == Hash && @source_json_schema["properties"][combinations[-1]]["type"] == "array"
36
+ res[res_index + index + 2] = @step_cover_size
37
+ res[res_index + index + 3] = @step_cover_size
38
+ res[res_index + index + 4] = @step_cover_size
39
+
40
+ schema = @source_json_schema["properties"][combinations[-1]]['items']
41
+ mark_required(res_index + index + 4, res, schema)
42
+ elsif @source_json_schema["properties"][combinations[-1]] && @source_json_schema["properties"][combinations[-1]].class == Hash && @source_json_schema["properties"][combinations[-1]]["type"] == "object"
43
+ schema = @source_json_schema["properties"][combinations[-1]]
44
+ res[res_index + index + 2] = @step_cover_size
45
+ mark_required(res_index + index + 2, res, schema)
46
+ end
47
+
48
+ @index_after = res_index + index + 4
49
+ @res_after = [] + res
50
+ [res, index]
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,48 @@
1
+ require 'fitting/doc/step'
2
+
3
+ module Fitting
4
+ class Doc
5
+ class CombinationStep < Step
6
+ class NotFound < RuntimeError; end
7
+
8
+ attr_accessor :json_schema, :type, :logs
9
+
10
+ def initialize(json_schema, type, combination, source_json_schema)
11
+ @logs = []
12
+ @step_cover_size = 0
13
+ @json_schema = json_schema
14
+ @next_steps = []
15
+ @type = type
16
+ @step_key = combination
17
+ @source_json_schema = source_json_schema
18
+ initialize_combinations(combination, json_schema)
19
+ end
20
+
21
+ def initialize_combinations(combination, json_schema)
22
+ end
23
+
24
+ def debug_report(index)
25
+ combinations = []
26
+ @next_steps.each do |next_step|
27
+ combinations.push(
28
+ next_step.debug_report(index)
29
+ )
30
+ end
31
+ return {} if index.nil? || index_before.nil?
32
+ {
33
+ "combination type" => @type,
34
+ "combination" => @step_key,
35
+ "json_schema" => @json_schema,
36
+ "valid_jsons" => @logs,
37
+ "index_before" => @index_before - index,
38
+ "index_medium" => @index_medium - index,
39
+ "index_after" => @index_after - index,
40
+ "res_before" => @res_before.map { |r| r ? r : "null" }[index..-1],
41
+ "res_medium" => @res_medium.map { |r| r ? r : "null" }[index..-1],
42
+ "res_after" => @res_after.map { |r| r ? r : "null" }[index..-1],
43
+ "combinations" => combinations
44
+ }
45
+ end
46
+ end
47
+ end
48
+ end