fitting 2.13.0 → 2.16.0

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 (54) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ruby.yml +33 -0
  3. data/.rubocop.yml +1 -1
  4. data/.ruby-version +1 -1
  5. data/.tool-versions +1 -1
  6. data/CHANGELOG.md +52 -0
  7. data/README.md +83 -259
  8. data/example.png +0 -0
  9. data/example2.png +0 -0
  10. data/fitting.gemspec +5 -5
  11. data/lib/fitting/cover/json_schema.rb +8 -6
  12. data/lib/fitting/cover/json_schema_enum.rb +8 -6
  13. data/lib/fitting/cover/json_schema_one_of.rb +7 -5
  14. data/lib/fitting/records/spherical/requests.rb +3 -1
  15. data/lib/fitting/report/action.rb +53 -0
  16. data/lib/fitting/report/actions.rb +51 -0
  17. data/lib/fitting/report/combination.rb +37 -0
  18. data/lib/fitting/report/combinations.rb +47 -0
  19. data/lib/fitting/report/console.rb +41 -0
  20. data/lib/fitting/report/prefix.rb +88 -0
  21. data/lib/fitting/report/prefixes.rb +54 -0
  22. data/lib/fitting/report/response.rb +71 -0
  23. data/lib/fitting/report/responses.rb +48 -0
  24. data/lib/fitting/report/test.rb +75 -0
  25. data/lib/fitting/report/tests.rb +69 -0
  26. data/lib/fitting/tests.rb +0 -1
  27. data/lib/fitting/version.rb +1 -1
  28. data/lib/tasks/fitting.rake +130 -0
  29. data/lib/templates/bomboniere/.gitignore +21 -0
  30. data/lib/templates/bomboniere/.tool-versions +1 -0
  31. data/lib/templates/bomboniere/README.md +19 -0
  32. data/lib/templates/bomboniere/dist/css/app.aa2bcd8a.css +1 -0
  33. data/lib/templates/bomboniere/dist/css/chunk-vendors.ec5f6c3f.css +1 -0
  34. data/lib/templates/bomboniere/dist/favicon.ico +0 -0
  35. data/lib/templates/bomboniere/dist/index.html +1 -0
  36. data/lib/templates/bomboniere/dist/js/app.e5f1a5ec.js +2 -0
  37. data/lib/templates/bomboniere/dist/js/app.e5f1a5ec.js.map +1 -0
  38. data/lib/templates/bomboniere/dist/js/chunk-vendors.0f99b670.js +13 -0
  39. data/lib/templates/bomboniere/dist/js/chunk-vendors.0f99b670.js.map +1 -0
  40. data/lib/templates/bomboniere/package-lock.json +9277 -0
  41. data/lib/templates/bomboniere/package.json +27 -0
  42. data/lib/templates/bomboniere/public/favicon.ico +0 -0
  43. data/lib/templates/bomboniere/public/index.html +17 -0
  44. data/lib/templates/bomboniere/src/App.vue +102 -0
  45. data/lib/templates/bomboniere/src/assets/logo.png +0 -0
  46. data/lib/templates/bomboniere/src/components/HelloWorld.vue +201 -0
  47. data/lib/templates/bomboniere/src/main.js +10 -0
  48. data/lib/templates/bomboniere/src/router/index.js +31 -0
  49. data/lib/templates/bomboniere/src/views/About.vue +5 -0
  50. data/lib/templates/bomboniere/src/views/Action.vue +173 -0
  51. data/lib/templates/bomboniere/src/views/Home.vue +17 -0
  52. data/lib/templates/bomboniere/vue.config.js +3 -0
  53. metadata +68 -31
  54. data/.travis.yml +0 -4
data/example.png ADDED
Binary file
data/example2.png ADDED
Binary file
data/fitting.gemspec CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
8
8
  spec.authors = ['d.efimov']
9
9
  spec.email = ['d.efimov@fun-box.ru']
10
10
 
11
- spec.summary = 'Validation in the rspec of API Blueprint'
12
- spec.description = 'Validation responses in the rspec with the help of API Blueprint'
11
+ spec.summary = 'Coverage API Blueprint, Swagger and OpenAPI with rspec tests'
12
+ spec.description = 'Coverage API Blueprint, Swagger and OpenAPI with rspec tests for easily make high-quality API and documenatiton.'
13
13
  spec.homepage = 'https://github.com/funbox/fitting'
14
14
  spec.license = 'MIT'
15
15
 
