fitting 2.18.0 → 3.0.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 (66) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +5 -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/combinations.rb +1 -1
  17. data/lib/fitting/report/console.rb +35 -15
  18. data/lib/fitting/report/prefix.rb +20 -41
  19. data/lib/fitting/report/prefixes.rb +7 -8
  20. data/lib/fitting/report/response.rb +0 -3
  21. data/lib/fitting/report/tests.rb +23 -10
  22. data/lib/fitting/storage/responses.rb +5 -9
  23. data/lib/fitting/tests.rb +12 -4
  24. data/lib/fitting/version.rb +1 -1
  25. data/lib/fitting.rb +38 -43
  26. data/lib/tasks/fitting.rake +3 -186
  27. data/lib/tasks/fitting_outgoing.rake +91 -0
  28. metadata +28 -45
  29. data/lib/fitting/configuration/legacy.rb +0 -61
  30. data/lib/fitting/configuration/yaml.rb +0 -89
  31. data/lib/fitting/cover/response.rb +0 -37
  32. data/lib/fitting/documentation.rb +0 -56
  33. data/lib/fitting/matchers/response_matcher.rb +0 -96
  34. data/lib/fitting/records/realized_unit.rb +0 -52
  35. data/lib/fitting/records/test_unit/request.rb +0 -98
  36. data/lib/fitting/records/unit/combination.rb +0 -27
  37. data/lib/fitting/records/unit/json_schema.rb +0 -111
  38. data/lib/fitting/records/unit/request.rb +0 -37
  39. data/lib/fitting/records/unit/response.rb +0 -32
  40. data/lib/fitting/request.rb +0 -38
  41. data/lib/fitting/response/fully_validates.rb +0 -34
  42. data/lib/fitting/response.rb +0 -88
  43. data/lib/fitting/statistics/analysis.rb +0 -25
  44. data/lib/fitting/statistics/cover_error.rb +0 -29
  45. data/lib/fitting/statistics/cover_error_enum.rb +0 -29
  46. data/lib/fitting/statistics/cover_error_one_of.rb +0 -29
  47. data/lib/fitting/statistics/great.rb +0 -13
  48. data/lib/fitting/statistics/list.rb +0 -55
  49. data/lib/fitting/statistics/lists.rb +0 -53
  50. data/lib/fitting/statistics/measurement.rb +0 -92
  51. data/lib/fitting/statistics/measurement_cover.rb +0 -92
  52. data/lib/fitting/statistics/measurement_cover_enum.rb +0 -92
  53. data/lib/fitting/statistics/measurement_cover_one_of.rb +0 -92
  54. data/lib/fitting/statistics/not_covered_responses.rb +0 -13
  55. data/lib/fitting/statistics/percent.rb +0 -20
  56. data/lib/fitting/statistics/requests_stats.rb +0 -40
  57. data/lib/fitting/statistics/responses_stats.rb +0 -32
  58. data/lib/fitting/statistics/template.rb +0 -117
  59. data/lib/fitting/statistics/template_cover_error.rb +0 -50
  60. data/lib/fitting/statistics/template_cover_error_enum.rb +0 -50
  61. data/lib/fitting/statistics/template_cover_error_one_of.rb +0 -50
  62. data/lib/fitting/statistics.rb +0 -25
  63. data/lib/fitting/storage/white_list.rb +0 -158
  64. data/lib/fitting/templates/realized_template.rb +0 -49
  65. data/lib/fitting/view/report.html.haml +0 -16
  66. 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, test_title = '')
13
- @tested_requests.push(Fitting::Records::Tested::Request.new(env_response, test_title))
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.0'.freeze
2
+ VERSION = '3.0.0'.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
13
+ def configuration
14
+ yaml = YAML.safe_load(File.read('.fitting.yml'))
15
+ @configuration ||= Configuration.new(yaml)
16
+ end
17
+
10
18
  def configure
11
- yield configuration
19
+ yield(configuration)
12
20
  end
13
21
 
14
- def configuration
15
- @configuration ||= Configuration.craft
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
16
25
  end
17
26
 
18
- def statistics
27
+ def save_test_data
28
+ clear_tests_directory
29
+
30
+ outgoing_responses = Fitting::Storage::Responses.new
19
31
  responses = Fitting::Storage::Responses.new
20
32
 
21
33
  RSpec.configure do |config|
22
- config.after(:each, type: :controller) do
23
- responses.add(response, inspect)
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
24
47
  end
25
48
 
26
- config.after(:suite) do
27
- responses.statistics.save
49
+ config.after(:each, type: :request) do |example|
50
+ responses.add(response, example)
28
51
  end
29
- end
30
- end
31
52
 
32
- extend Gem::Deprecate
33
- deprecate :statistics, :save_test_data, 2022, 1
34
-
35
- def save_test_data
36
- responses = Fitting::Storage::Responses.new
37
-
38
- FileUtils.rm_r Dir.glob('fitting_tests/*'), force: true
39
-
40
- RSpec.configure do |config|
41
- config.after(:each, type: :request) do
42
- responses.add(response, inspect)
53
+ config.after(:each, type: :controller) do |example|
54
+ responses.add(response, example)
43
55
  end
44
56
 
45
- config.after(:each, type: :controller) do
46
- responses.add(response, inspect)
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.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