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,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
@@ -11,6 +11,10 @@ module Fitting
11
11
  @response = response
12
12
  end
13
13
 
14
+ def host
15
+ @host ||= @response.request.host
16
+ end
17
+
14
18
  def method
15
19
  @method ||= @response.request.request_method
16
20
  end
@@ -42,7 +46,8 @@ module Fitting
42
46
  body: body,
43
47
  response: fitting_response.to_spherical,
44
48
  title: test_path,
45
- group: test_file_path
49
+ group: test_file_path,
50
+ host: host
46
51
  )
47
52
  end
48
53
  end
@@ -16,10 +16,15 @@ module Fitting
16
16
  @body ||= @response.body
17
17
  end
18
18
 
19
+ def content_type
20
+ @content_type ||= @response.content_type
21
+ end
22
+
19
23
  def to_spherical
20
24
  Fitting::Records::Spherical::Response.new(
21
25
  status: status,
22
- body: body
26
+ body: body,
27
+ content_type: content_type
23
28
  )
24
29
  end
25
30
  end
@@ -0,0 +1,32 @@
1
+ module Fitting
2
+ class Rep
3
+ class HTML
4
+ def self.copy_file(folder, name)
5
+ File.open("#{folder}/#{name}", 'w') do |file|
6
+ file.write(
7
+ File.read("#{$LOAD_PATH.find { |i| i.include?('fitting') }}/templates/htmlcss/#{name}")
8
+ )
9
+ end
10
+ end
11
+
12
+ def self.copy_file_with_json(folder, name, fitting_json, fitting_lock_json)
13
+ res = File.read("#{$LOAD_PATH.find { |i| i.include?('fitting') }}/templates/htmlcss/#{name}")
14
+ File.open("#{folder}/#{name}", 'w') do |file|
15
+ file.write(
16
+ res
17
+ .gsub("{'fitting json': []}", ::JSON.pretty_generate(fitting_json))
18
+ .gsub("{'fitting lock json': []}", ::JSON.pretty_generate(fitting_lock_json))
19
+ )
20
+ end
21
+ end
22
+
23
+ def self.bootstrap(folder, fitting_json, fitting_lock_json)
24
+ copy_file_with_json(folder, 'fitting.html', fitting_json, fitting_lock_json)
25
+ copy_file(folder, 'bootstrap-nightshade.min.css')
26
+ copy_file(folder, 'darkmode.min.js')
27
+ copy_file(folder, 'jquery-3.6.0.min.js')
28
+ copy_file(folder, 'bootstrap.min.js')
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,24 @@
1
+ require 'fitting/rep/html'
2
+
3
+ module Fitting
4
+ class Rep
5
+ def initialize(apis)
6
+ @actions = apis
7
+ end
8
+
9
+ def save!
10
+ destination = 'coverage'
11
+ FileUtils.mkdir_p(destination)
12
+
13
+ fitting_json = @actions.inject({}) do |sum, action|
14
+ sum.merge(action.to_hash)
15
+ end
16
+ fitting_lock_json = @actions.inject({}) do |sum, action|
17
+ sum.merge(action.to_hash_lock)
18
+ end
19
+ File.open('coverage/.fitting.json', 'w') { |file| file.write(::JSON.pretty_generate(fitting_json)) }
20
+ File.open('coverage/.fitting.lock.json', 'w') { |file| file.write(::JSON.pretty_generate(fitting_lock_json)) }
21
+ Fitting::Rep::HTML.bootstrap('coverage', fitting_json, fitting_lock_json)
22
+ end
23
+ end
24
+ end
@@ -5,8 +5,16 @@ module Fitting
5
5
  class Action
6
6
  def initialize(action)
7
7
  @action = action
8
- @tests = Fitting::Report::Tests.new([])
9
8
  @responses = Fitting::Report::Responses.new(@action.responses)
9
+ @cover = false
10
+ end
11
+
12
+ def cover?
13
+ @cover
14
+ end
15
+
16
+ def cover!
17
+ @cover = true
10
18
  end
11
19
 
12
20
  def method
@@ -19,10 +27,6 @@ module Fitting
19
27
 
20
28
  attr_reader :responses, :tests
21
29
 
22
- def add_test(test)
23
- @tests.push(test)
24
- end
25
-
26
30
  def path_match(find_path)
27
31
  regexp =~ find_path
28
32
  end
@@ -35,16 +39,6 @@ module Fitting
35
39
  str = "\\A#{str}\\z"
36
40
  @regexp = Regexp.new(str)
37
41
  end
38
-
39
- def details
40
- {
41
- tests_without_responses: @tests.without_responses,
42
- responses_details: @responses.to_a.map do |r|
43
- { method: r.status, tests_size: r.tests.size, json_schema: r.id,
44
- combinations: r.details }
45
- end
46
- }
47
- end
48
42
  end
