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
@@ -3,6 +3,15 @@ require 'fitting/report/response'
3
3
  module Fitting
4
4
  module Report
5
5
  class Responses
6
+ class NotFound < RuntimeError
7
+ attr_reader :log
8
+
9
+ def initialize(msg, log)
10
+ @log = log
11
+ super(msg)
12
+ end
13
+ end
14
+
6
15
  def initialize(responses)
7
16
  @responses = responses
8
17
  @responses = []
@@ -11,38 +20,25 @@ module Fitting
11
20
  end
12
21
  end
13
22
 
14
- def to_a
15
- @responses
16
- end
17
-
18
- def join(tests)
19
- tests.to_a.map do |test|
20
- if there_a_suitable_response?(test)
21
- cram_into_the_appropriate_response(test)
22
- test.mark_response
23
- end
24
- end
25
- end
26
-
27
- def there_a_suitable_response?(test)
28
- return false if @responses.nil?
29
-
23
+ def find!(log)
24
+ message = ""
30
25
  @responses.map do |response|
31
- return true if response.status.to_s == test.status &&
32
- JSON::Validator.fully_validate(response.body, test.body) == []
26
+ if response.status.to_s == log.status
27
+ if JSON::Validator.fully_validate(response.body, log.body) == []
28
+ return response
29
+ else
30
+ message += "\nbody: #{response.body}\nvalidate: #{JSON::Validator.fully_validate(response.body, log.body)}\n"
31
+ end
32
+ else
33
+ message += "\nstatus: #{response.status}\n"
34
+ end
33
35
  end
34
36
 
35
- false
37
+ raise NotFound.new("method: #{log.method}, host: #{log.host}, path: #{log.path}, status: #{log.status}, body: #{log.body}\n\n#{message}", log)
36
38
  end
37
39
 
38
- def cram_into_the_appropriate_response(test)
39
- @responses.map do |response|
40
- next unless response.status.to_s == test.status &&
41
- JSON::Validator.fully_validate(response.body, test.body) == []
42
-
43
- response.add_test(test)
44
- break
45
- end
40
+ def to_a
41
+ @responses
46
42
  end
47
43
  end
48
44
  end
@@ -11,10 +11,8 @@ module Fitting
11
11
 
12
12
  def self.new_from_config
13
13
  tests = []
14
- Dir["#{Fitting.configuration.rspec_json_path}/*.json"].each do |file|
15
- JSON.parse(File.read(file)).map do |test|
16
- tests.push(Fitting::Report::Test.new(test))
17
- end
14
+ File.read('log/test.log').split("\n").select{|f|f.include?('incoming request ')}.each do |test|
15
+ tests.push(Fitting::Report::Test.new(JSON.load(test.split('incoming request ')[1])))
18
16
  end
19
17
  tests.sort { |a, b| b.path <=> a.path }
20
18
  new(tests)
@@ -22,10 +20,8 @@ module Fitting
22
20
 
23
21
  def self.new_from_outgoing_config
24
22
  tests = []
25
- Dir["#{Fitting.configuration.webmock_json_path}/*.json"].each do |file|
26
- JSON.parse(File.read(file)).map do |test|
27
- tests.push(Fitting::Report::Test.new(test))
28
- end
23
+ File.read('log/test.log').split("\n").select{|f|f.include?('outgoing request ')}.each do |test|
24
+ tests.push(Fitting::Report::Test.new(JSON.load(test.split('outgoing request ')[1])))
29
25
  end
30
26
  tests.sort { |a, b| b.path <=> a.path }
31
27
  new(tests)