@@ -20,10 +20,10 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.add_runtime_dependency 'json-schema', '~> 2.6', '>= 2.6.2'
22
22
  spec.add_runtime_dependency 'multi_json', '~> 1.11'
23
- spec.add_runtime_dependency 'tomograph', '~> 2.0', '>= 2.2.0'
24
- spec.add_development_dependency 'bundler', '~> 1.12'
23
+ spec.add_runtime_dependency 'tomograph', '~> 3.1', '>= 3.1.0'
24
+ spec.add_development_dependency 'bundler', '~> 2.0'
25
25
  spec.add_development_dependency 'byebug', '~> 8.2', '>= 8.2.1'
26
- spec.add_development_dependency 'rake', '~> 10.0'
26
+ spec.add_development_dependency 'rake', '>= 12.3.3'
27
27
  spec.add_development_dependency 'rspec', '~> 3.4', '>= 3.4.0'
28
28
  spec.add_development_dependency 'rubocop', '~> 0.49.1', '>= 0.49.1'
29
29
  spec.add_development_dependency 'simplecov', '~> 0.11', '>= 0.11.2'
@@ -16,17 +16,19 @@ module Fitting
16
16
  def inception(json_schema, combinations)
17
17
  json_schema.each do |key, value|
18
18
  if key == 'properties' and json_schema['required'] != value.keys
19
- one_of = json_schema.delete('required') || []
20
- json_schema['properties'].each_key do |property|
19
+ schema = json_schema.dup
20
+ one_of = schema.delete('required') || []
21
+ schema['properties'].each_key do |property|
21
22
  next if one_of.include?(property)
22
- combinations.push([json_schema.merge('required' => one_of + [property]), "required.#{property}"])
23
+ combinations.push([schema.merge('required' => one_of + [property]), "required.#{property}"])
23
24
  end
24
25
  elsif value.is_a?(Hash)
25
- inception(value, combinations)
26
- combinations.each do |combination|
27
- combination[0] = { key => combination[0]}
26
+ com = inception(value, [])
27
+ com.each do |combination|
28
+ combination[0] = { key => value.merge(combination[0])}
28
29
  combination[1] = "#{key}.#{combination[1]}"
29
30
  end
31
+ combinations += com
30
32
  end
31
33
  end
32
34
 
@@ -15,17 +15,19 @@ module Fitting
15
15
 
16
16
  def inception(json_schema, combinations)
17
17
  json_schema.each do |key, value|
18
- if key == 'enum'
19
- one_of = json_schema.delete('enum')
18
+ if key == 'enum' && value.size > 1
19
+ schema = json_schema.dup
20
+ one_of = schema.delete('enum')
20
21
  one_of.each_index do |index|
21
- combinations.push([json_schema.merge('enum' => [one_of[index]]), "enum.#{one_of[index]}"])
22
+ combinations.push([schema.merge('enum' => [one_of[index]]), "enum.#{one_of[index]}"])
22
23
  end
23
24
  elsif value.is_a?(Hash)
24
- inception(value, combinations)
25
- combinations.each do |combination|
26
- combination[0] = { key => combination[0]}
25
+ com = inception(value, [])
26
+ com.each do |combination|
27
+ combination[0] = { key => value.merge(combination[0])}
27
28
  combination[1] = "#{key}.#{combination[1]}"
28
29
  end
30
+ combinations += com
29
31
  end
30
32
  end
31
33
 
@@ -16,16 +16,18 @@ module Fitting
16
16
  def inception(json_schema, combinations)
17
17
  json_schema.each do |key, value|
18
18
  if key == 'oneOf'
19
- one_of = json_schema.delete('oneOf')
19
+ schema = json_schema.dup
20
+ one_of = schema.delete('oneOf')
20
21
  one_of.each_index do |index|
21
- combinations.push([json_schema.merge('oneOf' => [one_of[index]]), "oneOf.#{index}"])
22
+ combinations.push([schema.merge('oneOf' => [one_of[index]]), "oneOf.#{index}"])
22
23
  end
23
24
  elsif value.is_a?(Hash)
24
- inception(value, combinations)
25
- combinations.each do |combination|
26
- combination[0] = { key => combination[0]}
25
+ com = inception(value, [])
26
+ com.each do |combination|
27
+ combination[0] = { key => value.merge(combination[0])}
27
28
  combination[1] = "#{key}.#{combination[1]}"
28
29
  end
30
+ combinations += com
29
31
  end
30
32
  end
31
33
 
@@ -13,7 +13,9 @@ module Fitting
13
13
  array += JSON.load(File.read(file))
14
14
  end
15
15
  @to_a = array.inject([]) do |res, tested_request|
