fitting 2.18.1 → 3.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -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