fitting 3.0.2 → 4.0.0

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 +9 -0
  5. data/README.md +272 -109
  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 +116 -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 +64 -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,116 @@
1
+ require 'fitting/doc/step'
2
+ require 'fitting/doc/combination_one_of'
3
+ require 'fitting/cover/json_schema_one_of'
4
+ require 'fitting/doc/combination_enum'
5
+ require 'fitting/cover/json_schema_enum'
6
+ require 'fitting/cover/json_schema'
7
+ require 'fitting/doc/combination_optional'
8
+ require 'json'
9
+ require 'json-schema'
10
+
11
+ module Fitting
12
+ class Doc
13
+ class JsonSchema < Step
14
+ class NotFound < RuntimeError; end
15
+
16
+ def initialize(json_schema, super_schema)
17
+ @super_schema = super_schema
18
+ @logs = []
19
+ @step_cover_size = 0
20
+ @step_key = json_schema
21
+ @next_steps = []
22
+ @oneOf = false
23
+ Fitting::Cover::JSONSchemaOneOf.new(json_schema).combi.each do |combination|
24
+ @oneOf = true
25
+ @next_steps.push(CombinationOneOf.new(combination[0], combination[1][0], combination[1][1], json_schema))
26
+ end
27
+ combinations = Fitting::Cover::JSONSchemaEnum.new(json_schema).combi
28
+ if combinations.size > 1
29
+ combinations.each do |comb|
30
+ @next_steps.push(CombinationEnum.new(comb[0], comb[1][0], comb[1][1], json_schema))
31
+ end
32
+ end
33
+
34
+ if json_schema['type'] != 'array'
35
+ combinations = Fitting::Cover::JSONSchema.new(json_schema).combi
36
+ combinations.each do |comb|
37
+ @next_steps.push(CombinationOptional.new(comb[0], comb[1][0], comb[1][1], json_schema))
38
+ end
39
+ end
40
+ end
41
+
42
+ def cover!(log)
43
+ if @super_schema
44
+ @step_cover_size += 1
45
+ @logs.push(log.body)
46
+ @next_steps.each { |combination| combination.cover!(log) }
47
+ elsif JSON::Validator.fully_validate(@step_key, log.body) == []
48
+ @step_cover_size += 1
49
+ @logs.push(log.body)
50
+ @next_steps.each { |combination| combination.cover!(log) }
51
+ else
52
+ raise Fitting::Doc::JsonSchema::NotFound.new "json-schema: #{::JSON.pretty_generate(@step_key)}\n\n"\
53
+ "body: #{::JSON.pretty_generate(log.body)}\n\n"\
54
+ "error #{::JSON.pretty_generate(JSON::Validator.fully_validate(@step_key, log.body))}"
55
+ end
56
+ rescue JSON::Schema::SchemaError => e
57
+ raise Fitting::Doc::JsonSchema::NotFound.new "json-schema: #{::JSON.pretty_generate(@step_key)}\n\n"\
58
+ "body: #{::JSON.pretty_generate(log.body)}\n\n"\
59
+ "error #{e.message}"
60
+ rescue Fitting::Doc::CombinationOneOf::NotFound => e
61
+ raise Fitting::Doc::JsonSchema::NotFound.new "#{e.message}\n\nsource json-schema: #{::JSON.pretty_generate(@step_key)}\n\n"
62
+ end
63
+
64
+ def logs
65
+ @logs
66
+ end
67
+
68
+ def mark_range(index, res)
69
+ start_index = index
70
+ end_index = start_index + 2
71
+
72
+ (start_index..end_index).each do |i|
73
+ res[i] = @step_cover_size
74
+ end
75
+
76
+ if @step_key["required"]
77
+ mark_required(end_index, res, @step_key)
78
+ end
79
+ end_index
80
+ end
81
+
82
+ def nocover!
83
+ @step_cover_size = nil
84
+ end
85
+
86
+ def to_hash
87
+ @step_key
88
+ end
89
+
90
+ def report(res, index)
91
+ @index_before = index
92
+ @res_before = [] + res
93
+
94
+ index = mark_range(index, res)
95
+ @index_medium = index
96
+ @res_medium = [] + res
97
+
98
+ if @next_steps != []
99
+ new_index = index
100
+ @next_steps.each do |next_step|
101
+ if @oneOf
102
+ res, new_index = next_step.report(res, new_index)
103
+ else
104
+ res, new_index = next_step.report(res, @index_before)
105
+ end
106
+ end
107
+ end
108
+
109
+ index += index_offset
110
+ @index_after = index
111
+ @res_after = [] + res
112
+ [res, index]
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,102 @@
1
+ module Fitting
2
+ class Doc
3
+ class Step
4
+ attr_accessor :step_cover_size, :step_key, :next_steps, :index_before, :index_medium, :index_after, :res_before, :res_medium, :res_after
5
+
6
+ def to_hash
7
+ {
8
+ @step_key => @next_steps.inject({}) { |sum, value| sum.merge!(value) }
9
+ }
10
+ end
11
+
12
+ def nocover!
13
+ @step_cover_size = nil
14
+ @next_steps.each do |next_step|
15
+ next_step.nocover!
16
+ end
17
+ end
18
+
19
+ def report(res, index)
20
+ @index_before = index
21
+ @res_before = [] + res
22
+
23
+ mark_range(index, res)
24
+ @index_medium = index
25
+ @res_medium = [] + res
26
+
27
+ if @next_steps != []
28
+ new_index = index + new_index_offset
29
+ @next_steps.each do |next_step|
30
+ if self.class == Fitting::Doc::CombinationOneOf
31
+ res, _new_index = next_step.report(res, new_index - 2)
32
+ else
33
+ res, new_index = next_step.report(res, new_index)
34
+ end
35
+ end
36
+ end
37
+
38
+ index += index_offset
39
+ @index_after = index
40
+ @res_after = [] + res
41
+ [res, index]
42
+ end
43
+
44
+ def mark_range(index, res)
45
+ res[index] = @step_cover_size
46
+ if @json_schema && @json_schema["required"]
47
+ mark_required(index, res, @json_schema)
48
+ end
49
+ end
50
+
51
+ def new_index_offset
52
+ 1
53
+ end
54
+
55
+ def index_offset
56
+ YAML.dump(@next_steps.inject({}) { |sum, value| sum.merge!(value) }).split("\n").size
57
+ end
58
+
59
+ def mark_required(index, res, schema)
60
+ start_index = index + YAML.dump(schema["properties"]).split("\n").size
61
+ end_index = start_index + YAML.dump(schema["required"]).split("\n").size - 1
62
+ (start_index..end_index).each do |i|
63
+ res[i] = @step_cover_size
64
+ end
65
+
66
+ return if schema["required"].nil?
67
+
68
+ schema["required"].each do |required|
69
+ required_index = YAML.dump(schema["properties"]).split("\n").index { |key| key == "#{required}:" }
70
+ break if required_index.nil?
71
+ res[index + required_index] = @step_cover_size
72
+ res[index + required_index + 1] = @step_cover_size
73
+ res[index + required_index + 2] = @step_cover_size if schema["properties"][required]["type"] == "string" && schema["properties"][required]["enum"]
74
+ if schema["properties"][required]["type"] == "object"
75
+ res[index + required_index + 2] = @step_cover_size
76
+ new_index = index + required_index + 2
77
+ mark_required(new_index, res, schema["properties"][required])
78
+ elsif schema["properties"][required]["type"] == "string" && schema["properties"][required]["enum"]
79
+ new_index = index + required_index + 2
80
+ mark_enum(new_index, res, schema["properties"][required])
81
+ end
82
+ end
83
+ end
84
+
85
+ def mark_enum(index, res, schema)
86
+ if schema["enum"].size == 1
87
+ res[index] = @step_cover_size
88
+ res[index + 1] = @step_cover_size
89
+ end
90
+ end
91
+
92
+ def valid?
93
+ end
94
+
95
+ def range
96
+ end
97
+
98
+ def next
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,107 @@
1
+ require 'fitting/doc/action'
2
+ require 'tomograph'
3
+
4
+ module Fitting
5
+ class Doc
6
+ class NotFound < RuntimeError; end
7
+
8
+ def self.all
9
+ apis = YAML.safe_load(File.read('.fitting.yml'))['APIs']
10
+ return [] unless apis
11
+ apis.map do |api|
12
+ if api['type'] == 'openapi2'
13
+ Tomograph::Tomogram.new(prefix: api['prefix'] || '', openapi2_json_path: api['path']).to_a.map do |action|
14
+ Fitting::Doc::Action.new(
15
+ api['host'],
16
+ api['prefix'] || '',
17
+ action.to_hash['method'],
18
+ action.to_hash['path'].path,
19
+ action.responses
20
+ )
21
+ end
22
+ elsif api['type'] == 'openapi3'
23
+ Tomograph::Tomogram.new(prefix: api['prefix'] || '', openapi3_yaml_path: api['path']).to_a.map do |action|
24
+ Fitting::Doc::Action.new(
25
+ api['host'],
26
+ api['prefix'] || '',
27
+ action.to_hash['method'],
28
+ action.to_hash['path'].path,
29
+ action.responses
30
+ )
31
+ end
32
+ elsif api['type'] == 'drafter'
33
+ Tomograph::Tomogram.new(prefix: api['prefix'] || '', drafter_yaml_path: api['path']).to_a.map do |action|
34
+ Fitting::Doc::Action.new(
35
+ api['host'],
36
+ api['prefix'] || '',
37
+ action.to_hash['method'],
38
+ action.to_hash['path'].path,
39
+ action.responses
40
+ )
41
+ end
42
+ elsif api['type'] == 'crafter'
43
+ Tomograph::Tomogram.new(prefix: api['prefix'] || '', crafter_yaml_path: api['path']).to_a.map do |action|
44
+ Fitting::Doc::Action.new(
45
+ api['host'],
46
+ api['prefix'] || '',
47
+ action.to_hash['method'],
48
+ action.to_hash['path'].path,
49
+ action.responses
50
+ )
51
+ end
52
+ elsif api['type'] == 'tomogram'
53
+ Tomograph::Tomogram.new(prefix: api['prefix'] || '', tomogram_json_path: api['path']).to_a.map do |action|
54
+ Fitting::Doc::Action.new(
55
+ api['host'],
56
+ api['prefix'] || '',
57
+ action.to_hash['method'],
58
+ action.to_hash['path'].path,
59
+ action.responses
60
+ )
61
+ end
62
+ end
63
+ end.flatten
64
+ end
65
+
66
+ def self.cover!(docs, log)
67
+ docs.each do |doc|
68
+ return if doc.cover!(log)
69
+ end
70
+ raise NotFound.new "log: #{log.method} #{log.host} #{log.url} #{log.status}"
71
+ rescue Fitting::Doc::Action::NotFound => e
72
+ raise NotFound.new "log error: #{e.message}"
73
+ end
74
+
75
+ def self.debug(docs, debug)
76
+ docs.each do |doc|
77
+ res = doc.debug(debug)
78
+ return res if res
79
+ end
80
+ raise NotFound
81
+ end
82
+
83
+ def self.report(docs)
84
+ all = 0
85
+ cov = 0
86
+ docs.each do |provid|
87
+ provid.to_hash.values.first.each do |prov|
88
+ if prov == nil
89
+ break
90
+ elsif prov == 0
91
+ all += 1
92
+ elsif prov > 0
93
+ all += 1
94
+ cov += 1
95
+ end
96
+ end
97
+ end
98
+ res = (cov.to_f / all.to_f * 100).round(2)
99
+ puts "Coverage: #{res}%"
100
+ if res == 100.00
101
+ exit 0
102
+ else
103
+ exit 1
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,37 @@
1
+ module Fitting
2
+ class Host
3
+ class Skip < RuntimeError; end
4
+ class NotFound < RuntimeError
5
+ attr_reader :log
6
+ def initialize(msg, log)
7
+ @log = log
8
+ super(msg)
9
+ end
10
+ end
11
+
12
+ def initialize(host, skip)
13
+ @host = host
14
+ @skip = skip
15
+ @cover = false
16
+ end
17
+
18
+ def self.find!(log)
19
+ yaml = YAML.safe_load(File.read('.fitting.yml'))
20
+ yaml['hosts']&.map do |host|
21
+ if log.host == host.first.first
22
+ return new(host.first.first, host.first.last)
23
+ end
24
+ end
25
+ raise NotFound.new(log.host, log)
26
+ end
27
+
28
+ def cover!
29
+ @cover = true
30
+ raise Skip if @skip == 'skip'
31
+ end
32
+
33
+ def to_s
34
+ @host
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,102 @@
1
+ module Fitting
2
+ class Log
3
+ def initialize(log, type)
4
+ @log = log
5
+ @type = type
6
+ @error = nil
7
+ @skip = false
8
+ end
9
+
10
+ def self.all
11
+ logs = []
12
+ Dir["log/fitting*.log"].each do |file_path|
13
+ testlog = File.read(file_path)
14
+ testlog.split("\n").select { |f| f.include?('incoming request ') }.each do |test|
15
+ logs.push(new(JSON.load(test.split('incoming request ')[1]), 'incoming'))
16
+ end
17
+ testlog.split("\n").select { |f| f.include?('outgoing request ') }.each do |test|
18
+ logs.push(new(JSON.load(test.split('outgoing request ')[1]), 'outgoing'))
19
+ end
20
+ end
21
+ logs.sort { |a, b| b.path <=> a.path }
22
+ end
23
+
24
+ def url
25
+ "#{host}#{path}"
26
+ end
27
+
28
+ def path
29
+ @log['path']
30
+ end
31
+
32
+ def method
33
+ @log['method']
34
+ end
35
+
36
+ def status
37
+ @log['response']['status'].to_s
38
+ end
39
+
40
+ def body
41
+ @log['response']['body']
42
+ end
43
+
44
+ def content_type
45
+ @log['response']['content_type']
46
+ end
47
+
48
+ def host
49
+ @log['host'] || 'www.example.com'
50
+ end
51
+
52
+ def type
53
+ @type
54
+ end
55
+
56
+ def access!
57
+ print "\e[32m.\e[0m"
58
+ end
59
+
60
+ def pending!
61
+ @skip = true
62
+ print "\e[33m*\e[0m"
63
+ end
64
+
65
+ def failure!(error)
66
+ @error = error
67
+ print "\e[31mF\e[0m"
68
+ end
69
+
70
+ def error
71
+ @error
72
+ end
73
+
74
+ def failure?
75
+ @error.present?
76
+ end
77
+
78
+ def self.failure(logs)
79
+ logs.select do |log|
80
+ log.failure?
81
+ end
82
+ end
83
+
84
+ def pending?
85
+ @skip
86
+ end
87
+
88
+ def self.pending(logs)
89
+ logs.select do |log|
90
+ log.pending?
91
+ end
92
+ end
93
+
94
+ def self.report(logs)
95
+ puts "\n\n"
96
+ Fitting::Log.failure(logs).each_with_index do |log, index|
97
+ puts "\e[31m #{index + 1}) #{log.error.class} #{log.error.message}\n\n\e[0m"
98
+ end
99
+ print "\e[31m#{logs.size} examples, #{Fitting::Log.failure(logs).size} failure, #{Fitting::Log.pending(logs).size} pending\e[0m\n"
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,64 @@
1
+ module Fitting
2
+ class NoCov
3
+ class NotFound < RuntimeError; end
4
+
5
+ def initialize(host, method, path, code, content_type, combination, combination_next)
6
+ @host = host
7
+ @method = method
8
+ @path = path
9
+ @code = code
10
+ @content_type = content_type
11
+ @combination = combination
12
+ @combination_next = combination_next
13
+ end
14
+
15
+ def self.all(yaml)
16
+ return [] unless yaml['NoCov']
17
+ yaml['NoCov'].map do |action|
18
+ new(action['host'], action['method'], action['path'], action['code'], action['content-type'], action['combination'], action['combination_next'])
19
+ end
20
+ end
21
+
22
+ def find(docs)
23
+ res = docs.find do |action|
24
+ action.host == @host && action.method == @method && action.path_match(@path)
25
+ end
26
+
27
+ if @code == nil
28
+ return res if res.present?
29
+ raise NotFound.new("host: #{@host}, method: #{@method}, path: #{@path}")
30
+ end
31
+
32
+ res_code = res.responses.find { |response| response.step_key == @code.to_s }
33
+
34
+ if @content_type == nil
35
+ return res_code if res_code.present?
36
+ raise NotFound.new("host: #{@host}, method: #{@method}, path: #{@path}, code: #{@code}")
37
+ end
38
+
39
+ res_content_type = res_code.next_steps.find { |content_type| content_type.step_key == @content_type.to_s }
40
+
41
+ if @combination == nil
42
+ return res_content_type if res_content_type.present?
43
+ raise NotFound.new("host: #{@host}, method: #{@method}, path: #{@path}, code: #{@code}, content-type: #{@content_type}")
44
+ end
45
+
46
+ res_json_schema = res_content_type.next_steps[0]
47
+ res_combination = res_json_schema.next_steps.find do |combination|
48
+ combination.step_key == @combination.to_s
49
+ end
50
+
51
+ if @combination_next == nil
52
+ return res_combination if res_combination
53
+ raise NotFound.new("host: #{@host}, method: #{@method}, path: #{@path}, code: #{@code}, content-type: #{@content_type}, combination: #{@combination}")
54
+ end
55
+
56
+ res_combination_next = res_combination.next_steps.find do |combination_next|
57
+ combination_next.step_key == @combination_next.to_s
58
+ end
59
+
60
+ return res_combination_next if res_combination_next
61
+ raise NotFound.new("host: #{@host}, method: #{@method}, path: #{@path}, code: #{@code}, content-type: #{@content_type}, combination: #{@combination}, combination_next: #{@combination_next}")
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,62 @@
1
+ require 'fitting/report/actions'
2
+
3
+ module Fitting
4
+ class Prefix
5
+ KEYS = {
6
+ 'openapi2' => :openapi2_json_path,
7
+ 'openapi3' => :openapi3_yaml_path,
8
+ 'drafter' => :drafter_yaml_path,
9
+ 'crafter' => :crafter_yaml_path,
10
+ 'tomogram' => :tomogram_json_path
11
+ }.freeze
12
+
13
+ attr_reader :name, :actions
14
+
15
+ def initialize(name, schema_paths, type, skip = false)
16
+ @prefix = name
17
+ @cover = false
18
+
19
+ @actions = Fitting::Report::Actions.new([])
20
+ raise Skip if skip
21
+
22
+ schema_paths.each do |path|
23
+ tomogram = Tomograph::Tomogram.new(prefix: name, KEYS[type] => path)
24
+
25
+ @actions.push(Fitting::Report::Actions.new(tomogram))
26
+ end
27
+ end
28
+
29
+ class Skip < RuntimeError; end
30
+
31
+ class NotFound < RuntimeError
32
+ attr_reader :log
33
+
34
+ def initialize(msg, log)
35
+ @log = log
36
+ super(msg)
37
+ end
38
+ end
39
+
40
+ def self.find(host:, log:)
41
+ yaml = YAML.safe_load(File.read('.fitting.yml'))
42
+
43
+ prefixes = yaml['hosts'].find{|h| h.first.first == host.to_s}.first.last['prefixes']
44
+ raise NotFound.new("host: #{log.host}, path: #{log.path}", log) unless prefixes
45
+
46
+ prefix = prefixes.find do |prefix|
47
+ prefix['name'].nil? || log.path[0..prefix['name'].size - 1] == prefix['name']
48
+ end
49
+ raise NotFound.new("host: #{log.host}, path: #{log.path}", log) unless prefix
50
+
51
+ new(prefix['name'], prefix['schema_paths'], prefix['type'], prefix['skip'])
52
+ end
53
+
54
+ def cover!
55
+ @cover = true
56
+ end
57
+
58
+ def cover?
59
+ @cover
60
+ end
61
+ end
62
+ end
@@ -4,7 +4,6 @@ module Fitting
4
4
  class MyRailtie < Rails::Railtie
