fitting 0.4.2 → 1.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.
- checksums.yaml +4 -4
- data/.gitignore +0 -2
- data/README.md +14 -31
- data/lib/fitting.rb +29 -1
- data/lib/fitting/configuration.rb +1 -10
- data/lib/fitting/documentation/request/route.rb +57 -0
- data/lib/fitting/documentation/response/route.rb +51 -0
- data/lib/fitting/matchers/response_matcher.rb +40 -0
- data/lib/fitting/report/response.rb +18 -0
- data/lib/fitting/request.rb +15 -18
- data/lib/fitting/response.rb +44 -23
- data/lib/fitting/storage/documentation.rb +17 -0
- data/lib/fitting/storage/responses.rb +21 -0
- data/lib/fitting/version.rb +1 -1
- metadata +8 -9
- data/lib/fitting/documentation.rb +0 -42
- data/lib/fitting/formatter/response/macro_yaml.rb +0 -36
- data/lib/fitting/formatter/response/micro_yaml.rb +0 -36
- data/lib/fitting/report/response/macro.rb +0 -89
- data/lib/fitting/report/response/micro.rb +0 -76
- data/lib/fitting/storage/json_file.rb +0 -37
- data/lib/fitting/storage/yaml_file.rb +0 -37
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3fd051bc55d0a84202300a746cb5c75041440924
|
4
|
+
data.tar.gz: a6be0e42f772ea7dd5505dc46a0eee5b68b90c29
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2fe0cb6d71f87702f48a83573732f515aa673d616e32f92b479144129423129aca0bb9bbfca65672fa55f9cc695e58fdeea07e038af99a88db70e0fa2706ec77
|
7
|
+
data.tar.gz: 6f5bdefbe659626a84a41b7682fe0edfb90a7dbb7f3768e7ad55d36787d53e2fa4e422544538b2f186e2e1235c909ae263f751ac055c147c56d24b490ee774a1
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -24,34 +24,11 @@ Or install it yourself as:
|
|
24
24
|
|
25
25
|
## Usage
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
rails_helper.rb
|
27
|
+
In your `spec_helper.rb`:
|
30
28
|
|
31
29
|
```ruby
|
32
|
-
|
33
|
-
config.after(:each, :type => :controller) do
|
34
|
-
Fitting::Documentation.try_on(self, request, response)
|
35
|
-
end
|
36
|
-
```
|
37
|
-
|
38
|
-
### Formatting
|
39
|
-
|
40
|
-
```
|
41
|
-
bundle exec rspec --format Fitting::Formatter::Response::MacroYaml
|
42
|
-
```
|
43
|
-
|
44
|
-
or
|
45
|
-
|
30
|
+
config.include JSON::SchemaMatchers
|
46
31
|
```
|
47
|
-
bundle exec rspec --format Fitting::Formatter::Response::MicroYaml
|
48
|
-
```
|
49
|
-
|
50
|
-
After that you can find the report in `report_response_macro.yaml` or `report_response_micro.yaml`.
|
51
|
-
|
52
|
-
## Config
|
53
|
-
|
54
|
-
### tomogram
|
55
32
|
|
56
33
|
This gem takes a simplified format json convert from API Blueprint which we have called API Tomogram.
|
57
34
|
|
@@ -64,17 +41,23 @@ Use gem [tomograph](https://github.com/funbox/tomograph)
|
|
64
41
|
|
65
42
|
```
|
66
43
|
|
67
|
-
|
44
|
+
You can then write tests such as:
|
68
45
|
|
69
|
-
|
46
|
+
```ruby
|
47
|
+
expect(response).to match_response
|
48
|
+
```
|
70
49
|
|
71
|
-
|
50
|
+
If you want check all tests:
|
72
51
|
|
73
|
-
|
52
|
+
```ruby
|
53
|
+
config.after(:each, :type => :controller) do
|
54
|
+
expect(response).to match_response
|
55
|
+
end
|
56
|
+
```
|
74
57
|
|
75
|
-
|
58
|
+
## Report
|
76
59
|
|
77
|
-
|
60
|
+
Autogenerate `report_request_by_response.yaml` and `report_response.yaml reports`.
|
78
61
|
|
79
62
|
## Contributing
|
80
63
|
|
data/lib/fitting.rb
CHANGED
@@ -1,6 +1,11 @@
|
|
1
1
|
require 'fitting/version'
|
2
|
-
require 'fitting/documentation'
|
3
2
|
require 'fitting/configuration'
|
3
|
+
require 'fitting/documentation/response/route'
|
4
|
+
require 'fitting/documentation/request/route'
|
5
|
+
require 'fitting/storage/responses'
|
6
|
+
require 'fitting/storage/documentation'
|
7
|
+
require 'fitting/report/response'
|
8
|
+
require 'fitting/matchers/response_matcher'
|
4
9
|
|
5
10
|
module Fitting
|
6
11
|
class << self
|
@@ -13,3 +18,26 @@ module Fitting
|
|
13
18
|
end
|
14
19
|
end
|
15
20
|
end
|
21
|
+
|
22
|
+
module RSpec
|
23
|
+
module Core
|
24
|
+
# Provides the main entry point to run a suite of RSpec examples.
|
25
|
+
class Runner
|
26
|
+
alias origin_run_specs run_specs
|
27
|
+
|
28
|
+
def run_specs(example_groups)
|
29
|
+
origin_run_specs(example_groups)
|
30
|
+
return if Fitting::Storage::Responses.nil?
|
31
|
+
|
32
|
+
response_routes = Fitting::Documentation::Response::Route.new(
|
33
|
+
Fitting::Storage::Documentation.hash,
|
34
|
+
Fitting::Storage::Responses.all
|
35
|
+
)
|
36
|
+
request_routes = Fitting::Documentation::Request::Route.new(response_routes)
|
37
|
+
puts "Coverage documentation API (responses) by RSpec tests: #{response_routes.cover_ratio}%"
|
38
|
+
Fitting::Report::Response.new('report_response.yaml', response_routes).save
|
39
|
+
Fitting::Report::Response.new('report_request_by_response.yaml', request_routes).save
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -1,14 +1,5 @@
|
|
1
1
|
module Fitting
|
2
2
|
class Configuration
|
3
|
-
attr_accessor :tomogram
|
4
|
-
:skip_not_documented,
|
5
|
-
:validation_requests,
|
6
|
-
:validation_response
|
7
|
-
|
8
|
-
def initialize
|
9
|
-
@skip_not_documented = true
|
10
|
-
@validation_requests = true
|
11
|
-
@validation_response = true
|
12
|
-
end
|
3
|
+
attr_accessor :tomogram
|
13
4
|
end
|
14
5
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'multi_json'
|
2
|
+
|
3
|
+
module Fitting
|
4
|
+
module Documentation
|
5
|
+
module Request
|
6
|
+
class Route
|
7
|
+
def initialize(response_routes)
|
8
|
+
@response_routes = response_routes
|
9
|
+
end
|
10
|
+
|
11
|
+
def coverage_statistic
|
12
|
+
stat = {}
|
13
|
+
@response_routes.coverage.map do |route|
|
14
|
+
macro_key = route.split(' ')[0..1].join(' ')
|
15
|
+
micro_key = route.split(' ')[2..3].join(' ')
|
16
|
+
stat[macro_key] ||= {}
|
17
|
+
stat[macro_key]['cover'] ||= []
|
18
|
+
stat[macro_key]['not_cover'] ||= []
|
19
|
+
stat[macro_key]['cover'].push(micro_key)
|
20
|
+
end
|
21
|
+
@response_routes.not_coverage.map do |route|
|
22
|
+
macro_key = route.split(' ')[0..1].join(' ')
|
23
|
+
micro_key = route.split(' ')[2..3].join(' ')
|
24
|
+
stat[macro_key] ||= {}
|
25
|
+
stat[macro_key]['cover'] ||= []
|
26
|
+
stat[macro_key]['not_cover'] ||= []
|
27
|
+
stat[macro_key]['not_cover'].push(micro_key)
|
28
|
+
end
|
29
|
+
@stat = stat.inject(
|
30
|
+
{
|
31
|
+
'full cover' => [],
|
32
|
+
'partial cover' => [],
|
33
|
+
'no cover' => []
|
34
|
+
}
|
35
|
+
) do |res, date|
|
36
|
+
ratio = date.last['cover_ratio'] =
|
37
|
+
(date.last['cover'].size.to_f /
|
38
|
+
(date.last['cover'].size + date.last['not_cover'].size).to_f * 100.0).round(2)
|
39
|
+
info = {date.first => {'cover' => date.last['cover'], 'not_cover' => date.last['not_cover']}}
|
40
|
+
if ratio == 100.0
|
41
|
+
res['full cover'].push(info)
|
42
|
+
elsif ratio == 0.0
|
43
|
+
res['no cover'].push(info)
|
44
|
+
else
|
45
|
+
res['partial cover'].push(info)
|
46
|
+
end
|
47
|
+
res
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def to_hash
|
52
|
+
@stat ||= coverage_statistic
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'multi_json'
|
2
|
+
|
3
|
+
module Fitting
|
4
|
+
module Documentation
|
5
|
+
module Response
|
6
|
+
class Route
|
7
|
+
def initialize(tomogram, coverage_responses)
|
8
|
+
@tomogram = tomogram
|
9
|
+
@coverage_responses = coverage_responses
|
10
|
+
end
|
11
|
+
|
12
|
+
def coverage
|
13
|
+
@coverage ||= @coverage_responses.map do |response|
|
14
|
+
response.route if response.documented? && response.valid?
|
15
|
+
end.compact.uniq
|
16
|
+
end
|
17
|
+
|
18
|
+
def not_coverage
|
19
|
+
@not_coverage ||= all - coverage
|
20
|
+
end
|
21
|
+
|
22
|
+
def all
|
23
|
+
@all ||= MultiJson.load(@tomogram).inject([]) do |routes, request|
|
24
|
+
request['responses'].inject({}) do |responses, response|
|
25
|
+
responses[response['status']] ||= 0
|
26
|
+
responses[response['status']] += 1
|
27
|
+
responses
|
28
|
+
end.map do |status, indexes|
|
29
|
+
indexes.times do |index|
|
30
|
+
route = "#{request['method']} #{request['path']} #{status} #{index}"
|
31
|
+
routes.push(route)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
routes
|
35
|
+
end.uniq
|
36
|
+
end
|
37
|
+
|
38
|
+
def cover_ratio
|
39
|
+
@cover_ratio ||= (coverage.size.to_f / all.size.to_f * 100.0).round(2)
|
40
|
+
end
|
41
|
+
|
42
|
+
def to_hash
|
43
|
+
{
|
44
|
+
'coverage' => coverage,
|
45
|
+
'not coverage' => not_coverage
|
46
|
+
}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'fitting/response'
|
2
|
+
require 'fitting/storage/responses'
|
3
|
+
require 'fitting/storage/documentation'
|
4
|
+
|
5
|
+
module Fitting
|
6
|
+
module Matchers
|
7
|
+
class Response
|
8
|
+
def matches?(response)
|
9
|
+
@response = Fitting::Response.new(
|
10
|
+
response,
|
11
|
+
Fitting::Storage::Documentation.tomogram
|
12
|
+
)
|
13
|
+
Fitting::Storage::Responses.push(@response)
|
14
|
+
@response.valid?
|
15
|
+
end
|
16
|
+
|
17
|
+
def ===(other)
|
18
|
+
matches?(other)
|
19
|
+
end
|
20
|
+
|
21
|
+
def failure_message
|
22
|
+
unless @response.documented?
|
23
|
+
return "response not documented\n"\
|
24
|
+
"got: #{@response.real_request_with_status}"
|
25
|
+
end
|
26
|
+
|
27
|
+
unless @response.valid?
|
28
|
+
"response not valid json-schema\n"\
|
29
|
+
"got: #{@response.got}\n"\
|
30
|
+
"diff: \n#{@response.diff}"\
|
31
|
+
"expected: \n#{@response.expected}\n"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def match_response
|
37
|
+
Response.new
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Fitting
|
4
|
+
module Report
|
5
|
+
class Response
|
6
|
+
def initialize(name, routes)
|
7
|
+
@name = name
|
8
|
+
@json = routes.to_hash
|
9
|
+
end
|
10
|
+
|
11
|
+
def save
|
12
|
+
File.open(@name, 'w') do |file|
|
13
|
+
file.write(YAML.dump(@json))
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/fitting/request.rb
CHANGED
@@ -1,35 +1,32 @@
|
|
1
|
+
require 'json-schema'
|
2
|
+
|
1
3
|
module Fitting
|
2
4
|
class Request
|
3
|
-
attr_accessor :path, :method, :body, :schema
|
4
|
-
|
5
|
-
class Unsuitable < RuntimeError; end
|
6
|
-
class NotDocumented < RuntimeError; end
|
7
|
-
|
8
5
|
def initialize(env_request, tomogram)
|
9
6
|
@method = env_request.request_method
|
10
7
|
@path = env_request.env['PATH_INFO']
|
11
8
|
@body = env_request.env['action_dispatch.request.request_parameters']
|
12
9
|
@schema = tomogram.find_request(method: @method, path: @path)
|
13
|
-
|
10
|
+
@fully_validate = JSON::Validator.fully_validate(@schema['request'], @body) if @schema
|
11
|
+
@valid = false
|
12
|
+
@valid = true if @fully_validate == []
|
14
13
|
self
|
15
14
|
end
|
16
15
|
|
17
|
-
def
|
18
|
-
|
19
|
-
raise Unsuitable unless res.empty?
|
16
|
+
def route
|
17
|
+
"#{@schema['method']} #{@schema['path']}"
|
20
18
|
end
|
21
19
|
|
22
|
-
def
|
23
|
-
@
|
20
|
+
def real_method_with_path
|
21
|
+
"#{@method} #{@path}"
|
24
22
|
end
|
25
23
|
|
26
|
-
def
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
}
|
24
|
+
def schemas_of_possible_responses(status:)
|
25
|
+
if @schema
|
26
|
+
@schema.find_responses(status: status).map do |response|
|
27
|
+
response['body']
|
28
|
+
end
|
29
|
+
end
|
33
30
|
end
|
34
31
|
end
|
35
32
|
end
|
data/lib/fitting/response.rb
CHANGED
@@ -1,21 +1,14 @@
|
|
1
|
+
require 'fitting/request'
|
2
|
+
require 'json-schema'
|
3
|
+
|
1
4
|
module Fitting
|
2
5
|
class Response
|
3
|
-
|
4
|
-
|
5
|
-
class Unsuitable < RuntimeError; end
|
6
|
-
class NotDocumented < RuntimeError; end
|
7
|
-
|
8
|
-
def initialize(env_response, expect_request)
|
6
|
+
def initialize(env_response, tomogram)
|
7
|
+
@request = Request.new(env_response.request, tomogram)
|
9
8
|
@status = env_response.status
|
10
9
|
@body = env_response.body
|
11
|
-
@schemas =
|
10
|
+
@schemas = @request.schemas_of_possible_responses(status: @status)
|
12
11
|
@fully_validates = set_fully_validate if @schemas
|
13
|
-
raise Response::NotDocumented unless (@schemas && @schemas.first) || Fitting.configuration.skip_not_documented
|
14
|
-
self
|
15
|
-
end
|
16
|
-
|
17
|
-
def valid!
|
18
|
-
raise Unsuitable unless @valid
|
19
12
|
end
|
20
13
|
|
21
14
|
def set_fully_validate
|
@@ -29,18 +22,46 @@ module Fitting
|
|
29
22
|
fully_validates
|
30
23
|
end
|
31
24
|
|
32
|
-
def
|
33
|
-
@schemas && @schemas.
|
25
|
+
def documented?
|
26
|
+
@schemas && @schemas.present?
|
27
|
+
end
|
28
|
+
|
29
|
+
def valid?
|
30
|
+
@valid == true
|
31
|
+
end
|
32
|
+
|
33
|
+
def route
|
34
|
+
"#{@request.route} #{@status} #{index}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def real_request_with_status
|
38
|
+
"#{@request.real_method_with_path} #{@status}"
|
34
39
|
end
|
35
40
|
|
36
|
-
def
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
41
|
+
def got
|
42
|
+
@body
|
43
|
+
end
|
44
|
+
|
45
|
+
def diff
|
46
|
+
@fully_validates.inject("") do |res, fully_validate|
|
47
|
+
res + "#{fully_validate}\n"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def expected
|
52
|
+
@schemas.inject("") do |res, schema|
|
53
|
+
res + "#{schema}\n"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def index
|
60
|
+
@schemas.size.times do |i|
|
61
|
+
if @fully_validates[i] == []
|
62
|
+
return i
|
63
|
+
end
|
64
|
+
end
|
44
65
|
end
|
45
66
|
end
|
46
67
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'tomogram_routing'
|
2
|
+
|
3
|
+
module Fitting
|
4
|
+
module Storage
|
5
|
+
module Documentation
|
6
|
+
class << self
|
7
|
+
def tomogram
|
8
|
+
@tomogram ||= TomogramRouting::Tomogram.craft(hash)
|
9
|
+
end
|
10
|
+
|
11
|
+
def hash
|
12
|
+
Fitting.configuration.tomogram
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Fitting
|
2
|
+
module Storage
|
3
|
+
module Responses
|
4
|
+
class << self
|
5
|
+
def push(test)
|
6
|
+
@responses ||= []
|
7
|
+
@responses.push(test)
|
8
|
+
end
|
9
|
+
|
10
|
+
def all
|
11
|
+
@responses ||= []
|
12
|
+
@responses.uniq
|
13
|
+
end
|
14
|
+
|
15
|
+
def nil?
|
16
|
+
@responses.nil?
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/fitting/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fitting
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- d.efimov
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-03-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json-schema
|
@@ -192,15 +192,14 @@ files:
|
|
192
192
|
- fitting.gemspec
|
193
193
|
- lib/fitting.rb
|
194
194
|
- lib/fitting/configuration.rb
|
195
|
-
- lib/fitting/documentation.rb
|
196
|
-
- lib/fitting/
|
197
|
-
- lib/fitting/
|
198
|
-
- lib/fitting/report/response
|
199
|
-
- lib/fitting/report/response/micro.rb
|
195
|
+
- lib/fitting/documentation/request/route.rb
|
196
|
+
- lib/fitting/documentation/response/route.rb
|
197
|
+
- lib/fitting/matchers/response_matcher.rb
|
198
|
+
- lib/fitting/report/response.rb
|
200
199
|
- lib/fitting/request.rb
|
201
200
|
- lib/fitting/response.rb
|
202
|
-
- lib/fitting/storage/
|
203
|
-
- lib/fitting/storage/
|
201
|
+
- lib/fitting/storage/documentation.rb
|
202
|
+
- lib/fitting/storage/responses.rb
|
204
203
|
- lib/fitting/version.rb
|
205
204
|
homepage: https://github.com/funbox/fitting
|
206
205
|
licenses:
|
@@ -1,42 +0,0 @@
|
|
1
|
-
require 'tomogram_routing'
|
2
|
-
require 'json-schema'
|
3
|
-
require 'fitting/storage/yaml_file'
|
4
|
-
require 'fitting/request'
|
5
|
-
require 'fitting/response'
|
6
|
-
|
7
|
-
module Fitting
|
8
|
-
class Documentation
|
9
|
-
class << self
|
10
|
-
def try_on(date, env_request, env_response)
|
11
|
-
request = Request.new(env_request, tomogram)
|
12
|
-
request.valid! if request.validate?
|
13
|
-
response = Response.new(env_response, request.schema)
|
14
|
-
response.valid! if response.validate?
|
15
|
-
add_storage(location(date), request, response)
|
16
|
-
end
|
17
|
-
|
18
|
-
private
|
19
|
-
|
20
|
-
def add_storage(location, request, response)
|
21
|
-
Fitting::Storage::YamlFile.push(
|
22
|
-
location,
|
23
|
-
'request' => MultiJson.dump(request.to_hash),
|
24
|
-
'response' => MultiJson.dump(response.to_hash)
|
25
|
-
)
|
26
|
-
end
|
27
|
-
|
28
|
-
def tomogram
|
29
|
-
@tomogram ||= TomogramRouting::Tomogram.craft(Fitting.configuration.tomogram)
|
30
|
-
end
|
31
|
-
|
32
|
-
def location(date)
|
33
|
-
name = date.inspect.to_s
|
34
|
-
if name.split('(').size > 1
|
35
|
-
name.split('(').last.split(')').first[2..-1]
|
36
|
-
else
|
37
|
-
name.split(' ')[3][2..-3]
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
@@ -1,36 +0,0 @@
|
|
1
|
-
require 'rspec/core/formatters/base_formatter'
|
2
|
-
require 'yaml'
|
3
|
-
require 'fitting/storage/yaml_file'
|
4
|
-
require 'fitting/report/response/macro'
|
5
|
-
|
6
|
-
module Fitting
|
7
|
-
module Formatter
|
8
|
-
module Response
|
9
|
-
class MacroYaml < RSpec::Core::Formatters::BaseFormatter
|
10
|
-
RSpec::Core::Formatters.register self, :start, :stop
|
11
|
-
|
12
|
-
def start(_notification)
|
13
|
-
Fitting::Storage::YamlFile.craft
|
14
|
-
end
|
15
|
-
|
16
|
-
def stop(_notification)
|
17
|
-
tests = Fitting::Storage::YamlFile.load
|
18
|
-
Fitting::Storage::YamlFile.destroy
|
19
|
-
|
20
|
-
if tests
|
21
|
-
report = Report::Response::Macro.new(tests).to_hash
|
22
|
-
else
|
23
|
-
report = 'no tests controllers'
|
24
|
-
end
|
25
|
-
craft_json(report)
|
26
|
-
end
|
27
|
-
|
28
|
-
def craft_json(report)
|
29
|
-
File.open('report_response_macro.yaml', 'w') do |file|
|
30
|
-
file.write(YAML.dump(report))
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
@@ -1,36 +0,0 @@
|
|
1
|
-
require 'rspec/core/formatters/base_formatter'
|
2
|
-
require 'yaml'
|
3
|
-
require 'fitting/storage/yaml_file'
|
4
|
-
require 'fitting/report/response/micro'
|
5
|
-
|
6
|
-
module Fitting
|
7
|
-
module Formatter
|
8
|
-
module Response
|
9
|
-
class MicroYaml < RSpec::Core::Formatters::BaseFormatter
|
10
|
-
RSpec::Core::Formatters.register self, :start, :stop
|
11
|
-
|
12
|
-
def start(_notification)
|
13
|
-
Fitting::Storage::YamlFile.craft
|
14
|
-
end
|
15
|
-
|
16
|
-
def stop(_notification)
|
17
|
-
tests = Fitting::Storage::YamlFile.load
|
18
|
-
Fitting::Storage::YamlFile.destroy
|
19
|
-
|
20
|
-
if tests
|
21
|
-
report = Report::Response::Micro.new(tests).to_hash
|
22
|
-
else
|
23
|
-
report = 'no tests controllers'
|
24
|
-
end
|
25
|
-
craft_json(report)
|
26
|
-
end
|
27
|
-
|
28
|
-
def craft_json(report)
|
29
|
-
File.open('report_response_micro.yaml', 'w') do |file|
|
30
|
-
file.write(YAML.dump(report))
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
@@ -1,89 +0,0 @@
|
|
1
|
-
module Fitting
|
2
|
-
module Report
|
3
|
-
module Response
|
4
|
-
class Macro
|
5
|
-
def initialize(tests)
|
6
|
-
@json = responses(tests)
|
7
|
-
end
|
8
|
-
|
9
|
-
def responses(tests)
|
10
|
-
data = {
|
11
|
-
'not_documented' => {},
|
12
|
-
'invalid' => {},
|
13
|
-
'valid' => {}
|
14
|
-
}
|
15
|
-
full_responses = {}
|
16
|
-
|
17
|
-
tests.map do |location, test|
|
18
|
-
request = MultiJson.load(test['request'])
|
19
|
-
response = MultiJson.load(test['response'])
|
20
|
-
if request['schema'].nil?
|
21
|
-
data['not_documented'][response_key(request, response)] = [location]
|
22
|
-
else
|
23
|
-
if response['schemas'].nil?
|
24
|
-
data['not_documented'][response_key(request['schema'], response)] = [location]
|
25
|
-
else
|
26
|
-
responses_documented(location, response['valid'], data, response_key(request['schema'], response), full_responses, response)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
not_cover = {}
|
32
|
-
full_responses.map do |response, date|
|
33
|
-
date['cases'].map do |one_case|
|
34
|
-
if not_cover["#{response} #{one_case}"]
|
35
|
-
not_cover["#{response} #{one_case}"] = not_cover["#{response} #{one_case}"] + [date['test']]
|
36
|
-
else
|
37
|
-
not_cover["#{response} #{one_case}"] = [date['test']]
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
data['not_cover_where_either'] = not_cover
|
42
|
-
data
|
43
|
-
end
|
44
|
-
|
45
|
-
def responses_documented(location, valid, data, name, full_responses, response)
|
46
|
-
if valid
|
47
|
-
unless full_responses[name]
|
48
|
-
full_responses[name] = {}
|
49
|
-
full_responses[name]['cases'] = (0..response['schemas'].size-1).to_a
|
50
|
-
end
|
51
|
-
full_responses[name]['test'] = location
|
52
|
-
full_responses[name]['cases'].delete(find_index(response))
|
53
|
-
push('valid', data, "#{name} #{find_index(response)}", location)
|
54
|
-
else
|
55
|
-
push('invalid', data, name, location)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def find_index(response)
|
60
|
-
response['schemas'].size.times do |i|
|
61
|
-
if response['fully_validates'][i] == []
|
62
|
-
return i
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
def push(key, data, name, location)
|
68
|
-
data[key] = if data[key][name]
|
69
|
-
data[key].merge(name => data[key][name] + [location])
|
70
|
-
else
|
71
|
-
data[key].merge(name => [location])
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
def request_key(request_data)
|
76
|
-
"#{request_data['method']} #{request_data['path']}"
|
77
|
-
end
|
78
|
-
|
79
|
-
def response_key(request_data, response_data)
|
80
|
-
"#{request_key(request_data)} #{response_data['status']}"
|
81
|
-
end
|
82
|
-
|
83
|
-
def to_hash
|
84
|
-
@json
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
@@ -1,76 +0,0 @@
|
|
1
|
-
require 'multi_json'
|
2
|
-
|
3
|
-
module Fitting
|
4
|
-
module Report
|
5
|
-
module Response
|
6
|
-
class Micro
|
7
|
-
def initialize(tests)
|
8
|
-
@json = responses(tests)
|
9
|
-
end
|
10
|
-
|
11
|
-
def responses(tests)
|
12
|
-
data = {}
|
13
|
-
|
14
|
-
tests.map do |location, test|
|
15
|
-
request = MultiJson.load(test['request'])
|
16
|
-
response = MultiJson.load(test['response'])
|
17
|
-
if request['schema'].nil?
|
18
|
-
data[location] = {
|
19
|
-
'status' => 'not_documented',
|
20
|
-
'got' => response['body']
|
21
|
-
}
|
22
|
-
else
|
23
|
-
if response['schemas'].nil?
|
24
|
-
data[location] = {
|
25
|
-
'status' => 'not_documented',
|
26
|
-
'got' => response['body']
|
27
|
-
}
|
28
|
-
else
|
29
|
-
responses_documented(location, data, response)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
data
|
35
|
-
end
|
36
|
-
|
37
|
-
def responses_documented(location, data, response)
|
38
|
-
if response['valid']
|
39
|
-
expect_body = {}
|
40
|
-
|
41
|
-
response['schemas'].size.times do |i|
|
42
|
-
if response['fully_validates'][i] == []
|
43
|
-
expect_body = response['schemas'][i]
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
data[location] = {
|
48
|
-
'status' => 'valid',
|
49
|
-
'got' => response['body'],
|
50
|
-
'expect' => MultiJson.dump(expect_body)
|
51
|
-
}
|
52
|
-
else
|
53
|
-
fully_validates = response['fully_validates'].map do |fully_validate|
|
54
|
-
MultiJson.dump(fully_validate)
|
55
|
-
end
|
56
|
-
|
57
|
-
schemas = response['schemas'].map do |schema|
|
58
|
-
MultiJson.dump(schema)
|
59
|
-
end
|
60
|
-
|
61
|
-
data[location] = {
|
62
|
-
'status' => 'invalid',
|
63
|
-
'got' => response['body'],
|
64
|
-
'diff' => fully_validates,
|
65
|
-
'expected' => schemas
|
66
|
-
}
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
def to_hash
|
71
|
-
@json
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
require 'multi_json'
|
2
|
-
|
3
|
-
module Fitting
|
4
|
-
module Storage
|
5
|
-
class JsonFile
|
6
|
-
NAME = 'storage.json'.freeze
|
7
|
-
|
8
|
-
def self.craft
|
9
|
-
save({})
|
10
|
-
end
|
11
|
-
|
12
|
-
def self.save(json)
|
13
|
-
File.open(NAME, 'w') do |file|
|
14
|
-
file.write(MultiJson.dump(json))
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.push(key, value)
|
19
|
-
save(tests.merge(key => value))
|
20
|
-
rescue
|
21
|
-
end
|
22
|
-
|
23
|
-
def self.tests
|
24
|
-
MultiJson.load(File.read(NAME))
|
25
|
-
rescue
|
26
|
-
end
|
27
|
-
|
28
|
-
def self.load
|
29
|
-
MultiJson.load(File.read(NAME))
|
30
|
-
end
|
31
|
-
|
32
|
-
def self.destroy
|
33
|
-
File.delete(NAME)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
require 'yaml'
|
2
|
-
|
3
|
-
module Fitting
|
4
|
-
module Storage
|
5
|
-
class YamlFile
|
6
|
-
NAME = 'storage.yaml'.freeze
|
7
|
-
|
8
|
-
def self.craft
|
9
|
-
save("---\n")
|
10
|
-
end
|
11
|
-
|
12
|
-
def self.save(json)
|
13
|
-
File.open(NAME, 'w') do |file|
|
14
|
-
file.write(json)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.push(key, value)
|
19
|
-
save(tests + YAML.dump(key => value)[4..-1])
|
20
|
-
rescue
|
21
|
-
end
|
22
|
-
|
23
|
-
def self.tests
|
24
|
-
File.read(NAME)
|
25
|
-
rescue
|
26
|
-
end
|
27
|
-
|
28
|
-
def self.load
|
29
|
-
YAML.load(File.read(NAME))
|
30
|
-
end
|
31
|
-
|
32
|
-
def self.destroy
|
33
|
-
File.delete(NAME)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|