fitting 3.0.2 → 4.0.1

Sign up to get free protection for your applications and to get access to all the features.
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