fitting 2.18.1 → 3.0.1

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 (65) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +2 -11
  3. data/CHANGELOG.md +21 -0
  4. data/README.md +46 -6
  5. data/fitting.gemspec +3 -1
  6. data/lib/fitting/configuration.rb +11 -41
  7. data/lib/fitting/cover/json_schema.rb +4 -2
  8. data/lib/fitting/cover/json_schema_enum.rb +4 -2
  9. data/lib/fitting/cover/json_schema_one_of.rb +4 -2
  10. data/lib/fitting/railtie.rb +1 -0
  11. data/lib/fitting/records/documented/request.rb +1 -15
  12. data/lib/fitting/records/spherical/requests.rb +1 -1
  13. data/lib/fitting/records/tested/request.rb +11 -11
  14. data/lib/fitting/records/tested/response.rb +4 -4
  15. data/lib/fitting/report/actions.rb +4 -0
  16. data/lib/fitting/report/console.rb +32 -12
  17. data/lib/fitting/report/prefix.rb +20 -41
  18. data/lib/fitting/report/prefixes.rb +7 -8
  19. data/lib/fitting/report/response.rb +0 -3
  20. data/lib/fitting/report/tests.rb +23 -10
  21. data/lib/fitting/storage/responses.rb +5 -9
  22. data/lib/fitting/tests.rb +12 -4
  23. data/lib/fitting/version.rb +1 -1
  24. data/lib/fitting.rb +38 -43
  25. data/lib/tasks/fitting.rake +3 -186
  26. data/lib/tasks/fitting_outgoing.rake +91 -0
  27. metadata +28 -45
  28. data/lib/fitting/configuration/legacy.rb +0 -61
  29. data/lib/fitting/configuration/yaml.rb +0 -89
  30. data/lib/fitting/cover/response.rb +0 -37
  31. data/lib/fitting/documentation.rb +0 -56
  32. data/lib/fitting/matchers/response_matcher.rb +0 -96
  33. data/lib/fitting/records/realized_unit.rb +0 -52
  34. data/lib/fitting/records/test_unit/request.rb +0 -98
  35. data/lib/fitting/records/unit/combination.rb +0 -27
  36. data/lib/fitting/records/unit/json_schema.rb +0 -111
  37. data/lib/fitting/records/unit/request.rb +0 -37
  38. data/lib/fitting/records/unit/response.rb +0 -32
  39. data/lib/fitting/request.rb +0 -38
  40. data/lib/fitting/response/fully_validates.rb +0 -34
  41. data/lib/fitting/response.rb +0 -88
  42. data/lib/fitting/statistics/analysis.rb +0 -25
  43. data/lib/fitting/statistics/cover_error.rb +0 -29
  44. data/lib/fitting/statistics/cover_error_enum.rb +0 -29
  45. data/lib/fitting/statistics/cover_error_one_of.rb +0 -29
  46. data/lib/fitting/statistics/great.rb +0 -13
  47. data/lib/fitting/statistics/list.rb +0 -55
  48. data/lib/fitting/statistics/lists.rb +0 -53
  49. data/lib/fitting/statistics/measurement.rb +0 -92
  50. data/lib/fitting/statistics/measurement_cover.rb +0 -92
  51. data/lib/fitting/statistics/measurement_cover_enum.rb +0 -92
  52. data/lib/fitting/statistics/measurement_cover_one_of.rb +0 -92
  53. data/lib/fitting/statistics/not_covered_responses.rb +0 -13
  54. data/lib/fitting/statistics/percent.rb +0 -20
  55. data/lib/fitting/statistics/requests_stats.rb +0 -40
  56. data/lib/fitting/statistics/responses_stats.rb +0 -32
  57. data/lib/fitting/statistics/template.rb +0 -117
  58. data/lib/fitting/statistics/template_cover_error.rb +0 -50
  59. data/lib/fitting/statistics/template_cover_error_enum.rb +0 -50
  60. data/lib/fitting/statistics/template_cover_error_one_of.rb +0 -50
  61. data/lib/fitting/statistics.rb +0 -25
  62. data/lib/fitting/storage/white_list.rb +0 -158
  63. data/lib/fitting/templates/realized_template.rb +0 -49
  64. data/lib/fitting/view/report.html.haml +0 -16
  65. data/lib/fitting/view/style.css +0 -47