16
- res.push(Fitting::Records::Spherical::Request.load(tested_request))
16
+ request = Fitting::Records::Spherical::Request.load(tested_request)
17
+ next res unless request.path.to_s.start_with?(Fitting.configuration.prefix)
18
+ res.push(request)
17
19
  end
18
20
  end
19
21
  end
@@ -0,0 +1,53 @@
1
+ require 'fitting/report/responses'
2
+
3
+ module Fitting
4
+ module Report
5
+ class Action
6
+ def initialize(action)
7
+ @action = action
8
+ @tests = Fitting::Report::Tests.new([])
9
+ @responses = Fitting::Report::Responses.new(@action.responses)
10
+ end
11
+
12
+ def method
13
+ @action.method
14
+ end
15
+
16
+ def path
17
+ @action.path.to_s
18
+ end
19
+
20
+ def responses
21
+ @responses
22
+ end
23
+
24
+ def add_test(test)
25
+ @tests.push(test)
26
+ end
27
+
28
+ def path_match(find_path)
29
+ regexp =~ find_path
30
+ end
31
+
32
+ def regexp
33
+ return @regexp if @regexp
34
+
35
+ str = Regexp.escape(path)
36
+ str = str.gsub(/\\{\w+\\}/, '[^&=\/]+')
37
+ str = "\\A#{str}\\z"
38
+ @regexp = Regexp.new(str)
39
+ end
40
+
41
+ def tests
42
+ @tests
43
+ end
44
+
45
+ def details
46
+ {
47
+ tests_without_responses: @tests.without_responses,
48
+ responses_details: @responses.to_a.map { |r| {method: r.status, tests_size: r.tests.size, json_schema: r.id, combinations: r.details} }
49
+ }
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,51 @@
1
+ require 'fitting/report/action'
2
+
3
+ module Fitting
4
+ module Report
5
+ class Actions
6
+ def initialize(actions)
7
+ @actions = []
8
+ actions.to_a.map do |action|
9
+ @actions.push(Fitting::Report::Action.new(action))
10
+ end
11
+ end
12
+
13
+ def to_a
14
+ @actions
15
+ end
16
+
17
+ def join(tests)
18
+ tests.to_a.map do |test|
19
+ if is_there_a_suitable_action?(test)
20
+ cram_into_the_appropriate_action(test)
21
+ test.mark_action
22
+ end
23
+ end
24
+ end
25
+
26
+ def is_there_a_suitable_action?(test)
27
+ @actions.map do |action|
28
+ return true if test.method == action.method && action.path_match(test.path)
29
+ end
30
+
31
+ false
32
+ end
33
+
34
+ def cram_into_the_appropriate_action(test)
35
+ @actions.map do |action|
36
+ if test.method == action.method && action.path_match(test.path)
37
+ action.add_test(test)
38
+ return
39
+ end
40
+ end
41
+ end
42
+
43
+ def details(prefix)
44
+ {
45
+ tests_without_actions: prefix.tests.without_actions,
46
+ actions_details: @actions.map { |a| {method: a.method, path: a.path, tests_size: a.tests.size, responses: a.details} }
47
+ }
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,37 @@
1
+ module Fitting
2
+ module Report
3
+ class Combination
4
+ def initialize(json_schema:, type:, combination:)
5
+ @json_schema = json_schema
6
+ @type = type
7
+ @combination = combination
8
+ @tests = Fitting::Report::Tests.new([])
9
+ @id = SecureRandom.hex
10
+ end
11
+
12
+ def json_schema
13
+ @json_schema
14
+ end
15
+
16
+ def id
17
+ @id
18
+ end
19
+
20
+ def type
21
+ @type
22
+ end
23
+
24
+ def name
25
+ @combination
26
+ end
27
+
28
+ def tests
29
+ @tests
30
+ end
31
+
32
+ def add_test(test)
33
+ @tests.push(test)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,47 @@
1
+ module Fitting
2
+ module Report
3
+ class Combinations
4
+ def initialize(combinations)
5
+ @combinations = combinations
6
+ end
7
+
8
+ def to_a
9
+ @combinations
10
+ end
11
+
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 is_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 is_there_a_suitable_combination?(test)
30
+ return false if @combinations.nil?
31
+ @combinations.map do |combination|
32
+ return true if JSON::Validator.fully_validate(combination.json_schema, test.body) == []
33
+ end
34
+
35
+ false
36
+ end
37
+
38
+ def cram_into_the_appropriate_combinations(test)
39
+ @combinations.map do |combination|
40
+ if JSON::Validator.fully_validate(combination.json_schema, test.body) == []
41
+ combination.add_test(test)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,41 @@
1
+ module Fitting
2
+ module Report
3
+ class Console
4
+ def initialize(tests_without_prefixes, prefixes_details)
5
+ @tests_without_prefixes = tests_without_prefixes
6
+ @prefixes_details = prefixes_details
7
+ @good = true
8
+ @tests_without_actions = []
9
+ @tests_without_responses = []
10
+ end
11
+
12
+ def output
13
+ doc_res = @prefixes_details.inject('') do |res, prefix_details|
14
+ res += "#{prefix_details[:name]}\n"
15
+ @tests_without_actions += prefix_details[:actions][:tests_without_actions]
16
+ res += prefix_details[:actions][:actions_details].inject('') do |res_actions, action|
17
+ res_actions += "#{action[:method]}\t#{action[:path]}"
18
+ tab = "\t" * (8 - action[:path].size / 8)
19
+ @tests_without_responses += action[:responses][:tests_without_responses]
20
+ res_actions += tab + action[:responses][:responses_details].inject('') do |res_responses, response|
21
+ @good = false if response[:combinations][:cover_percent] != '100%'
22
+ res_responses += " #{response[:combinations][:cover_percent]} #{response[:method]}"
23
+ end
24
+ res_actions += "\n"
25
+ end
26
+ end
27
+ doc_res += "\n"
28
+ doc_res += "tests_without_prefixes: #{@tests_without_prefixes.size}\n"
29
+ doc_res += "tests_without_actions: #{@tests_without_actions.size}\n"
30
+ doc_res += "tests_without_responses: #{@tests_without_responses.size}\n"
31
+ end
32
+
33
+ def good?
34
+ return false if @tests_without_prefixes.size != 0
35
+ return false if @tests_without_actions.size != 0
36
+ return false if @tests_without_responses.size != 0
37
+ @good
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,88 @@
1
+ require 'fitting/report/actions'
2
+
3
+ module Fitting
4
+ module Report
5
+ class Prefix
6
+ def initialize(name: '', openapi2_json_path: nil, openapi3_yaml_path: nil, drafter_yaml_path: nil, tomogram_json_path: nil, crafter_yaml_path: nil, skip: false)
7
+ @name = name
8
+ @tomogram_json_path = tomogram_json_path
9
+ @tests = Fitting::Report::Tests.new([])
10
+ @skip = skip
11
+ unless skip
12
+ @actions = if openapi2_json_path
13
+ Fitting::Report::Actions.new(
14
+ Tomograph::Tomogram.new(
15
+ prefix: name,
16
+ openapi2_json_path: openapi2_json_path
17
+ )
18
+ )
19
+ elsif openapi3_yaml_path
20
+ Fitting::Report::Actions.new(
21
+ Tomograph::Tomogram.new(
22
+ prefix: name,
23
+ openapi3_yaml_path: openapi3_yaml_path
24
+ )
25
+ )
26
+ elsif drafter_yaml_path
27
+ Fitting::Report::Actions.new(
28
+ Tomograph::Tomogram.new(
29
+ prefix: name,
30
+ drafter_yaml_path: drafter_yaml_path
31
+ )
32
+ )
33
+ elsif crafter_yaml_path
34
+ Fitting::Report::Actions.new(
35
+ Tomograph::Tomogram.new(
36
+ prefix: name,
37
+ crafter_yaml_path: crafter_yaml_path
38
+ )
39
+ )
40
+ else
41
+ Fitting::Report::Actions.new(
42
+ Tomograph::Tomogram.new(
43
+ prefix: name,
44
+ tomogram_json_path: tomogram_json_path
45
+ )
46
+ )
47
+ end
48
+ end
49
+ end
50
+
51
+ def name
52
+ @name
53
+ end
54
+
55
+ def tests
56
+ @tests
57
+ end
58
+
59
+ def skip?
60
+ @skip
61
+ end
62
+
63
+ def actions
64
+ @actions
65
+ end
66
+
67
+ def details
68
+ if @skip
69
+ {
70
+ name: @name,
71
+ tests_size: @tests.size,
72
+ actions: {tests_without_actions: [], actions_details: []}
73
+ }
74
+ else
75
+ {
76
+ name: @name,
77
+ tests_size: @tests.size,
78
+ actions: @actions.details(self)
79
+ }
80
+ end
81
+ end
82
+
83
+ def add_test(test)
84
+ @tests.push(test)
85
+ end
86
+ end
87
+ end
88
+ end