5
5
  rake_tasks do
6
6
  load 'tasks/fitting.rake'
7
- load 'tasks/fitting_outgoing.rake'
8
7
  end
9
8
  end
10
9
  end
@@ -5,15 +5,16 @@ module Fitting
5
5
  class Records
6
6
  class Spherical
7
7
  class Request
8
- attr_reader :method, :path, :body, :response, :title, :group
8
+ attr_reader :method, :path, :body, :response, :title, :group, :host
9
9
 
10
- def initialize(method:, path:, body:, response:, title:, group:)
10
+ def initialize(method:, path:, body:, response:, title:, group:, host:)
11
11
  @method = method
12
12
  @path = path
13
13
  @body = body
14
14
  @response = response
15
15
  @title = title
16
16
  @group = group
17
+ @host = host
17
18
  end
18
19
 
19
20
  def to_hash
@@ -23,7 +24,8 @@ module Fitting
23
24
  body: body,
24
25
  response: response.to_hash,
25
26
  title: title,
26
- group: group
27
+ group: group,
28
+ host: host
27
29
  }
28
30
  end
29
31
 
@@ -39,7 +41,8 @@ module Fitting
39
41
  body: hash['body'],
40
42
  response: Fitting::Records::Spherical::Response.load(hash['response']),
41
43
  title: hash['title'],
