vigia 0.0.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +7 -0
- data/README.md +145 -0
- data/Rakefile +7 -0
- data/lib/vigia/blueprint.rb +14 -0
- data/lib/vigia/config.rb +46 -0
- data/lib/vigia/example.rb +92 -0
- data/lib/vigia/headers.rb +48 -0
- data/lib/vigia/http_client/rest_client.rb +44 -0
- data/lib/vigia/parameters.rb +22 -0
- data/lib/vigia/rspec.rb +47 -0
- data/lib/vigia/spec/api_spec.rb +31 -0
- data/lib/vigia/spec/support/shared_examples/apib_example.rb +33 -0
- data/lib/vigia/spec/support/shared_examples/skip_example.rb +15 -0
- data/lib/vigia/spec/support/utils.rb +29 -0
- data/lib/vigia/url.rb +48 -0
- data/lib/vigia/version.rb +5 -0
- data/lib/vigia.rb +35 -0
- metadata +218 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 929d9503715c7b1c7d98b04831cac098545caf26
|
4
|
+
data.tar.gz: e8cbd9941d8839d48bb8d8fc278e96f4f6fed369
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3c06c22b0c3bfce8583293f22bf6e195799e13cb811b33d80532383e599b91614221a333d4fa07377cb2810961daee2ecbcf3d47505ca3a2ee5b4b5b25bdec5c
|
7
|
+
data.tar.gz: b4dca429249f5218810f138b3bc38fade070f4923c8e876f5aae129e1bf9664bbfa7759d142c3e3c18c8f08466d17ba0858e74a798d178b1357b4c42f1980f41
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
Vigia
|
2
|
+
========
|
3
|
+
|
4
|
+
[![Build Status](https://travis-ci.org/nogates/vigia.svg?branch=master)](https://travis-ci.org/nogates/vigia)
|
5
|
+
[![Code Climate](https://codeclimate.com/github/nogates/vigia/badges/gpa.svg)](https://codeclimate.com/github/nogates/vigia)
|
6
|
+
[![Test Coverage](https://codeclimate.com/github/nogates/vigia/badges/coverage.svg)](https://codeclimate.com/github/nogates/vigia)
|
7
|
+
|
8
|
+
# What is it?
|
9
|
+
|
10
|
+
Vigia is a gem to perform integration test within RSpec framework using a compatible
|
11
|
+
[Api Blueprint](https://github.com/apiaryio/api-blueprint/blob/master/API%20Blueprint%20Specification.md) definition file. It uses [RedSnow](https://github.com/apiaryio/redsnow) to parse the Api Blueprint file and [RestClient](https://github.com/rest-client/rest-client) as http client to perform the requests.
|
12
|
+
|
13
|
+
Vigia runs by default only two comparision between the blueprint file and the server response. The Http response code and the inclusion of the blueprint headers inside the headers response. But it can be easily extended through rspec shared examples
|
14
|
+
|
15
|
+
|
16
|
+
# Installation
|
17
|
+
|
18
|
+
Include Vigia as gem inside `:test` group
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
|
22
|
+
group :test do
|
23
|
+
gem 'vigia'
|
24
|
+
end
|
25
|
+
|
26
|
+
```
|
27
|
+
|
28
|
+
Run bundle install
|
29
|
+
|
30
|
+
```
|
31
|
+
$ bundle install
|
32
|
+
```
|
33
|
+
|
34
|
+
Vigia can now be used inside your application.
|
35
|
+
|
36
|
+
# Getting started
|
37
|
+
|
38
|
+
Vigia provides an easy way to configure the parameters of the test
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
|
42
|
+
Vigia.configure do |config|
|
43
|
+
|
44
|
+
# Define the Apib Blueprint Path. For example, within a Rails app
|
45
|
+
config.apib_path = "#{ Rails.root }/apibs/my_api.apib"
|
46
|
+
|
47
|
+
# Define the host address where the request will be performed.
|
48
|
+
config.host = 'http://localhost:3000'
|
49
|
+
|
50
|
+
# Include examples files within the Rspec.
|
51
|
+
config.custom_examples_paths = [ "#{ Rails.root }/spec/apibs" ]
|
52
|
+
|
53
|
+
# Add custom examples for the apib.
|
54
|
+
config.add_custom_examples_on(:all, 'my custom examples')
|
55
|
+
|
56
|
+
# Includes a collection of custom headers in all the requests.
|
57
|
+
config.headers = { authorization: 'Bearer <your hash here>' }
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
```
|
62
|
+
|
63
|
+
## Putting all together: using a rake task to perform the tests
|
64
|
+
|
65
|
+
This example shows an easy way to start a rails server an perform you apibs test.
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
# Your lib/tasks/vigia.rake
|
69
|
+
|
70
|
+
namespace :spec do
|
71
|
+
|
72
|
+
desc 'Run Vigia tests'
|
73
|
+
task :vigia => :environment do
|
74
|
+
|
75
|
+
# start rails server by the easiest way
|
76
|
+
system("bundle exec rails s -e #{ Rails.env } -d")
|
77
|
+
# give some time to the server
|
78
|
+
sleep 10
|
79
|
+
|
80
|
+
Vigia.configure do |config|
|
81
|
+
config.apib_path = "#{ Rails.root }/apibs/my_api.apib"
|
82
|
+
config.host = 'http://localhost:3000'
|
83
|
+
end
|
84
|
+
|
85
|
+
Vigia.rspec!
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
89
|
+
```
|
90
|
+
|
91
|
+
## Custom examples
|
92
|
+
|
93
|
+
Vigia allows to include custom rspec examples in the test using some options in the config
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
|
97
|
+
Vigia.configure do |config|
|
98
|
+
# Define where your examples are located
|
99
|
+
config.custom_examples_paths = [ '/my_project/shared_examples/apib_examples.rb' ]
|
100
|
+
|
101
|
+
# Define the custom examples you want to include in your test
|
102
|
+
|
103
|
+
# To the example in all your request use `:all` symbol
|
104
|
+
config.add_custom_examples_on(:all, 'my custom examples')
|
105
|
+
|
106
|
+
# You can specify the name of an action or a resource. Only the requests which belong to that
|
107
|
+
# resource or action will run these shared examples
|
108
|
+
config.add_custom_examples_on('Create an Image', 'create image examples')
|
109
|
+
|
110
|
+
end
|
111
|
+
```
|
112
|
+
|
113
|
+
Then, create your Rspec shared example and name the examples accordingly
|
114
|
+
|
115
|
+
```ruby
|
116
|
+
# /my_project/shared_examples/apib_examples.rb
|
117
|
+
|
118
|
+
shared_examples 'my custom examples' do |vigia_example, response|
|
119
|
+
it 'is a valid json response' do
|
120
|
+
expect { JSON.parse(result[:body]) }.not_to raise_error
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
shared_examples 'create image examples' do |vigia_example, response|
|
125
|
+
before do
|
126
|
+
@json_result = JSON.parse(result[:body])
|
127
|
+
@json_expectation = JSON.parse(expectations[:body])
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'has the expected link to the image' do |vigia_example, response|
|
131
|
+
expect(@json_result['image']['link']).to eql(@json_expectation['image']['link'])
|
132
|
+
end
|
133
|
+
end
|
134
|
+
```
|
135
|
+
|
136
|
+
# ToDo
|
137
|
+
|
138
|
+
- [ ] Vigia::Example defines each Api Blueprint transactional example, but each example can have several responses (200, 404, etc.). Think a better way to handle this instead of passing the response variable across methods.
|
139
|
+
|
140
|
+
- [ ] Spike: Do we need to set RSpec specific options? (Vigia::Rspec)
|
141
|
+
|
142
|
+
- [ ] Parse http client exceptions properly. (done?)
|
143
|
+
|
144
|
+
- [ ] Support custom http client through config. (low priority)
|
145
|
+
|
data/Rakefile
ADDED
data/lib/vigia/config.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
module Vigia
|
2
|
+
class Config
|
3
|
+
attr_accessor :apib_path, :host, :custom_examples_paths, :custom_examples, :headers, :http_client_class
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@host = nil
|
7
|
+
@apib_path = nil
|
8
|
+
@headers = {}
|
9
|
+
@custom_examples_paths = []
|
10
|
+
@custom_examples = []
|
11
|
+
@http_client_class = Vigia::HttpClient::RestClient
|
12
|
+
end
|
13
|
+
|
14
|
+
def validate!
|
15
|
+
raise("You need to provide an apib_path") unless @apib_path
|
16
|
+
raise("You have to provide a host value in config or in the Apib") unless host
|
17
|
+
end
|
18
|
+
|
19
|
+
def add_custom_examples_on(filter, name)
|
20
|
+
@custom_examples << { filter: filter, name: name }
|
21
|
+
end
|
22
|
+
|
23
|
+
def host
|
24
|
+
@host || blueprint.metadata['host']
|
25
|
+
end
|
26
|
+
|
27
|
+
def custom_examples_for(specpaib_example)
|
28
|
+
custom_examples.each_with_object([]) do |custom_example, collection|
|
29
|
+
collection << custom_example[:name] if eligible_example?(specpaib_example, custom_example[:filter])
|
30
|
+
collection
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def blueprint
|
35
|
+
@blueprint ||= Vigia::Blueprint.new(File.read(apib_path))
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def eligible_example?(specpaib_example, filter)
|
41
|
+
return true if filter == :all
|
42
|
+
|
43
|
+
[ specpaib_example.resource.name, specpaib_example.action.name ].include?(filter)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
module Vigia
|
2
|
+
class Example
|
3
|
+
|
4
|
+
attr_reader :action, :resource, :apib_example, :requests, :headers
|
5
|
+
|
6
|
+
def initialize(resource:, action:, apib_example:)
|
7
|
+
@resource = resource
|
8
|
+
@action = action
|
9
|
+
@apib_example = apib_example
|
10
|
+
@error = []
|
11
|
+
@requests = {}
|
12
|
+
@parameters = Vigia::Parameters.new(resource, action)
|
13
|
+
@headers = Vigia::Headers.new(resource)
|
14
|
+
@url = Vigia::Url.new(resource.uri_template)
|
15
|
+
end
|
16
|
+
|
17
|
+
# do the request only once ??
|
18
|
+
def perform_request(response)
|
19
|
+
return @requests[response.name] if @requests.key?(response.name)
|
20
|
+
|
21
|
+
@requests[response.name] = http_client_request(http_options_for(response))
|
22
|
+
@requests[response.name]
|
23
|
+
end
|
24
|
+
|
25
|
+
def expectations_for(response)
|
26
|
+
{
|
27
|
+
code: response.name.to_i,
|
28
|
+
headers: @headers.expected(response),
|
29
|
+
body: response.body
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
def url
|
34
|
+
@url.expand(parameters)
|
35
|
+
end
|
36
|
+
|
37
|
+
def custom_examples
|
38
|
+
Vigia.config.custom_examples_for(self)
|
39
|
+
end
|
40
|
+
|
41
|
+
def skip?
|
42
|
+
resource.description.include?('@skip') or action.description.include?('@skip')
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def parameters
|
48
|
+
@parameters.to_hash
|
49
|
+
end
|
50
|
+
|
51
|
+
def http_options_for(response)
|
52
|
+
options = default_http_options_for(response)
|
53
|
+
|
54
|
+
if with_payload?
|
55
|
+
options.merge!(payload: request_for(response).body)
|
56
|
+
end
|
57
|
+
|
58
|
+
options
|
59
|
+
end
|
60
|
+
|
61
|
+
def http_client_request(http_options)
|
62
|
+
Vigia.config.http_client_class.new(http_options).run!
|
63
|
+
end
|
64
|
+
|
65
|
+
def default_http_options_for(response)
|
66
|
+
options = {
|
67
|
+
method: action.method,
|
68
|
+
url: url,
|
69
|
+
headers: headers(response)
|
70
|
+
}
|
71
|
+
end
|
72
|
+
|
73
|
+
def headers(response)
|
74
|
+
if with_payload?
|
75
|
+
@headers.http_client_with_payload(response, request_for(response))
|
76
|
+
else
|
77
|
+
@headers.http_client(response)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def with_payload?
|
82
|
+
%w(POST PUT PATCH).include? action.method
|
83
|
+
end
|
84
|
+
|
85
|
+
def request_for(response)
|
86
|
+
index = apib_example.responses.index(response)
|
87
|
+
apib_example.requests.fetch(index)
|
88
|
+
rescue => e
|
89
|
+
raise "Unable to load payload for response #{ response.name }"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Vigia
|
2
|
+
class Headers
|
3
|
+
|
4
|
+
# ToDo: resource should be an instance variable
|
5
|
+
def initialize(resource)
|
6
|
+
@resource = resource
|
7
|
+
end
|
8
|
+
|
9
|
+
def expected(response)
|
10
|
+
compile_headers(headers_for_response(response))
|
11
|
+
end
|
12
|
+
|
13
|
+
def http_client(response)
|
14
|
+
compile_headers(headers_for_response(response)).merge(config_headers)
|
15
|
+
end
|
16
|
+
|
17
|
+
def http_client_with_payload(response, payload)
|
18
|
+
compile_headers(headers_for_response_and_payload(response, payload)).merge(config_headers)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
def compile_headers(headers, options = {})
|
23
|
+
headers.inject({}) do |hash, header|
|
24
|
+
# Find a better way to match headers in expectations (Hash with indifferent access?).s
|
25
|
+
# Right now, this is needed to match RestClient headers format.
|
26
|
+
normalize_header_name = header[:name].gsub('-', '_').downcase.to_sym
|
27
|
+
hash.merge!(normalize_header_name => header[:value])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def config_headers
|
32
|
+
Vigia.config.headers
|
33
|
+
end
|
34
|
+
|
35
|
+
def headers_for_response(response)
|
36
|
+
collection = []
|
37
|
+
collection << [*@resource.model.headers.collection]
|
38
|
+
collection << [*response.headers.collection]
|
39
|
+
collection.flatten
|
40
|
+
end
|
41
|
+
|
42
|
+
def headers_for_response_and_payload(response, payload)
|
43
|
+
collection = headers_for_response(response)
|
44
|
+
collection << [*payload.headers.collection]
|
45
|
+
collection.flatten
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Vigia
|
2
|
+
module HttpClient
|
3
|
+
class RestClient
|
4
|
+
attr_accessor :code, :headers, :body
|
5
|
+
|
6
|
+
def initialize(http_options)
|
7
|
+
@http_options = http_options
|
8
|
+
end
|
9
|
+
|
10
|
+
def run!
|
11
|
+
perform_request
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
# :nocov:
|
17
|
+
def parse_request(rest_client_result)
|
18
|
+
{
|
19
|
+
code: rest_client_result.code,
|
20
|
+
headers: rest_client_result.headers,
|
21
|
+
body: rest_client_result.body
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
def error_request(exception)
|
26
|
+
{
|
27
|
+
code: exception.http_code, # Todo. Parse each exception
|
28
|
+
headers: exception.response.headers,
|
29
|
+
body: exception.response
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
def perform_request
|
34
|
+
begin
|
35
|
+
request = ::RestClient::Request.execute(@http_options)
|
36
|
+
parse_request(request)
|
37
|
+
rescue ::RestClient::Exception => exception
|
38
|
+
error_request(exception)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
# :nocov:
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Vigia
|
2
|
+
class Parameters
|
3
|
+
|
4
|
+
attr_reader :resource, :action
|
5
|
+
|
6
|
+
def initialize(resource, action)
|
7
|
+
@resource = resource
|
8
|
+
@action = action
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_hash
|
12
|
+
all.each_with_object({}) do |parameter, collection|
|
13
|
+
collection[parameter.name] = parameter.example_value
|
14
|
+
collection
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def all
|
19
|
+
resource.parameters.collection + action.parameters.collection
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/vigia/rspec.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
module Vigia
|
2
|
+
class Rspec
|
3
|
+
class << self
|
4
|
+
def apib
|
5
|
+
Vigia.config.blueprint.apib
|
6
|
+
end
|
7
|
+
|
8
|
+
def include_shared_folders
|
9
|
+
require_custom_examples
|
10
|
+
require "#{ __dir__ }/spec/support/utils"
|
11
|
+
require "#{ __dir__ }/spec/support/shared_examples/skip_example"
|
12
|
+
require "#{ __dir__ }/spec/support/shared_examples/apib_example"
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
def require_custom_examples
|
17
|
+
if Vigia.config.custom_examples_paths
|
18
|
+
[ *Vigia.config.custom_examples_paths ].sort.each do |example_file|
|
19
|
+
require example_file
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Run `Vigia.spec_folder` spec file
|
26
|
+
def run!
|
27
|
+
with_options do
|
28
|
+
RSpec::Core::Runner::run(
|
29
|
+
[ Vigia.spec_folder ], $stderr, $stdout)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
# ToDo: Do we need rspec config?
|
36
|
+
|
37
|
+
def with_options &block
|
38
|
+
RSpec.configure do |config|
|
39
|
+
config.before(:each) do |example|
|
40
|
+
end
|
41
|
+
config.before(:suite) do
|
42
|
+
end
|
43
|
+
end
|
44
|
+
yield
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
describe Vigia::Rspec do
|
4
|
+
|
5
|
+
described_class.include_shared_folders
|
6
|
+
|
7
|
+
described_class.apib.resource_groups.each do |resource_group|
|
8
|
+
describe description_for(resource_group) do
|
9
|
+
resource_group.resources.each do |resource|
|
10
|
+
describe description_for(resource) do
|
11
|
+
resource.actions.each do |action|
|
12
|
+
describe description_for(action) do
|
13
|
+
action.examples.each do |apib_example|
|
14
|
+
runner_example = Vigia::Example.new(
|
15
|
+
resource: resource,
|
16
|
+
action: action,
|
17
|
+
apib_example: apib_example)
|
18
|
+
|
19
|
+
if runner_example.skip?
|
20
|
+
include_examples 'skip example', runner_example
|
21
|
+
else
|
22
|
+
include_examples 'apib example', runner_example
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
shared_examples 'apib example' do |runner_example|
|
2
|
+
|
3
|
+
let(:runner_example) { runner_example }
|
4
|
+
|
5
|
+
runner_example.apib_example.responses.each do |response|
|
6
|
+
context description_for(response) do
|
7
|
+
context "when requesting #{ runner_example.url }" do
|
8
|
+
|
9
|
+
let(:response) { response }
|
10
|
+
let!(:expectations) { runner_example.expectations_for(response) }
|
11
|
+
let!(:result) { runner_example.perform_request(response) }
|
12
|
+
|
13
|
+
it 'returns the expected HTTP code' do
|
14
|
+
expect(result[:code]).to eql(expectations[:code]),
|
15
|
+
-> { format_error(result, expectations) }
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'returns the expected HTTP headers' do
|
19
|
+
expect(result[:headers]).to include(expectations[:headers]),
|
20
|
+
-> { format_error(result, expectations) }
|
21
|
+
end
|
22
|
+
|
23
|
+
if runner_example.custom_examples.any?
|
24
|
+
context 'when running custom rspec examples' do
|
25
|
+
runner_example.custom_examples.each do |example_name|
|
26
|
+
include_examples example_name, runner_example, response
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
shared_examples 'skip example' do |runner_example|
|
2
|
+
|
3
|
+
let(:runner_example) { runner_example }
|
4
|
+
|
5
|
+
runner_example.apib_example.responses.each do |response|
|
6
|
+
context description_for(response) do
|
7
|
+
context "when requesting #{ runner_example.url }" do
|
8
|
+
|
9
|
+
it '# disabled with @skip' do
|
10
|
+
expect(runner_example.skip?).to be_truthy
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
def description_for object
|
4
|
+
case object
|
5
|
+
when RedSnow::ResourceGroup
|
6
|
+
"Resource Group: #{ object.name }"
|
7
|
+
when RedSnow::Resource
|
8
|
+
"Resource: #{ object.name } (#{ object.uri_template })"
|
9
|
+
when RedSnow::Action
|
10
|
+
"Action: #{ object.name } (#{ object.method })"
|
11
|
+
when RedSnow::Payload
|
12
|
+
"Response: #{ object.name }"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def format_error(result, expectation)
|
17
|
+
<<-FORMATTED_ERROR
|
18
|
+
|
19
|
+
Expected:
|
20
|
+
|
21
|
+
#{ expectation.inspect }
|
22
|
+
|
23
|
+
Got:
|
24
|
+
|
25
|
+
#{ result.inspect }
|
26
|
+
|
27
|
+
|
28
|
+
FORMATTED_ERROR
|
29
|
+
end
|
data/lib/vigia/url.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'uri'
|
2
|
+
|
3
|
+
module Vigia
|
4
|
+
class Url
|
5
|
+
|
6
|
+
attr_reader :uri_template
|
7
|
+
|
8
|
+
# ApiBluprint uses RFC6570 in all its resource's uri_templates
|
9
|
+
# https://github.com/apiaryio/api-blueprint/blob/master/API%20Blueprint%20Specification.md#1-uri-templates
|
10
|
+
def initialize(apib_uri_template)
|
11
|
+
@uri_template = ::URITemplate.new(:rfc6570, apib_uri_template)
|
12
|
+
end
|
13
|
+
|
14
|
+
def expand(parameters)
|
15
|
+
validate(parameters) # if Vigia.config.validate_url_parameters?
|
16
|
+
|
17
|
+
absolute_url uri_template.expand(parameters.to_hash)
|
18
|
+
end
|
19
|
+
|
20
|
+
def absolute_url path
|
21
|
+
URI.join(host, path).to_s
|
22
|
+
end
|
23
|
+
|
24
|
+
def validate(parameters)
|
25
|
+
return if required_template_parameters.empty?
|
26
|
+
|
27
|
+
missing_parameters = required_template_parameters - valid_paremeters(parameters)
|
28
|
+
|
29
|
+
raise("Uri template #{ @uri_template } needs parameter/s #{ missing_parameters.join(',') }") unless missing_parameters.empty?
|
30
|
+
end
|
31
|
+
|
32
|
+
def host
|
33
|
+
Vigia.config.host
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def valid_paremeters(parameters)
|
39
|
+
parameters.to_hash.delete_if{|_,v| v.nil? || v.empty? }.keys
|
40
|
+
end
|
41
|
+
|
42
|
+
def required_template_parameters
|
43
|
+
uri_template.tokens.select{
|
44
|
+
|token| token.is_a?(URITemplate::RFC6570::Expression::Basic)
|
45
|
+
}.map(&:variables).flatten
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/vigia.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'redsnow'
|
4
|
+
require 'rspec'
|
5
|
+
require 'rest_client'
|
6
|
+
require 'uri_template'
|
7
|
+
|
8
|
+
require_relative 'vigia/blueprint'
|
9
|
+
require_relative 'vigia/config'
|
10
|
+
require_relative 'vigia/example'
|
11
|
+
require_relative 'vigia/headers'
|
12
|
+
require_relative 'vigia/http_client/rest_client'
|
13
|
+
require_relative 'vigia/parameters'
|
14
|
+
require_relative 'vigia/rspec'
|
15
|
+
require_relative 'vigia/url'
|
16
|
+
require_relative 'vigia/version'
|
17
|
+
|
18
|
+
module Vigia
|
19
|
+
class << self
|
20
|
+
def config
|
21
|
+
@config
|
22
|
+
end
|
23
|
+
def configure
|
24
|
+
@config = Vigia::Config.new
|
25
|
+
yield @config
|
26
|
+
@config.validate!
|
27
|
+
end
|
28
|
+
def spec_folder
|
29
|
+
File.join(__dir__, 'vigia', 'spec')
|
30
|
+
end
|
31
|
+
def rspec!
|
32
|
+
Vigia::Rspec.new.run!
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
metadata
ADDED
@@ -0,0 +1,218 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: vigia
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.9
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- David Tapiador
|
8
|
+
- atlas2ninjas
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-10-22 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ">="
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '0'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: redsnow
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: rest-client
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
type: :runtime
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: rspec
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
type: :runtime
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: uri_template
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :runtime
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: bundler
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
type: :development
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
- !ruby/object:Gem::Dependency
|
99
|
+
name: sinatra
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
type: :development
|
106
|
+
prerelease: false
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
- !ruby/object:Gem::Dependency
|
113
|
+
name: celluloid
|
114
|
+
requirement: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - ">="
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '0'
|
119
|
+
type: :development
|
120
|
+
prerelease: false
|
121
|
+
version_requirements: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - ">="
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: json
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- - ">="
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '0'
|
133
|
+
type: :development
|
134
|
+
prerelease: false
|
135
|
+
version_requirements: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - ">="
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0'
|
140
|
+
- !ruby/object:Gem::Dependency
|
141
|
+
name: pry-debugger
|
142
|
+
requirement: !ruby/object:Gem::Requirement
|
143
|
+
requirements:
|
144
|
+
- - ">="
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: '0'
|
147
|
+
type: :development
|
148
|
+
prerelease: false
|
149
|
+
version_requirements: !ruby/object:Gem::Requirement
|
150
|
+
requirements:
|
151
|
+
- - ">="
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: '0'
|
154
|
+
- !ruby/object:Gem::Dependency
|
155
|
+
name: simplecov
|
156
|
+
requirement: !ruby/object:Gem::Requirement
|
157
|
+
requirements:
|
158
|
+
- - ">="
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
version: '0'
|
161
|
+
type: :development
|
162
|
+
prerelease: false
|
163
|
+
version_requirements: !ruby/object:Gem::Requirement
|
164
|
+
requirements:
|
165
|
+
- - ">="
|
166
|
+
- !ruby/object:Gem::Version
|
167
|
+
version: '0'
|
168
|
+
description: Test your Apiary Blueprint specification on ruby
|
169
|
+
email:
|
170
|
+
- david.tapiador@lonelyplanet.com.au
|
171
|
+
- atlas2ninjas@lonelyplanet.com.au
|
172
|
+
executables: []
|
173
|
+
extensions: []
|
174
|
+
extra_rdoc_files: []
|
175
|
+
files:
|
176
|
+
- Gemfile
|
177
|
+
- README.md
|
178
|
+
- Rakefile
|
179
|
+
- lib/vigia.rb
|
180
|
+
- lib/vigia/blueprint.rb
|
181
|
+
- lib/vigia/config.rb
|
182
|
+
- lib/vigia/example.rb
|
183
|
+
- lib/vigia/headers.rb
|
184
|
+
- lib/vigia/http_client/rest_client.rb
|
185
|
+
- lib/vigia/parameters.rb
|
186
|
+
- lib/vigia/rspec.rb
|
187
|
+
- lib/vigia/spec/api_spec.rb
|
188
|
+
- lib/vigia/spec/support/shared_examples/apib_example.rb
|
189
|
+
- lib/vigia/spec/support/shared_examples/skip_example.rb
|
190
|
+
- lib/vigia/spec/support/utils.rb
|
191
|
+
- lib/vigia/url.rb
|
192
|
+
- lib/vigia/version.rb
|
193
|
+
homepage: https://github.com/nogates/vigia
|
194
|
+
licenses:
|
195
|
+
- MIT
|
196
|
+
metadata: {}
|
197
|
+
post_install_message:
|
198
|
+
rdoc_options: []
|
199
|
+
require_paths:
|
200
|
+
- lib
|
201
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
202
|
+
requirements:
|
203
|
+
- - ">="
|
204
|
+
- !ruby/object:Gem::Version
|
205
|
+
version: '0'
|
206
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
207
|
+
requirements:
|
208
|
+
- - ">="
|
209
|
+
- !ruby/object:Gem::Version
|
210
|
+
version: '0'
|
211
|
+
requirements: []
|
212
|
+
rubyforge_project:
|
213
|
+
rubygems_version: 2.2.2
|
214
|
+
signing_key:
|
215
|
+
specification_version: 4
|
216
|
+
summary: Test your Apiary Blueprint specification on ruby
|
217
|
+
test_files: []
|
218
|
+
has_rdoc:
|