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
@@ -1,111 +0,0 @@
1
- require 'json-schema'
2
- require 'fitting/cover/json_schema'
3
- require 'fitting/cover/json_schema_enum'
4
- require 'fitting/cover/json_schema_one_of'
5
- require 'fitting/records/unit/combination'
6
-
7
- module Fitting
8
- class Records
9
- class Unit
10
- class JsonSchema
11
- attr_reader :json_schema
12
-
13
- def initialize(json_schema, tested_bodies)
14
- @json_schema = json_schema
15
- @tested_bodies = tested_bodies
16
- end
17
-
18
- def bodies
19
- @bodies ||= @tested_bodies.inject([]) do |res, tested_body|
20
- next res unless JSON::Validator.validate(@json_schema, tested_body)
21
-
22
- res.push(tested_body)
23
- rescue JSON::Schema::UriError
24
- res.push(tested_body)
25
- end
26
- end
27
-
28
- def combinations
29
- return @combinations if @combinations
30
-
31
- @combinations = []
32
- cover_json_schema = Fitting::Cover::JSONSchema.new(@json_schema)
33
- cover_json_schema.combi.map do |comb|
34
- @combinations.push(Fitting::Records::Unit::Combination.new(
35
- comb,
36
- bodies
37
- ))
38
- end
39
- @combinations
40
- end
41
-
42
- def combinations_with_enum
43
- return @combinations_with_enum if @combinations_with_enum
44
-
45
- @combinations_with_enum = []
46
- qwe = Fitting::Cover::JSONSchema.new(@json_schema).combi +
47
- Fitting::Cover::JSONSchemaEnum.new(@json_schema).combi
48
- qwe.map do |comb|
49
- @combinations_with_enum.push(Fitting::Records::Unit::Combination.new(
50
- comb,
51
- bodies
52
- ))
53
- end
54
- @combinations_with_enum
55
- end
56
-
57
- def combinations_with_one_of
58
- return @combinations_with_one_of if @combinations_with_one_of
59
-
60
- @combinations_with_one_of = []
61
- qwe = Fitting::Cover::JSONSchema.new(@json_schema).combi +
62
- Fitting::Cover::JSONSchemaEnum.new(@json_schema).combi +
63
- Fitting::Cover::JSONSchemaOneOf.new(@json_schema).combi
64
- qwe.map do |comb|
65
- @combinations_with_one_of.push(Fitting::Records::Unit::Combination.new(
66
- comb,
67
- bodies
68
- ))
69
- end
70
- @combinations_with_one_of
71
- end
72
-
73
- def cover
74
- @cover ||= if bodies == []
75
- 0
76
- else
77
- count = 0
78
- combinations.map do |combination|
79
- count += 1 unless combination.valid_bodies == []
80
- end
81
- (count + 1) * 100 / (combinations.size + 1)
82
- end
83
- end
84
-
85
- def cover_enum
86
- @cover_enum ||= if bodies == []
87
- 0
88
- else
89
- count = 0
90
- combinations_with_enum.map do |combination|
91
- count += 1 unless combination.valid_bodies == []
92
- end
93
- (count + 1) * 100 / (combinations_with_enum.size + 1)
94
- end
95
- end
96
-
97
- def cover_one_of
98
- @cover_one_of ||= if bodies == []
99
- 0
100
- else
101
- count = 0
102
- combinations_with_one_of.map do |combination|
103
- count += 1 unless combination.valid_bodies == []
104
- end
105
- (count + 1) * 100 / (combinations_with_one_of.size + 1)
106
- end
107
- end
108
- end
109
- end
110
- end
111
- end
@@ -1,37 +0,0 @@
1
- require 'fitting/records/unit/response'
2
-
3
- module Fitting
4
- class Records
5
- class Unit
6
- class Request
7
- def initialize(documented_request, tested_requests)
8
- @documented_request = documented_request
9
- @tested_requests = tested_requests
10
- end
11
-
12
- def path
13
- @path ||= @documented_request.path
14
- end
15
-
16
- def method
17
- @method ||= @documented_request.method
18
- end
19
-
20
- def responses
21
- @responses ||= @documented_request.responses.to_a.inject([]) do |res, documented_response|
22
- res.push(Fitting::Records::Unit::Response.new(documented_response, tested_responses))
23
- end
24
- end
25
-
26
- def tested_responses
27
- @tested_responses ||= @tested_requests.to_a.inject([]) do |res, tested_request|
28
- next res unless @documented_request.method == tested_request.method &&
29
- @documented_request.path.match(tested_request.path.to_s)
30
-
31
- res.push(tested_request.response)
32
- end
33
- end
34
- end
35
- end
36
- end
37
- end
@@ -1,32 +0,0 @@
1
- require 'fitting/records/unit/json_schema'
2
-
3
- module Fitting
4
- class Records
5
- class Unit
6
- class Response
7
- def initialize(documented_response, tested_responses)
8
- @documented_response = documented_response
9
- @tested_responses = tested_responses
10
- end
11
-
12
- def status
13
- @status ||= @documented_response['status']
14
- end
15
-
16
- def json_schemas
17
- @json_schemas ||= @documented_response['json_schemas'].inject([]) do |res, documented_json_schema|
18
- res.push(Fitting::Records::Unit::JsonSchema.new(documented_json_schema, tested_bodies))
19
- end
20
- end
21
-
22
- def tested_bodies
23
- @tested_bodies ||= @tested_responses.inject([]) do |res, tested_response|
24
- next res unless status == tested_response.status.to_s
25
-
26
- res.push(tested_response.body)
27
- end
28
- end
29
- end
30
- end
31
- end
32
- end
@@ -1,38 +0,0 @@
1
- require 'json-schema'
2
-
3
- module Fitting
4
- class Request
5
- def initialize(env_request, tomogram)
6
- @method = env_request.request_method
7
- @path = env_request.env['PATH_INFO'] || env_request.fullpath
8
- @body = env_request.env['action_dispatch.request.request_parameters']
9
- @schema = tomogram.find_request(method: @method, path: @path)
10
- end
11
-
12
- def route
13
- "#{@schema.method}\t#{@schema.path}"
14
- end
15
-
16
- def real_method_with_path
17
- "#{@method}\t#{@path}"
18
- end
19
-
20
- def schemas_of_possible_responses(status:)
21
- return nil unless @schema
22
-
23
- @schema.find_responses(status: status).map do |response|
24
- response['body']
25
- end
26
- end
27
-
28
- def within_prefix?(prefix)
29
- @path.start_with?(prefix)
30
- end
31
-
32
- def ignored?(ignore_list)
33
- ignore_list.any? do |regexp|
34
- regexp.match(@path)
35
- end
36
- end
37
- end
38
- end
@@ -1,34 +0,0 @@
1
- require 'json-schema'
2
-
3
- module Fitting
4
- class Response
5
- class FullyValidates < Array
6
- def self.craft(schemas, body, strict)
7
- if schemas
8
- new(schemas.inject([]) do |res, schema|
9
- res.push(fully_validate(schema, body, strict))
10
- end)
11
- else
12
- @valid = false
13
- new
14
- end
15
- end
16
-
17
- def valid?
18
- @valid ||= any? { |fully_validate| fully_validate == [] }
19
- end
20
-
21
- def to_s
22
- @to_s ||= join("\n\n")
23
- end
24
-
25
- class << self
26
- def fully_validate(schema, body, strict)
27
- JSON::Validator.fully_validate(schema, body, strict: strict)
28
- rescue JSON::Schema::UriError
29
- []
30
- end
31
- end
32
- end
33
- end
34
- end
@@ -1,88 +0,0 @@
1
- require 'fitting/request'
2
- require 'fitting/response/fully_validates'
3
- require 'json'
4
-
5
- module Fitting
6
- class Response
7
- attr_reader :body
8
-
9
- def initialize(env_response, tomogram)
10
- @request = Fitting::Request.new(env_response.request, tomogram)
11
- @status = env_response.status
12
- @body = env_response.body
13
- @schemas = @request.schemas_of_possible_responses(status: @status)
14
- end
15
-
16
- def within_prefix?(prefix)
17
- @request.within_prefix?(prefix)
18
- end
19
-
20
- def fully_validates
21
- @fully_validates ||= Fitting::Response::FullyValidates.craft(@schemas, @body, false)
22
- end
23
-
24
- def strict_fully_validates
25
- @strict_fully_validates ||= Fitting::Response::FullyValidates.craft(@schemas, @body, true)
26
- end
27
-
28
- def documented?
29
- @schemas&.present?
30
- end
31
-
32
- def route
33
- index.map do |i|
34
- "#{@request.route} #{@status} #{i}"
35
- end
36
- end
37
-
38
- def strict_route
39
- strict_index.map do |i|
40
- "#{@request.route} #{@status} #{i}"
41
- end
42
- end
43
-
44
- def real_request_with_status
45
- "#{@request.real_method_with_path} #{@status}"
46
- end
47
-
48
- def got
49
- JSON.pretty_generate(JSON.parse(@body))
50
- end
51
-
52
- def expected
53
- @expected ||= @schemas.inject([]) do |res, schema|
54
- res.push(JSON.pretty_generate(schema).to_s)
55
- end.join("\n\n")
56
- end
57
-
58
- def json_schema
59
- @schemas[index.first]
60
- end
61
-
62
- def ignored?(ignore_list)
63
- @request.ignored?(ignore_list)
64
- end
65
-
66
- private
67
-
68
- def index
69
- return @index_res if @index_res
70
-
71
- @index_res = []
72
- @schemas.size.times do |i|
73
- @index_res.push(i) if fully_validates[i] == []
74
- end
75
- @index_res
76
- end
77
-
78
- def strict_index
79
- return @strict_index_res if @strict_index_res
80
-
81
- @strict_index_res = []
82
- @schemas.size.times do |i|
83
- @strict_index_res.push(i) if strict_fully_validates[i] == []
84
- end
85
- @strict_index_res
86
- end
87
- end
88
- end
@@ -1,25 +0,0 @@
1
- require 'fitting/statistics/lists'
2
- require 'fitting/statistics/requests_stats'
3
- require 'fitting/statistics/responses_stats'
4
- require 'fitting/statistics/great'
5
- require 'fitting/statistics/not_covered_responses'
6
-
7
- module Fitting
8
- class Statistics
9
- class Analysis
10
- def initialize(measurement, depth)
11
- @measurement = measurement
12
- @depth = depth
13
- end
14
-
15
- def to_s
16
- [
17
- Fitting::Statistics::Lists.new(@measurement, @depth).to_s,
18
- Fitting::Statistics::RequestsStats.new(@measurement).to_s,
19
- Fitting::Statistics::ResponsesStats.new(@measurement).to_s,
20
- Fitting::Statistics::Great.new(@measurement).to_s
21
- ].compact.join("\n\n")
22
- end
23
- end
24
- end
25
- end
@@ -1,29 +0,0 @@
1
- module Fitting
2
- class Statistics
3
- class CoverError
4
- def initialize(request_unit)
5
- @request_unit = request_unit
6
- end
7
-
8
- def to_s
9
- res = ''
10
- @request_unit.map do |request|
11
- request.responses.map do |response|
12
- next unless response.tested_bodies != []
13
-
14
- response.json_schemas.map do |json_schema|
15
- json_schema.combinations.map do |combination|
16
- next unless combination.valid_bodies == []
17
-
18
- res += "request method: #{request.method}\nrequest path: #{request.path}\n"\
19
- "response status: #{response.status}\nsource json-schema: #{json_schema.json_schema}\n"\
20
- "combination: #{combination.description}\nnew json-schema: #{combination.json_schema}\n\n"
21
- end
22
- end
23
- end
24
- end
25
- res
26
- end
27
- end
28
- end
29
- end
@@ -1,29 +0,0 @@
1
- module Fitting
2
- class Statistics
3
- class CoverErrorEnum
4
- def initialize(request_unit)
5
- @request_unit = request_unit
6
- end
7
-
8
- def to_s
9
- res = ''
10
- @request_unit.map do |request|
11
- request.responses.map do |response|
12
- next unless response.tested_bodies != []
13
-
14
- response.json_schemas.map do |json_schema|
15
- json_schema.combinations_with_enum.map do |combination|
16
- next unless combination.valid_bodies == []
17
-
18
- res += "request method: #{request.method}\nrequest path: #{request.path}\n"\
19
- "response status: #{response.status}\nsource json-schema: #{json_schema.json_schema}\n"\
20
- "combination: #{combination.description}\nnew json-schema: #{combination.json_schema}\n\n"
21
- end
22
- end
23
- end
24
- end
25
- res
26
- end
27
- end
28
- end
29
- end
@@ -1,29 +0,0 @@
1
- module Fitting
2
- class Statistics
3
- class CoverErrorOneOf
4
- def initialize(request_unit)
5
- @request_unit = request_unit
6
- end
7
-
8
- def to_s
9
- res = ''
10
- @request_unit.map do |request|
11
- request.responses.map do |response|
12
- next unless response.tested_bodies != []
13
-
14
- response.json_schemas.map do |json_schema|
15
- json_schema.combinations_with_one_of.map do |combination|
16
- next unless combination.valid_bodies == []
17
-
18
- res += "request method: #{request.method}\nrequest path: #{request.path}\n"\
19
- "response status: #{response.status}\nsource json-schema: #{json_schema.json_schema}\n"\
20
- "combination: #{combination.description}\nnew json-schema: #{combination.json_schema}\n\n"
21
- end
22
- end
23
- end
24
- end
25
- res
26
- end
27
- end
28
- end
29
- end
@@ -1,13 +0,0 @@
1
- module Fitting
2
- class Statistics
3
- class Great
4
- def initialize(measurement)
5
- @measurement = measurement
6
- end
7
-
8
- def to_s
9
- return 'All responses are 100% valid! Great job!' if @measurement.cover_responses == @measurement.all_responses
10
- end
11
- end
12
- end
13
- end
@@ -1,55 +0,0 @@
1
- module Fitting
2
- class Statistics
3
- class List
4
- def initialize(coverage, max_response_path, depth)
5
- @coverage = coverage
6
- @max_response_path = max_response_path
7
- @depth = depth
8
- end
9
-
10
- def to_s
11
- list_sort.inject([]) do |res, request|
12
- res.push("#{request.method}\t#{request.path}#{responses_stat(request)}")
13
- end.join("\n")
14
- end
15
-
16
- def list_sort
17
- @coverage.sort do |first, second|
18
- first.path.to_s <=> second.path.to_s
19
- end
20
- end
21
-
22
- def responses_stat(request)
23
- tab = "\t" * ((@max_response_path - request.path.to_s.size / 8) + 3)
24
- tab + request.responses.to_a.each_with_object([]) do |response, res|
25
- response_stat(response, res)
26
- end.join(' ')
27
- end
28
-
29
- private
30
-
31
- def response_stat(response, res)
32
- response.json_schemas.map do |json_schema|
33
- json_schema_stat(res, json_schema, response)
34
- end
35
- end
36
-
37
- def json_schema_stat(res, json_schema, response)
38
- case @depth
39
- when 'valid'
40
- if json_schema.bodies == []
41
- res.push("✖ #{response.status}")
42
- else
43
- res.push("✔ #{response.status}")
44
- end
45
- when 'cover'
46
- res.push("#{json_schema.cover}% #{response.status}")
47
- when 'cover_enum'
48
- res.push("#{json_schema.cover_enum}% #{response.status}")
49
- when 'cover_one_of'
50
- res.push("#{json_schema.cover_one_of}% #{response.status}")
51
- end
52
- end
53
- end
54
- end
55
- end
@@ -1,53 +0,0 @@
1
- require 'fitting/statistics/list'
2
-
3
- module Fitting
4
- class Statistics
5
- class Lists
6
- def initialize(measurement, depth)
7
- @measurement = measurement
8
- @depth = depth
9
- end
10
-
11
- def to_s
12
- [
13
- coverage_fully_stat,
14
- coverage_partially_stat,
15
- coverage_non_stat
16
- ].compact.join("\n\n")
17
- end
18
-
19
- def coverage_fully_stat
20
- if @measurement.coverage_fully == []
21
- nil
22
- else
23
- [
24
- 'Fully conforming requests:',
25
- Fitting::Statistics::List.new(@measurement.coverage_fully, @measurement.max_response_path, @depth).to_s
26
- ].join("\n")
27
- end
28
- end
29
-
30
- def coverage_partially_stat
31
- if @measurement.coverage_partially == []
32
- nil
33
- else
34
- [
35
- 'Partially conforming requests:',
36
- Fitting::Statistics::List.new(@measurement.coverage_partially, @measurement.max_response_path, @depth).to_s
37
- ].join("\n")
38
- end
39
- end
40
-
41
- def coverage_non_stat
42
- if @measurement.coverage_non == []
43
- nil
44
- else
45
- [
46
- 'Non-conforming requests:',
47
- Fitting::Statistics::List.new(@measurement.coverage_non, @measurement.max_response_path, @depth).to_s
48
- ].join("\n")
49
- end
50
- end
51
- end
52
- end
53
- end
@@ -1,92 +0,0 @@
1
- module Fitting
2
- class Statistics
3
- class Measurement
4
- attr_reader :requests, :all_responses, :cover_responses, :not_cover_responses, :max_response_path,
5
- :coverage_fully, :coverage_non, :coverage_partially, :not_covered_responses
6
-
7
- def initialize(requests)
8
- @requests = requests
9
- @all_responses = 0
10
- @cover_responses = 0
11
- @not_cover_responses = 0
12
- @max_response_path = 0
13
- @coverage_fully = []
14
- @coverage_non = []
15
- @coverage_partially = []
16
- @not_covered_responses = []
17
- check_responses
18
- end
19
-
20
- def check_responses
21
- return if @ready
22
-
23
- @requests.map do |request|
24
- chech_request(request)
25
- end
26
-
27
- @ready = true
28
- end
29
-
30
- private
31
-
32
- def chech_request(request)
33
- check_cover(request)
34
- coverage_push(request)
35
-
36
- @max_response_path = request.path.to_s.size / 8 if request.path.to_s.size / 8 > @max_response_path
37
- request.responses.map do |response|
38
- check_response(response, request)
39
- end
40
- end
41
-
42
- def check_response(response, request)
43
- json_schema_index = 0
44
- response.json_schemas.map do |json_schema|
45
- json_schema_index = check_json_schema(json_schema, request, response, json_schema_index)
46
- end
47
- end
48
-
49
- def check_json_schema(json_schema, request, response, json_schema_index)
50
- if json_schema.bodies == []
51
- @not_cover_responses += 1
52
- @not_covered_responses.push("#{request.method}\t#{request.path} #{response.status} #{json_schema_index}")
53
- else
54
- @cover_responses += 1
55
- end
56
- @all_responses += 1
57
- json_schema_index + 1
58
- end
59
-
60
- def coverage_push(request)
61
- if @all == @cover
62
- @coverage_fully.push(request)
63
- elsif @all == @not_cover
64
- @coverage_non.push(request)
65
- else
66
- @coverage_partially.push(request)
67
- end
68
- end
69
-
70
- def check_cover(request)
71
- @all = 0
72
- @cover = 0
73
- @not_cover = 0
74
-
75
- request.responses.map do |response|
76
- response.json_schemas.map do |json_schema|
77
- count_cover(json_schema)
78
- end
79
- end
80
- end
81
-
82
- def count_cover(json_schema)
83
- @all += 1
84
- if json_schema.bodies == []
85
- @not_cover += 1
86
- else
87
- @cover += 1
88
- end
89
- end
90
- end
91
- end
92
- end