@@ -3,13 +3,26 @@ require 'fitting/report/test'
3
3
  module Fitting
4
4
  module Report
5
5
  class Tests
6
+ attr_reader :tests
7
+
6
8
  def initialize(tests)
7
9
  @tests = tests
8
10
  end
9
11
 
10
- def self.new_from_config(tests_path)
12
+ def self.new_from_config
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
18
+ end
19
+ tests.sort { |a, b| b.path <=> a.path }
20
+ new(tests)
21
+ end
22
+
23
+ def self.new_from_outgoing_config
11
24
  tests = []
12
- Dir[tests_path].each do |file|
25
+ Dir["#{Fitting.configuration.webmock_json_path}/*.json"].each do |file|
13
26
  JSON.parse(File.read(file)).map do |test|
14
27
  tests.push(Fitting::Report::Test.new(test))
15
28
  end
@@ -19,45 +32,45 @@ module Fitting
19
32
  end
20
33
 
21
34
  def without_prefixes
22
- @tests.each_with_object([]) do |test, result|
35
+ tests.each_with_object([]) do |test, result|
23
36
  result.push(test.path) unless test.there_a_prefix?
24
37
  end
25
38
  end
26
39
 
27
40
  def without_actions
28
- @tests.each_with_object([]) do |test, result|
41
+ tests.each_with_object([]) do |test, result|
29
42
  result.push("#{test.method} #{test.path}") unless test.there_an_actions?
30
43
  end
31
44
  end
32
45
 
33
46
  def without_responses
34
- @tests.each_with_object([]) do |test, result|
47
+ tests.each_with_object([]) do |test, result|
35
48
  result.push(test.id) unless test.there_an_responses?
36
49
  end
37
50
  end
38
51
 
39
52
  def without_combinations
40
- @tests.each_with_object([]) do |test, result|
53
+ tests.each_with_object([]) do |test, result|
41
54
  result.push(test.path) unless test.there_an_combinations?
42
55
  end
43
56
  end
44
57
 
45
58
  def push(test)
46
- @tests.push(test)
59
+ tests.push(test)
47
60
  end
48
61
 
49
62
  def size
50
- @tests.size
63
+ tests.size
51
64
  end
52
65
 
53
66
  def to_a
54
- @tests
67
+ tests
55
68
  end
56
69
 
57
70
  def to_h
58
71
  return @hash if @hash
59
72
 
60
- @hash = @tests.inject({}) do |res, test|
73
+ @hash = tests.inject({}) do |res, test|
61
74
  res.merge!(test.id => test.to_h)
62
75
  end
63
76
  end
@@ -1,24 +1,20 @@
1
- require 'fitting/statistics'
2
- require 'fitting/tests'
3
1
  require 'fitting/records/tested/request'
4
2
 
5
3
  module Fitting
6
4
  module Storage
7
5
  class Responses
6
+ attr_reader :tested_requests
7
+
8
8
  def initialize
9
9
  @tested_requests = []
10
10
  end
11
11
 
12
- def add(env_response, metadata = {})
13
- @tested_requests.push(Fitting::Records::Tested::Request.new(env_response, metadata))
14
- end
15
-
16
- def statistics
17
- Fitting::Statistics.new(@tested_requests)
12
+ def add(response, example)
13
+ tested_requests.push(Fitting::Records::Tested::Request.new(response, example))
18
14
  end
19
15
 
20
16
  def tests
21
- Fitting::Tests.new(@tested_requests)
17
+ Fitting::Tests.new(tested_requests)
22
18
  end
23
19
  end
24
20
  end
data/lib/fitting/tests.rb CHANGED
@@ -1,5 +1,3 @@
1
- require 'fitting/statistics/template'
2
-
3
1
  module Fitting
4
2
  class Tests
5
3
  def initialize(tested_requests)
@@ -7,13 +5,23 @@ module Fitting
7
5
  end
8
6
 
9
7
  def save