42
- group: hash['group']
44
+ group: hash['group'],
45
+ host: hash['host']
43
46
  )
44
47
  end
45
48
  end
@@ -6,32 +6,38 @@ module Fitting
6
6
  class Response
7
7
  attr_reader :status, :body
8
8
 
9
- def initialize(status:, body:)
9
+ def initialize(status:, body:, content_type:)
10
10
  @status = status
11
11
  @body = body
12
+ @content_type = content_type
12
13
  end
13
14
 
14
15
  def to_hash
15
- {
16
- status: status,
17
- body: JSON.parse(body)
18
- }
19
- rescue JSON::ParserError
20
- {
21
- status: status,
22
- body: {}
23
- }
16
+ begin
17
+ parse_body = JSON.parse(body)
18
+ rescue JSON::ParserError
19
+ parse_body = {}
20
+ end
21
+
22
+ if @content_type == nil || @content_type == ''
23
+ {
24
+ status: status,
25
+ content_type: 'application/json',
26
+ body: parse_body
27
+ }
28
+ else
29
+ ct = @content_type.split("; ")
30
+ {
31
+ status: status,
32
+ content_type: ct.first,
33
+ body: parse_body
34
+ }
35
+ end
24
36
  end
25
37
 
26
38
  def to_json(*_args)
27
39
  JSON.dump(to_hash)
28
40
  end
29
-
30
- class << self
31
- def load(hash)
32
- new(status: hash['status'], body: hash['body'])
33
- end
34
- end
35
41
  end
36
42
  end
37
43
  end