49
43
  end
50
44
  end
@@ -3,54 +3,43 @@ require 'fitting/report/action'
3
3
  module Fitting
4
4
  module Report
5
5
  class Actions
6
- def initialize(actions)
7
- @actions = []
8
- actions.to_a.map do |action|
9
- @actions.push(Fitting::Report::Action.new(action))
6
+ class Empty < RuntimeError; end
7
+ class NotFound < RuntimeError
8
+ attr_reader :log
9
+
10
+ def initialize(msg, log)
11
+ @log = log
12
+ super(msg)
10
13
  end
11
14
  end
12
15
 
13
- def to_a
14
- @actions
15
- end
16
+ def cover!
16
17
 
17
- def push(actions)
18
- @actions += actions.to_a
19
18
  end
20
19
 
21
- def join(tests)
22
- tests.to_a.map do |test|
23
- if there_a_suitable_action?(test)
24
- cram_into_the_appropriate_action(test)
25
- test.mark_action
26
- end
20
+ def initialize(actions)
21
+ @actions = []
22
+ actions.to_a.map do |action|
23
+ @actions.push(Fitting::Report::Action.new(action))
27
24
  end
28
25
  end
29
26
 
30
- def there_a_suitable_action?(test)
27
+ def find!(log)
28
+ raise Empty if @actions.empty?
31
29
  @actions.map do |action|
32
- return true if test.method == action.method && action.path_match(test.path)
30
+ if log.method == action.method && action.path_match(log.path)
31
+ return action
32
+ end
33
33
  end
34
-
35
- false
34
+ raise NotFound.new("method: #{log.method}, host: #{log.host}, path: #{log.path}", log)
36
35
  end
37
36
 
38
- def cram_into_the_appropriate_action(test)
39
- @actions.map do |action|
40
- if test.method == action.method && action.path_match(test.path)
41
- action.add_test(test)
42
- break
43
- end
44
- end
37
+ def to_a
38
+ @actions
45
39
  end
46
40
 
47
- def details(prefix)
48
- {
49
- tests_without_actions: prefix.tests.without_actions,
50
- actions_details: @actions.map do |a|
51
- { method: a.method, path: a.path, tests_size: a.tests.size, responses: a.details }
52
- end
53
- }
41
+ def push(actions)
42
+ @actions += actions.to_a
54
43
  end
55
44
  end
56
45
  end
@@ -5,18 +5,22 @@ module Fitting
5
5
  @json_schema = json_schema
6
6
  @type = type
7
7
  @combination = combination
8
- @tests = Fitting::Report::Tests.new([])
9
8
  @id = SecureRandom.hex
9
+ @cover = false
10
10
  end
11
11
 
12
- attr_reader :json_schema, :id, :type, :tests
12
+ attr_reader :json_schema, :id, :type
13
13
 
14
- def name
15
- @combination
14
+ def cover?
15
+ @cover
16
+ end
17
+
18
+ def cover!
19
+ @cover = true
16
20
  end
17
21
 
18
- def add_test(test)
19
- @tests.push(test)
22
+ def name
23
+ @combination
20
24
  end
21
25
  end
22
26
  end
@@ -1,6 +1,9 @@
1
1
  module Fitting
2
2
  module Report
3
3
  class Combinations
4
+ class Empty < RuntimeError; end
5
+ class NotFound < RuntimeError; end
6
+
4
7
  def initialize(combinations)
5
8
  @combinations = combinations
6
9
  end
@@ -9,37 +12,14 @@ module Fitting
9
12
  @combinations
10
13
  end
11
14
 
12
- def size
13
- @combinations.size
14
- end
15
-
16
- def size_with_tests
17
- @combinations.count { |c| c.tests.size != 0 }
18
- end
19
-
20
- def join(tests)
21
- tests.to_a.map do |test|
22
- if there_a_suitable_combination?(test)
23
- cram_into_the_appropriate_combinations(test)
24
- test.mark_combination
25
- end
26
- end
27
- end
28
-
29
- def there_a_suitable_combination?(test)
30
- return false if @combinations.nil?
31
-
32
- @combinations.map do |combination|
33
- return true if JSON::Validator.fully_validate(combination.json_schema, test.body) == []
34
- end
35
-
36
- false
37
- end
38
-
39
- def cram_into_the_appropriate_combinations(test)
15
+ def find!(test)
16
+ raise Empty if @combinations.empty?
40
17
  @combinations.map do |combination|
41
- combination.add_test(test) if JSON::Validator.fully_validate(combination.json_schema, test.body) == []
18
+ if JSON::Validator.fully_validate(combination.json_schema, test.body) == []
19
+ return combination
20
+ end
42
21
  end
22
+ raise NotFound
43
23
  end
44
24
  end
45
25
  end