10
- make_dir('fitting_tests')
8
+ make_dir(Fitting.configuration.rspec_json_path)
9
+ array = @tested_requests.inject([]) do |res, request|
10
+ res.push(request.to_spherical.to_hash)
11
+ end
12
+ json = JSON.dump(array)
13
+
14
+ File.open("#{Fitting.configuration.rspec_json_path}/test#{ENV['TEST_ENV_NUMBER']}.json", 'w') { |file| file.write(json) }
15
+ end
16
+
17
+ def outgoing_save
18
+ make_dir('./outgoing_request_tests')
11
19
  array = @tested_requests.inject([]) do |res, request|
12
20
  res.push(request.to_spherical.to_hash)
13
21
  end
14
22
  json = JSON.dump(array)
15
23
 
16
- File.open("fitting_tests/test#{ENV['TEST_ENV_NUMBER']}.json", 'w') { |file| file.write(json) }
24
+ File.open("./outgoing_request_tests/test#{ENV['TEST_ENV_NUMBER']}.json", 'w') { |file| file.write(json) }
17
25
  end
18
26
 
19
27
  def make_dir(dir_name)
@@ -1,3 +1,3 @@
1
1
  module Fitting
2
- VERSION = '2.18.1'.freeze
2
+ VERSION = '3.0.1'.freeze
3
3
  end
data/lib/fitting.rb CHANGED
@@ -1,73 +1,68 @@
1
1
  require 'fitting/version'
2
2
  require 'fitting/configuration'
3
- require 'fitting/matchers/response_matcher'
4
- require 'fitting/documentation'
3
+
5
4
  require 'fitting/storage/responses'
5
+ require 'fitting/tests'
6
+ require 'fitting/cover/json_schema_enum'
7
+ require 'fitting/cover/json_schema_one_of'
8
+ require 'fitting/records/documented/request'
6
9
  require 'fitting/railtie' if defined?(Rails)
7
10
 
8
11
  module Fitting
9
12
  class << self
10
- def configure
11
- yield configuration
12
- end
13
-
14
13
  def configuration
15
- @configuration ||= Configuration.craft
14
+ yaml = YAML.safe_load(File.read('.fitting.yml'))
15
+ @configuration ||= Configuration.new(yaml)
16
16
  end
17
17
 
18
- def statistics
19
- responses = Fitting::Storage::Responses.new
20
-
21
- RSpec.configure do |config|
22
- config.after(:each, type: :controller) do
23
- responses.add(response, inspect)
24
- end
25
-
26
- config.after(:suite) do
27
- responses.statistics.save
28
- end
29
- end
18
+ def configure
19
+ yield(configuration)
30
20
  end
31
21
 
32
- extend Gem::Deprecate
33
- deprecate :statistics, :save_test_data, 2022, 1
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
34
26
 
35
27
  def save_test_data
36
- responses = Fitting::Storage::Responses.new
28
+ clear_tests_directory
37
29
 
38
- FileUtils.rm_r Dir.glob('fitting_tests/*'), force: true
30
+ outgoing_responses = Fitting::Storage::Responses.new
31
+ responses = Fitting::Storage::Responses.new
39
32
 
40
33
  RSpec.configure do |config|
34
+ if defined?(WebMock)
35
+ config.before(:each) do |example|
36
+ WebMock.after_request do |request_signature, response|
37
+ env = Rack::MockRequest.env_for(request_signature.uri, { method: request_signature.method })
38
+ # Парсим в тот формат с которым работает fitting
39
+ mock_request = ActionDispatch::Request.new(env)
40
+ mock_response = ActionDispatch::Response.create(response.status.first || 200, response.headers || {},
41
+ response.body || {})
42
+ mock_response.instance_variable_set(:@request, mock_request)
43
+
44
+ outgoing_responses.add(mock_response, example)
45
+ end
46
+ end
47
+ end
48
+
41
49
  config.after(:each, type: :request) do |example|
42
- responses.add(response, example.metadata)
50
+ responses.add(response, example)
43
51
  end
44
52
 
45
53
  config.after(:each, type: :controller) do |example|
46
- responses.add(response, example.metadata)
54
+ responses.add(response, example)
55
+ end
56
+
57
+ config.after(:each) do
58
+ WebMock::CallbackRegistry.reset
47
59
  end
48
60
 
49
61
  config.after(:suite) do
50
62
  responses.tests.save
63
+ outgoing_responses.tests.outgoing_save
51
64
  end
52
65
  end
53
66
  end
54
67
  end