@@ -0,0 +1,44 @@
1
+ module Fitting
2
+ class Skip
3
+ class Action
4
+ attr_accessor :host, :method, :path, :code
5
+
6
+ def initialize(host, method, path, code)
7
+ @host = host
8
+ @method = method
9
+ @path = path
10
+ @code = code
11
+ end
12
+
13
+ def self.all(actions)
14
+ return [] unless actions
15
+ actions.map do |action|
16
+ next if action['method'].nil? || action['path'].nil?
17
+ new(action['host'], action['method'], action['path'], action['code'])
18
+ end.compact
19
+ end
20
+
21
+ def self.find(actions, log)
22
+ actions.find do |action|
23
+ if action.host == log.host &&
24
+ action.method == log.method &&
25
+ action.path_match(log.path)
26
+ return action if action.code == nil
27
+ return action if action.code.to_s == log.status
28
+ end
29
+ end
30
+ end
31
+
32
+ def path_match(find_path)
33
+ regexp =~ find_path
34
+ end
35
+
36
+ def regexp
37
+ str = Regexp.escape(path)
38
+ str = str.gsub(/\\{\w+\\}/, '[^&=\/]+')
39
+ str = "\\A#{str}\\z"
40
+ Regexp.new(str)
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,29 @@
1
+ module Fitting
2
+ class Skip
3
+ class API
4
+ attr_accessor :type, :host, :prefix, :path
5
+
6
+ def initialize(type, host, prefix)
7
+ @type = type
8
+ @host = host
9
+ @prefix = prefix
10
+ end
11
+
12
+ def self.all(apis)
13
+ return [] unless apis
14
+ apis.map do |api|
15
+ next if api['method'] || api['path']
16
+ new('provided', api['host'], api['prefix'])
17
+ end.compact
18
+ end
19
+
20
+ def self.find(apis, log)
21
+ apis.find do |api|
22
+ if log.host == api.host
23
+ api.prefix.nil? || api.prefix == '' || log.path[0..api.prefix.size - 1] == api.prefix
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,21 @@
1
+ require 'fitting/skip/api'
2
+ require 'fitting/skip/action'
3
+
4
+ module Fitting
5
+ class Skip
6
+ def self.all
7
+ yaml = YAML.safe_load(File.read('.fitting.yml'))
8
+ {
9
+ apis: Fitting::Skip::API.all(yaml['SkipValidation']),
10
+ actions: Fitting::Skip::Action.all(yaml['SkipValidation'])
11
+ }
12
+ end
13
+
14
+ def self.find(skips, log)
15
+ api = Fitting::Skip::API.find(skips[:apis], log)
16
+ return api if api
17
+
18
+ Fitting::Skip::Action.find(skips[:actions], log)
19
+ end
20
+ end
21
+ end
@@ -1,3 +1,3 @@
1
1
  module Fitting
2
- VERSION = '3.0.2'.freeze
2
+ VERSION = '4.0.1'.freeze
3
3
  end
data/lib/fitting.rb CHANGED
@@ -1,35 +1,16 @@
1
1
  require 'json-schema'
2
2
  require 'fitting/version'
3
- require 'fitting/configuration'
4
- require 'fitting/storage/responses'
5
- require 'fitting/tests'
6
3
  require 'fitting/cover/json_schema_enum'
7
4
  require 'fitting/cover/json_schema_one_of'
8
5
  require 'fitting/records/documented/request'
9
6
  require 'fitting/railtie' if defined?(Rails)
7
+ require 'fitting/records/tested/request'
10
8
 
11
9
  module Fitting
12
10
  class << self
13
- def configuration
14
- yaml = YAML.safe_load(File.read('.fitting.yml'))
15
- @configuration ||= Configuration.new(yaml)
16
- end
17
-
18
- def configure
19
- yield(configuration)
20
- end
21
-
22
- def clear_tests_directory
23
- FileUtils.rm_r Dir.glob(configuration.rspec_json_path), force: true
24
- FileUtils.rm_r Dir.glob(configuration.webmock_json_path), force: true
25
- end
26
-
27
- def save_test_data
28
- clear_tests_directory
29
-
30
- outgoing_responses = Fitting::Storage::Responses.new
31
- responses = Fitting::Storage::Responses.new
32
-
11
+ def logger
12
+ # :nocov:
13
+ responses = ""
33
14
  RSpec.configure do |config|
34
15
  if defined?(WebMock)
35
16
  config.before(:each) do |example|
@@ -41,17 +22,20 @@ module Fitting
41
22
  response.body || {})
42
23
  mock_response.instance_variable_set(:@request, mock_request)
43
24
 
44
- outgoing_responses.add(mock_response, example)
25
+ request = Fitting::Records::Tested::Request.new(mock_response, example)
26
+ responses += "FITTING outgoing request #{request.to_spherical.to_json}\n"
45
27
  end
46
28
  end
47
29
  end
48
30
 
49
31
  config.after(:each, type: :request) do |example|
50
- responses.add(response, example)
32
+ request = Fitting::Records::Tested::Request.new(response, example)
33
+ responses += "FITTING incoming request #{request.to_spherical.to_json}\n"
51
34
  end
52
35
 
53
36
  config.after(:each, type: :controller) do |example|
54
- responses.add(response, example)
37
+ request = Fitting::Records::Tested::Request.new(response, example)
38
+ responses += "FITTING incoming request #{request.to_spherical.to_json}\n"
55
39
  end
56
40
 
57
41
  config.after(:each) do
@@ -59,10 +43,10 @@ module Fitting
59
43
  end
60
44
 
61
45
  config.after(:suite) do
62
- responses.tests.save
63
- outgoing_responses.tests.outgoing_save
46
+ File.open("log/fitting#{ENV['TEST_ENV_NUMBER']}.log", 'w') { |file| file.write(responses) }
64
47
  end
65
48
  end
49
+ # :nocov:
66
50
  end
67
51
  end
68
52
  end