@@ -11,15 +11,14 @@ module Fitting
11
11
  'tomogram' => :tomogram_json_path
12
12
  }.freeze
13
13
 
14
- attr_reader :name, :tests, :actions
14
+ attr_reader :name, :actions
15
15
 
16
16
  def initialize(schema_paths: nil, type: nil, name: '', skip: false, only: [])
17
17
  @name = name
18
- @tests = Fitting::Report::Tests.new([])
19
- @skip = skip
20
- return if skip
18
+ @cover = false
21
19
 
22
20
  @actions = Fitting::Report::Actions.new([])
21
+ return if skip
23
22
 
24
23
  schema_paths.each do |path|
25
24
  tomogram = Tomograph::Tomogram.new(prefix: name, KEYS[type] => path)
@@ -30,28 +29,12 @@ module Fitting
30
29
  end
31
30
  end
32
31
 
33
- def skip?
34
- @skip
35
- end
36
-
37
- def details
38
- if @skip
39
- {
40
- name: @name,
41
- tests_size: @tests.size,
42
- actions: { tests_without_actions: [], actions_details: [] }
43
- }
44
- else
45
- {
46
- name: @name,
47
- tests_size: @tests.size,
48
- actions: @actions.details(self)
49
- }
50
- end
32
+ def cover!
33
+ @cover = true
51
34
  end
52
35
 
53
- def add_test(test)
54
- @tests.push(test)
36
+ def cover?
37
+ @cover
55
38
  end
56
39
  end
57
40
  end
@@ -19,37 +19,23 @@ module Fitting
19
19
  end
20
20
  end
21
21
 
22
- def there_a_suitable_prefix?(test_path)
23
- @prefixes.map do |prefix|
24
- return true if prefix.name.nil?
25
- return true if prefix.name == ''
26
- return true if test_path[0..prefix.name.size - 1] == prefix.name
27
- end
28
-
29
- false
22
+ def to_a
23
+ @prefixes
30
24
  end
31
25
 
32
- def cram_into_the_appropriate_prefix(test)
26
+ def find!(test)
33
27
  @prefixes.map do |prefix|
34
- if prefix.name.nil? || prefix.name == '' || test.path[0..prefix.name.size - 1] == prefix.name
35
- prefix.add_test(test)
36
- break
28
+ puts test.path
29
+ puts test.host
30
+ puts test.method
31
+ puts test.status
32
+ puts test.body
33
+ puts prefix.name
34
+ if test.path[0..prefix.name.size - 1] == prefix.name
35
+ return prefix
37
36
  end
38
37
  end
39
38
  end
40
-
41
- def join(tests)
42
- tests.to_a.map do |test|
43
- if there_a_suitable_prefix?(test.path)
44
- cram_into_the_appropriate_prefix(test)
45
- test.mark_prefix
46
- end
47
- end
48
- end
49
-
50
- def to_a
51
- @prefixes
52
- end
53
39
  end
54
40
  end
55
41
  end
@@ -1,13 +1,24 @@
1
1
  require 'fitting/report/combinations'
2
2
  require 'fitting/report/combination'
3
+ require 'fitting/cover/json_schema'
4
+ require 'fitting/cover/json_schema_enum'
5
+ require 'fitting/cover/json_schema_one_of'
3
6
 
4
7
  module Fitting
5
8
  module Report
6
9
  class Response
7
10
  def initialize(response)
8
11
  @response = response
9
- @tests = Fitting::Report::Tests.new([])
10
12
  @id = SecureRandom.hex
13
+ @cover = false
14
+ end
15
+
16
+ def cover?
17
+ @cover
18
+ end
19
+
20
+ def cover!
21
+ @cover = true
11
22
  end
12
23
 
13
24
  def status
@@ -20,10 +31,6 @@ module Fitting
20
31
 
21
32
  attr_reader :id, :tests
22
33
 
23
- def add_test(test)
24
- @tests.push(test)
25
- end
26
-
27
34
  def combinations
28
35
  return @combinations if @combinations
29
36
 
@@ -45,23 +52,6 @@ module Fitting
45
52
 
46
53
  @combinations = Fitting::Report::Combinations.new(cmbntns)
47
54
  end
48
-
49
- def cover_percent
50
- return '0%' if @tests.size.zero?
51
- return '100%' if @combinations.size.zero?
52
-
53
- "#{(@combinations.size_with_tests + 1) * 100 / (@combinations.size + 1)}%"
54
- end
55
-
56
- def details
57
- {
58
- cover_percent: cover_percent,
59
- tests_without_combinations: @tests.without_combinations,
60
- combinations_details: @combinations.to_a.map do |c|
61
- { json_schema: c.id, tests_size: c.tests.size, type: c.type, name: c.name }
62
- end
63
- }
64
- end
65
55
  end
66
56
  end
67
57
  end