55
-
56
- def self.loaded_tasks=(val)
57
- @loaded_tasks = val
58
- end
59
-
60
- def self.loaded_tasks
61
- @loaded_tasks
62
- end
63
-
64
- def self.load_tasks
65
- return if loaded_tasks
66
-
67
- self.loaded_tasks = true
68
-
69
- Dir[File.join(File.dirname(__FILE__), 'tasks', '**/*.rake')].each do |rake|
70
- load rake
71
- end
72
- end
73
68
  end
@@ -1,10 +1,4 @@
1
1
  require 'fitting/records/spherical/requests'
2
- require 'fitting/configuration'
3
- require 'fitting/records/realized_unit'
4
- require 'fitting/templates/realized_template'
5
- require 'fitting/statistics/template_cover_error'
6
- require 'fitting/statistics/template_cover_error_enum'
7
- require 'fitting/statistics/template_cover_error_one_of'
8
2
  require 'fitting/cover/json_schema'
9
3
  require 'fitting/report/prefixes'
10
4
  require 'fitting/report/tests'
@@ -12,8 +6,8 @@ require 'fitting/report/console'
12
6
 
13
7
  namespace :fitting do
14
8
  task :report do
15
- tests = Fitting::Report::Tests.new_from_config('fitting_tests/*.json')
16
- prefixes = Fitting::Report::Prefixes.new('.fitting.yml')
9
+ tests = Fitting::Report::Tests.new_from_config
10
+ prefixes = Fitting::Report::Prefixes.new(Fitting.configuration.prefixes)
17
11
 
18
12
  prefixes.join(tests)
19
13
 
@@ -88,187 +82,10 @@ namespace :fitting do
88
82
  )
89
83
 
90
84
  puts console.output
85
+ puts console.output_sum
91
86
 
92
87
  exit 1 unless console.good?
93
88
 
94
89
  exit 0