@@ -1,91 +1,30 @@
1
- require 'fitting/records/spherical/requests'
2
- require 'fitting/cover/json_schema'
3
- require 'fitting/report/prefixes'
4
- require 'fitting/report/tests'
5
- require 'fitting/report/console'
1
+ require 'fitting/log'
2
+ require 'fitting/doc'
3
+ require 'fitting/skip'
4
+ require 'fitting/nocov'
5
+ require 'fitting/rep'
6
+ require 'fitting/debug'
6
7
 
7
8
  namespace :fitting do
8
- task :report do
9
- tests = Fitting::Report::Tests.new_from_config
10
- prefixes = Fitting::Report::Prefixes.new(Fitting.configuration.prefixes)
11
-
12
- prefixes.join(tests)
13
-
14
- prefixes.to_a.map do |prefix|
15
- prefix.actions.join(prefix.tests) unless prefix.skip?
9
+ task :validate do
10
+ logs = Fitting::Log.all
11
+ docs = Fitting::Doc.all
12
+ skips = Fitting::Skip.all
13
+
14
+ logs.each do |log|
15
+ Fitting::Doc.cover!(docs, log)
16
+ log.access!
17
+ rescue Fitting::Doc::NotFound => e
18
+ next log.pending! if Fitting::Skip.find(skips, log)
19
+ log.failure!(e)
16
20
  end
21
+ Fitting::Log.report(logs)
17
22
 
18
- prefixes.to_a.map do |prefix|
19
- next if prefix.skip?
20
-
21
- prefix.actions.to_a.map do |action|
22
- action.responses.join(action.tests)
23
- end
23
+ Fitting::NoCov.all(YAML.safe_load(File.read('.fitting.yml'))).each do |nocov|
24
+ nocov.find(docs).nocover!
24
25
  end
25
-
26
- prefixes.to_a.map do |prefix|
27
- next if prefix.skip?
28
-
29
- prefix.actions.to_a.map do |action|
30
- action.responses.to_a.map do |response|
31
- response.combinations.join(response.tests)
32
- end
33
- end
34
- end
35
-
36
- report = JSON.pretty_generate(
37
- {
38
- tests_without_prefixes: tests.without_prefixes,
39
- prefixes_details: prefixes.to_a.map(&:details)
40
- }
41
- )
42
-
43
- destination = 'fitting'
44
- FileUtils.mkdir_p(destination)
45
- FileUtils.rm_r Dir.glob("#{destination}/*"), force: true
46
- File.open('fitting/report.json', 'w') { |file| file.write(report) }
47
-
48
- gem_path = $LOAD_PATH.find { |i| i.include?('fitting') }
49
- source_path = "#{gem_path}/templates/bomboniere/dist"
50
- FileUtils.copy_entry source_path, destination
51
-
52
- json_schemas = {}
53
- combinations = {}
54
- prefixes.to_a.map do |prefix|
55
- next if prefix.skip?
56
-
57
- prefix.actions.to_a.map do |action|
58
- action.responses.to_a.map do |response|
59
- json_schemas.merge!(response.id => response.body)
60
- response.combinations.to_a.map do |combination|
61
- combinations.merge!(combination.id => combination.json_schema)
62
- end
63
- end
64
- end
65
- end
66
- File.open('fitting/json_schemas.json', 'w') { |file| file.write(JSON.pretty_generate(json_schemas)) }
67
- File.open('fitting/combinations.json', 'w') { |file| file.write(JSON.pretty_generate(combinations)) }
68
- File.open('fitting/tests.json', 'w') { |file| file.write(JSON.pretty_generate(tests.to_h)) }
69
-
70
- js_path = Dir["#{destination}/js/*"].find { |f| f[0..14] == 'fitting/js/app.' and f[-3..] == '.js' }
71
- js_file = File.read(js_path)
72
- new_js_file = js_file.gsub('{stub:"prefixes report"}', report)
73
- new_js_file = new_js_file.gsub('{stub:"for action page"}', report)
74
- new_js_file = new_js_file.gsub('{stub:"json-schemas"}', JSON.pretty_generate(json_schemas))
75
- new_js_file = new_js_file.gsub('{stub:"combinations"}', JSON.pretty_generate(combinations))
76
- new_js_file = new_js_file.gsub('{stub:"tests"}', JSON.pretty_generate(tests.to_h))
77
- File.open(js_path, 'w') { |file| file.write(new_js_file) }
78
-
79
- console = Fitting::Report::Console.new(
80
- tests.without_prefixes,
81
- prefixes.to_a.map(&:details)
82
- )
83
-
84
- puts console.output
85
- puts console.output_sum
86
-
87
- exit 1 unless console.good?
88
-
89
- exit 0
26
+ Fitting::Rep.new(docs).save!
27
+ Fitting::Debug.save!(docs, YAML.safe_load(File.read('.fitting.yml')))
28
+ Fitting::Doc.report(docs)
90
29
  end
91
30
  end