95
-
96
- actions.map do |action|
97
- action.to_hash['responses'].map do |response|
98
- response['combination'] ||= []
99
- combinations = Fitting::Cover::JSONSchema.new(response['body']).combi +
100
- Fitting::Cover::JSONSchemaEnum.new(response['body']).combi +
101
- Fitting::Cover::JSONSchemaOneOf.new(response['body']).combi
102
- next unless combinations != []
103
-
104
- combinations.map do |combination|
105
- response['combination'].push(
106
- {
107
- 'json_schema' => combination[0],
108
- 'type' => combination[1][0],
109
- 'combination' => combination[1][1],
110
- 'tests' => [],
111
- 'error' => []
112
- }
113
- )
114
- end
115
- end
116
- end
117
-
118
- actions.map do |action|
119
- action.to_hash['responses'].map do |response|
120
- response['tests'] ||= []
121
- response['tests'].map do |test|
122
- next unless response['combination'][0]
123
-
124
- response['combination'].map do |combination|
125
- res = JSON::Validator.fully_validate(combination['json_schema'], test['response']['body'])
126
- if res == []
127
- combination['tests'].push(test)
128
- response['tests'] = response['tests'] - [test]
129
- next
130
- else
131
- combination['error'].push({ test: test, error: res })
132
- end
133
- rescue JSON::Schema::SchemaError => e
134
- combination['error'].push({ test: test, error: e })
135
- end
136
- end
137
- end
138
- end
139
-
140
- actions_test = { actions: actions, tests: tests }
141
-
142
- makedirs('fitting')
143
- File.open('fitting/old_report.json', 'w') { |file| file.write(JSON.dump(actions_test)) }
144
- end
145
-
146
- # deprecated
147
- desc 'Fitting documentation'
148
- task :documentation do
149
- documented_unit = Fitting::Statistics::Template.new(
150
- Fitting::Records::Spherical::Requests.new,
151
- Fitting.configuration
152
- )
153
- puts documented_unit.stats
154
-
155
- unless documented_unit.not_covered == "\n"
156
- puts 'Not all responses from the whitelist are covered!'
157
- exit 1
158
- end
159
- end
160
-
161
- desc 'Fitting documentation responses cover'
162
- task :documentation_responses, [:size] => :environment do |_, args|
163
- case args.size
164
- when 'xs'
165
- documented_unit = Fitting::Statistics::Template.new(
166
- Fitting::Records::Spherical::Requests.new,
167
- Fitting.configuration
168
- )
169
- puts documented_unit.stats
170
-
171
- unless documented_unit.not_covered == "\n"
172
- puts 'Not all responses from the whitelist are covered!'
173
- exit 1
174
- end
175
- when 's'
176
- documented_unit = Fitting::Statistics::Template.new(
177
- Fitting::Records::Spherical::Requests.new,
178
- Fitting.configuration,
179
- 'cover'
180
- )
181
- puts documented_unit.stats
182
-
183
- unless documented_unit.not_covered == "\n"
184
- puts 'Not all responses from the whitelist are covered!'
185
- exit 1
186
- end
187
- when 'm'
188
- documented_unit = Fitting::Statistics::Template.new(
189
- Fitting::Records::Spherical::Requests.new,
190
- Fitting.configuration,
191
- 'cover_enum'
192
- )
193
- puts documented_unit.stats
194
-
195
- unless documented_unit.not_covered == "\n"
196
- puts 'Not all responses from the whitelist are covered!'
197
- exit 1
198
- end
199
- when 'l'
200
- documented_unit = Fitting::Statistics::Template.new(
201
- Fitting::Records::Spherical::Requests.new,
202
- Fitting.configuration,
203
- 'cover_one_of'
204
- )
205
- puts documented_unit.stats
206
-
207
- unless documented_unit.not_covered == "\n"
208
- puts 'Not all responses from the whitelist are covered!'
209
- exit 1
210
- end
211
- else
212
- puts 'need key xs, s, m or l'
213
- end
214
- end
215
-
216
- desc 'Fitting documentation responses cover error'
217
- task :documentation_responses_error, [:size] => :environment do |_, args|
218
- case args.size
219
- when 's'
220
- documented_unit = Fitting::Statistics::TemplateCoverError.new(
221
- Fitting::Records::Spherical::Requests.new,
222
- Fitting.configuration
223
- )
224
- puts documented_unit.stats
225
- when 'm'
226
- documented_unit = Fitting::Statistics::TemplateCoverErrorEnum.new(
227
- Fitting::Records::Spherical::Requests.new,
228
- Fitting.configuration
229
- )
230
- puts documented_unit.stats
231
- when 'l'
232
- documented_unit = Fitting::Statistics::TemplateCoverErrorOneOf.new(
233
- Fitting::Records::Spherical::Requests.new,
234
- Fitting.configuration
235
- )
236
- puts documented_unit.stats
237
- else
238
- puts 'need key s, m or l'
239
- end
240
- end
241
-
242
- # deprecated
243
- desc 'Fitting tests'
244
- task :tests do
245
- realized_unit = Fitting::Records::RealizedUnit.new(
246
- Fitting::Records::Spherical::Requests.new,
247
- Fitting.configuration.tomogram
248
- )
249
- puts Fitting::Templates::RealizedTemplate.new(realized_unit).to_s
250
-
251
- unless realized_unit.fully_covered?
252
- puts 'Not all responses from the whitelist are covered!'
253
- exit 1
254
- end
255
- end
256
-
257
- desc 'Fitting tests'
258
- task :tests_responses, [:size] => :environment do |_, args|
259
- if args.size == 'xs'
260
- realized_unit = Fitting::Records::RealizedUnit.new(
261
- Fitting::Records::Spherical::Requests.new,
262
- Fitting.configuration.tomogram
263
- )
264
- puts Fitting::Templates::RealizedTemplate.new(realized_unit).to_s
265
-
266
- unless realized_unit.fully_covered?
267
- puts 'Not all responses from the whitelist are covered!'
268
- exit 1
269
- end
270
- else
271
- puts 'need key xs'
272
- end
273
90
  end
274
91
  end
@@ -0,0 +1,91 @@
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'
6
+
7
+ namespace :fitting_out do
8
+ task :report do
9
+ tests = Fitting::Report::Tests.new_from_outgoing_config
10
+ prefixes = Fitting::Report::Prefixes.new(Fitting.configuration.outgoing_prefixes)
11
+
12
+ prefixes.join(tests)
13
+
14
+ prefixes.to_a.map do |prefix|
15
+ prefix.actions.join(prefix.tests) unless prefix.skip?
16
+ end
17
+
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
24
+ 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[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
90
+ end
91
+ end