vigia 0.0.9 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 929d9503715c7b1c7d98b04831cac098545caf26
4
- data.tar.gz: e8cbd9941d8839d48bb8d8fc278e96f4f6fed369
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NzQzNmJmYjk4OTkzYjZmZDc0ZGQ3N2I4MTZiYjUyYmZhOTNkODExZQ==
5
+ data.tar.gz: !binary |-
6
+ ZDI3MTQ4ZWYxNDY5MjIzMjA2MGM3OWVkN2EwNzA0NDU0NDhjODY5MQ==
5
7
  SHA512:
6
- metadata.gz: 3c06c22b0c3bfce8583293f22bf6e195799e13cb811b33d80532383e599b91614221a333d4fa07377cb2810961daee2ecbcf3d47505ca3a2ee5b4b5b25bdec5c
7
- data.tar.gz: b4dca429249f5218810f138b3bc38fade070f4923c8e876f5aae129e1bf9664bbfa7759d142c3e3c18c8f08466d17ba0858e74a798d178b1357b4c42f1980f41
8
+ metadata.gz: !binary |-
9
+ ZGI4ZWY0MjAxZGM5YzRmYjdhYTE0MTc0NTg0NmRjZTI1ZTE3NDBjMWQ0YmE2
10
+ YmZmY2FhMWJhZTkzMDQ5NDU5N2U5MmE0ODAwNjhhYzk5MWRjODVmNjI0NmM0
11
+ NmY3ZDliMjRlNDMyOGJiZGJiMmU0NDhlNzRkNDJkMWFjMmQwYmY=
12
+ data.tar.gz: !binary |-
13
+ MzdkMDE5NjMzYmI5MGJmODY3MWQ1YWQwMDRjZDhhOWIwNzAxMWUxODVmMzQ5
14
+ M2ExMmVkMDI3Y2MwYzg2MWRiYWI3YTAyZDY2ZTFjMjliZTgyYmEyNmNlMmIy
15
+ MTlhM2I2NTc4NzM5OTY2Yzc0ZGY5ZDUyNjk1YTQ4NjVmZGY2NTU=
data/README.md CHANGED
@@ -7,11 +7,11 @@ Vigia
7
7
 
8
8
  # What is it?
9
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.
10
+ <img src="http://singularities.org/vigia.png" width="96" height="96" class="right" alt="Vigia logo" />
12
11
 
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
12
+ Vigia is a gem to perform integration tests using RSpec and a compatible adapter (See [Adapters](#adapters)). The adapter creates the structure of the test (groups and context) and sets up all the variables (See [Context variables](#context-variables)) used to perform the http request.
14
13
 
14
+ These results and expectations objects can be used to run examples that will compare the expected value with the server response value. Vigia allows to use a variety of different ways to execute these comparisons (See [Vigia Examples](#vigia-examples) and [Custom Shared Examples](#custom-shared-examples))
15
15
 
16
16
  # Installation
17
17
 
@@ -27,70 +27,229 @@ end
27
27
 
28
28
  Run bundle install
29
29
 
30
- ```
30
+ ```bash
31
31
  $ bundle install
32
32
  ```
33
33
 
34
- Vigia can now be used inside your application.
34
+ Now, Vigia can be used inside your application.
35
35
 
36
36
  # Getting started
37
37
 
38
- Vigia provides an easy way to configure the parameters of the test
38
+ This example shows an easy way to start a rails server and perform you apibs test.
39
+
40
+ ```ruby
41
+ # Your lib/tasks/vigia.rake
42
+ namespace :spec do
43
+ desc 'Run Vigia tests'
44
+ task :vigia => :environment do
45
+
46
+ # start rails server by the easiest way
47
+ system("bundle exec rails s -e #{ Rails.env } -d")
48
+ # give some time to the server
49
+ sleep 10
50
+
51
+ Vigia.configure do |config|
52
+ config.source_file = "#{ Rails.root }/apibs/my_api.apib"
53
+ config.host = 'http://localhost:3000'
54
+ end
55
+
56
+ Vigia.rspec!
57
+ end
58
+ end
59
+ ```
60
+
61
+ ## Configuration
62
+
63
+ Vigia tries to be flexible enough in case that you need to run custom operations during the tests.
39
64
 
40
65
  ```ruby
41
66
 
42
67
  Vigia.configure do |config|
43
68
 
44
- # Define the Apib Blueprint Path. For example, within a Rails app
45
- config.apib_path = "#{ Rails.root }/apibs/my_api.apib"
69
+ # Define your source file. For example, within a Rails app
70
+ config.source_file = "#{ Rails.root }/apibs/my_api.apib"
46
71
 
47
72
  # Define the host address where the request will be performed.
48
73
  config.host = 'http://localhost:3000'
49
74
 
50
- # Include examples files within the Rspec.
51
- config.custom_examples_paths = [ "#{ Rails.root }/spec/apibs" ]
75
+ # Include a collection of custom headers in all the requests.
76
+ config.headers = { authorization: 'Bearer <your hash here>' }
52
77
 
53
- # Add custom examples for the apib.
54
- config.add_custom_examples_on(:all, 'my custom examples')
78
+ # Reset rspec_config and set up documentation formatter
79
+ config.rspec_config do |rspec_config|
80
+ rspec_config.reset
81
+ rspec_config.formatter = RSpec::Core::Formatters::DocumentationFormatter
82
+ end
55
83
 
56
- # Includes a collection of custom headers in all the requests.
57
- config.headers = { authorization: 'Bearer <your hash here>' }
84
+ # Attach a before_context hook to set up the database using Databasecleaner
85
+ config.before_context do
86
+ DatabaseCleaner.start
87
+ end
58
88
 
89
+ # Set a timer on the primary group and raise an exception if the
90
+ # described group takes more than 5 seconds to run
91
+ config.before_group do
92
+ let!(:group_started_at) { Time.now } if described_class.options[:primary]
93
+ end
94
+
95
+ config.after_group do
96
+ if described_class.options[:primary]
97
+ it 'has taken less than 5 seconds to run this example' do
98
+ expect(Time.now.to_i - group_started_at.to_i).to be < 5
99
+ end
100
+ end
101
+ end
59
102
  end
60
103
 
104
+ Vigia.rspec!
105
+
61
106
  ```
107
+ For more information about config, see the `Vigia::Config` class.
108
+
109
+ ## Adapters
62
110
 
63
- ## Putting all together: using a rake task to perform the tests
111
+ By default, Vigia uses `Vigia::Adapters::Blueprint` adapter. This adapter takes an Api Blueprint compatible file and parses it using [RedSnow](https://github.com/apiaryio/redsnow). Then, it builds up the test structure accordingly.
64
112
 
65
- This example shows an easy way to start a rails server an perform you apibs test.
113
+ If needed, Vigia can be configured to use a custom adapter. To do so, you just need to specify the adapter class inside the vigia configuration block:
66
114
 
67
115
  ```ruby
68
- # Your lib/tasks/vigia.rake
116
+ Vigia.configure do |config|
117
+ config.adapter = MyBlogAdapter
118
+ end
119
+ ```
69
120
 
70
- namespace :spec do
121
+ Then, insde your adapter class, you can use the `setup_adater` method to define the groups and contexts that the adapter will provide:
71
122
 
72
- desc 'Run Vigia tests'
73
- task :vigia => :environment do
123
+ ```ruby
74
124
 
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
125
+ # Post
126
+ class MyBlogAdapter < Vigia::Adapter
127
+ setup_adapter do
128
+ group :resource,
129
+ primary: true,
130
+ contexts: [ :default ]
131
+ describes: [ :post, :pages ]
132
+
133
+ context :default,
134
+ http_client_options: {
135
+ url: -> { "/#{ resource }" },
136
+ method: :get
137
+ },
138
+ expectations: {
139
+ code: 200,
140
+ headers: {},
141
+ body: -> { adapter.body_for(resource) }
142
+ }
143
+ end
79
144
 
80
- Vigia.configure do |config|
81
- config.apib_path = "#{ Rails.root }/apibs/my_api.apib"
82
- config.host = 'http://localhost:3000'
145
+ def body_for(resource)
146
+ case resource
147
+ when :post
148
+ # Your post index expected body
149
+ when :pages
150
+ # Your pages index expected body
151
+ else
152
+ 'Unknown resource. WTH!'
83
153
  end
154
+ end
155
+ end
156
+ ```
84
157
 
85
- Vigia.rspec!
158
+ When vigia starts, it fetchs the first group defined as primary. For each group, Vigia will loop on each element of the describes option (`:post, :page` in this example), and will set a rspec memoized object named as the group (`let(:resource) { :post }`). Then, it will run the children (if any) and the contexts in this group, setting up the `http_client_options` and `expectations` memoized objects per context.
159
+
160
+ See `Vigia::Adapters::Blueprint` class for more information about configuring and setting up an adapter.
161
+
162
+ ## Context Variables
163
+
164
+ Vigia tries to be consistent with the way the RSpec are normally written. It creates the describe groups and context based on the adapter configuration and set up all the variables for the examples by using RSpec memoized objects.
86
165
 
166
+ ```ruby
167
+
168
+ # With an adapter `ExampleAdapter` with this config
169
+ #
170
+ # group :resource,
171
+ # describes: [ :posts, :pages ],
172
+ # children: [ :action ]
173
+ #
174
+ # group :action
175
+ # describes: [ :get, :post ],
176
+ # context: [ :default ]
177
+ #
178
+ # context :default,
179
+ # http_client_options: {
180
+ # method: -> { action.to_s.upcase }
181
+ # url: -> { adapter.url_for(resource) }" }
182
+ # headers: :headers
183
+ # expectations:
184
+ # code: :code
185
+ # headers: {}
186
+ # body: -> { Body.for(resource} }
187
+ #
188
+ # Vigia will generate this RSpec code
189
+
190
+ describe Vigia::RSpec do
191
+ let(:adapter) { ExampleAdapter.instance }
192
+ let(:client) { Vigia.config.http_client_class.new(http_options) }
193
+ let(:result) { client.run }
194
+
195
+ # the loop starts...
196
+ describe 'posts' do
197
+ let(:resource) { :posts }
198
+
199
+ describe 'action' do
200
+ let(:action) { :get }
201
+
202
+ context 'default' do
203
+ let(:http_client_options) { Vigia::HttpClient::Options.new(context_options) }
204
+ let(:expectations) { Vigia::HttpClient::ExpectedRequest.new(expectations) }
205
+
206
+ # EXAMPLES RUN HERE!
207
+ end
208
+ # NEXT ACTION
209
+ end
210
+ # NEXT RESOURCE
87
211
  end
88
212
  end
89
213
  ```
90
214
 
91
- ## Custom examples
215
+ Also, It is important to mention that it is in this context where the adapter configuration will be executed. In the previous example, we configured the http_client option as follows:
216
+
217
+ ```ruby
218
+ # http_client_options: {
219
+ # method: -> { action.to_s.upcase }
220
+ # url: -> { adapter.url_for(resource) }" }
221
+ # headers: :headers
222
+ ```
223
+
224
+ The option `method` is a lambda object. This object will be executed inside the RSpec memoized objects context. It is the same as doing:
225
+
226
+ ```ruby
227
+ # it has access to all context/group memoized objects
228
+ let(:method) { action.to_s.upcase }
229
+ ```
230
+
231
+ You can also use the adapter like in option `url`, since it has been defined as a memoized object by Vigia::RSpec.
232
+
233
+ Lastly, you can specify a symbol as the option value. In this case, the adapter will be the reciever of this method.
234
+
235
+ ## Vigia Examples
92
236
 
93
- Vigia allows to include custom rspec examples in the test using some options in the config
237
+ The first way to include examples on vigia is using `register`. Option `disabled_if` can be used to prevent the example for being executed on different situations. `contexts` limits the example to the listed contexts.
238
+
239
+ ```ruby
240
+
241
+ # On your config file, spec_helper, etc.
242
+ Vigia::Sail::Example.register(
243
+ :my_custom_body_validator,
244
+ expectation: -> { expect { MyValidator(result.body) }.not.to raise_error } },
245
+ contexts: [ :my_context ], # default: :default
246
+ disable_if: -> { ! result.headers[:content_type].include?('my_validator_mime') }
247
+ )
248
+ ```
249
+
250
+ ## Custom shared examples
251
+
252
+ Vigia allows to include custom shared rspec examples in the test using some options in the config
94
253
 
95
254
  ```ruby
96
255
 
@@ -100,13 +259,8 @@ Vigia.configure do |config|
100
259
 
101
260
  # Define the custom examples you want to include in your test
102
261
 
103
- # To the example in all your request use `:all` symbol
262
+ # To the example in all your requests use `:all` symbol
104
263
  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
264
  end
111
265
  ```
112
266
 
@@ -117,29 +271,8 @@ Then, create your Rspec shared example and name the examples accordingly
117
271
 
118
272
  shared_examples 'my custom examples' do |vigia_example, response|
119
273
  it 'is a valid json response' do
120
- expect { JSON.parse(result[:body]) }.not_to raise_error
274
+ expect { JSON.parse(result.body) }.not_to raise_error
121
275
  end
122
276
  end
123
277
 
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
278
  ```
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 CHANGED
@@ -1,7 +1,18 @@
1
1
  require 'bundler/gem_tasks'
2
2
  require 'rspec/core/rake_task'
3
+ require 'cucumber/rake/task'
4
+
5
+ Cucumber::Rake::Task.new(:cucumber) do |t|
6
+ t.cucumber_opts = '--tags ~@wip'
7
+ end
3
8
 
4
9
  RSpec::Core::RakeTask.new(:spec)
5
10
 
6
- task :default => :spec
7
- task :test => :spec
11
+ desc 'Clear tmp folders'
12
+ task :clobber do
13
+ FileUtils.rm_rf(File.join(__dir__, 'coverage'))
14
+ end
15
+
16
+ # Not sure why simplecov is preventing cucumber for being run after spec
17
+ # when running rake default
18
+ task :default => [ :spec, :cucumber ]
@@ -0,0 +1,63 @@
1
+ module Vigia
2
+ class Adapter
3
+
4
+ attr_accessor :source_file, :structure
5
+
6
+ class << self
7
+ def setup_adapter(&block)
8
+ raise 'You have to call config_adapter with a block' unless block_given?
9
+ @template = block
10
+ end
11
+
12
+ def template
13
+ @template
14
+ end
15
+
16
+ def instance
17
+ new.tap do |object|
18
+ object.source_file = Vigia.config.source_file
19
+ object.structure = Structure.generate(object, @template)
20
+ object
21
+ end
22
+ end
23
+ end
24
+
25
+ class Structure
26
+ class << self
27
+ def generate(adapter, structure)
28
+ instance = new(adapter, structure)
29
+ instance.preload
30
+ instance
31
+ end
32
+ end
33
+
34
+ attr_reader :adapter, :groups, :contexts, :template
35
+
36
+ def initialize(adapter, template)
37
+ @adapter = adapter
38
+ @template = template
39
+ @groups = {}
40
+ @contexts = {}
41
+ end
42
+
43
+ def preload
44
+ instance_exec(&template)
45
+
46
+ Vigia::Sail::Group.collection = groups
47
+ Vigia::Sail::Context.collection = contexts
48
+ end
49
+
50
+ def after_initialize(&block)
51
+ adapter.instance_exec(&block)
52
+ end
53
+
54
+ def group(name, options = {})
55
+ @groups.merge!(name => options)
56
+ end
57
+
58
+ def context(name, options = {})
59
+ @contexts.merge!(name => options)
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,105 @@
1
+ module Vigia
2
+ module Adapters
3
+ class Blueprint < Vigia::Adapter
4
+
5
+ attr_reader :apib
6
+
7
+ setup_adapter do
8
+
9
+ after_initialize do
10
+ @apib_parsed = RedSnow::parse(File.read(source_file))
11
+ @apib = @apib_parsed.ast
12
+ end
13
+
14
+ group :resource_group,
15
+ primary: true,
16
+ children: [ :resource ],
17
+ describes: -> { adapter.apib.resource_groups },
18
+ description: -> { "Resource Group: #{ resource_group.name }" }
19
+
20
+ group :resource,
21
+ children: [ :action ],
22
+ describes: -> { resource_group.resources },
23
+ description: -> { "Resource: #{ resource.name }" }
24
+
25
+ group :action,
26
+ children: [ :transactional_example ],
27
+ describes: -> { resource.actions },
28
+ description: -> { action.method }
29
+
30
+ group :transactional_example,
31
+ children: [ :response ],
32
+ describes: -> { action.examples },
33
+ description: -> { "Example ##{ parent_object.examples.index(transactional_example) }" }
34
+
35
+ group :response,
36
+ contexts: [ :default ],
37
+ describes: -> { transactional_example.responses },
38
+ description: -> { "Running Response #{ response.name }" }
39
+
40
+ context :default,
41
+ http_client_options: {
42
+ headers: -> { adapter.headers_for(resource, action, transactional_example, response) },
43
+ method: -> { action.method },
44
+ uri_template: -> { resource.uri_template },
45
+ parameters: -> { adapter.parameters_for(resource, action) },
46
+ payload: -> { adapter.payload_for(transactional_example, response) if adapter.with_payload?(action) }
47
+ },
48
+ expectations: {
49
+ code: -> { response.name.to_i },
50
+ headers: -> { adapter.headers_for(resource, action, transactional_example, response, include_payload = false) },
51
+ body: -> { response.body }
52
+ }
53
+ end
54
+
55
+ def headers_for(resource, action, transactional_example, response, include_payload = true)
56
+ headers = headers_for_response(resource, response)
57
+ headers += headers_for_payload(transactional_example, response) if with_payload?(action) && include_payload
58
+ compile_headers(headers)
59
+ end
60
+
61
+ def parameters_for(resource, action)
62
+ (resource.parameters.collection + action.parameters.collection).each_with_object([]) do |parameter, collection|
63
+ collection << { name: parameter.name, value: parameter.example_value, required: (parameter.use == :required) }
64
+ end
65
+ end
66
+
67
+ def with_payload?(action)
68
+ %w(POST PUT PATCH).include? action.method
69
+ end
70
+
71
+ def payload_for(transactional_example, response)
72
+ payload = get_payload(transactional_example, response)
73
+ payload.body
74
+ end
75
+
76
+ private
77
+
78
+ def compile_headers(headers)
79
+ headers.inject({}) do |hash, header|
80
+ normalize_header_name = header[:name].gsub('-', '_').downcase.to_sym
81
+ hash.merge!(normalize_header_name => header[:value])
82
+ end
83
+ end
84
+
85
+ def headers_for_response(resource, response)
86
+ collection = []
87
+ collection << [*resource.model.headers.collection]
88
+ collection << [*response.headers.collection]
89
+ collection.flatten
90
+ end
91
+
92
+ def headers_for_payload(transactional_example, response)
93
+ payload = get_payload(transactional_example, response)
94
+ [ *payload.headers.collection ].flatten
95
+ end
96
+
97
+ def get_payload(transactional_example, response)
98
+ index = transactional_example.responses.index(response)
99
+ transactional_example.requests.fetch(index)
100
+ rescue => e
101
+ raise "Unable to load payload for response #{ response.name }"
102
+ end
103
+ end
104
+ end
105
+ end
data/lib/vigia/config.rb CHANGED
@@ -1,18 +1,28 @@
1
1
  module Vigia
2
2
  class Config
3
- attr_accessor :apib_path, :host, :custom_examples_paths, :custom_examples, :headers, :http_client_class
3
+ attr_accessor :source_file, :host, :custom_examples_paths, :custom_examples, :headers, :http_client_class
4
+ attr_accessor :adapter, :hooks, :rspec_config_block, :stderr, :stdout
4
5
 
5
6
  def initialize
6
7
  @host = nil
7
- @apib_path = nil
8
+ @source_file = nil
9
+ @rspec_config_block = nil
8
10
  @headers = {}
9
11
  @custom_examples_paths = []
10
12
  @custom_examples = []
13
+ @hooks = []
14
+ @stderr = $stderr
15
+ @stdout = $stdout
16
+ @adapter = Vigia::Adapters::Blueprint
11
17
  @http_client_class = Vigia::HttpClient::RestClient
12
18
  end
13
19
 
20
+ def apply
21
+ validate!
22
+ end
23
+
14
24
  def validate!
15
- raise("You need to provide an apib_path") unless @apib_path
25
+ raise("You need to provide an source") unless source_file
16
26
  raise("You have to provide a host value in config or in the Apib") unless host
17
27
  end
18
28
 
@@ -20,27 +30,28 @@ module Vigia
20
30
  @custom_examples << { filter: filter, name: name }
21
31
  end
22
32
 
23
- def host
24
- @host || blueprint.metadata['host']
33
+ def rspec_config(&block)
34
+ @rspec_config_block = block
25
35
  end
26
36
 
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
37
+ def before_group(&block)
38
+ store_hook(Vigia::Sail::GroupInstance, :before, block)
32
39
  end
33
40
 
34
- def blueprint
35
- @blueprint ||= Vigia::Blueprint.new(File.read(apib_path))
41
+ def after_group(&block)
42
+ store_hook(Vigia::Sail::GroupInstance, :after, block)
36
43
  end
37
44
 
38
- private
45
+ def before_context(&block)
46
+ store_hook(Vigia::Sail::Context, :before, block)
47
+ end
39
48
 
40
- def eligible_example?(specpaib_example, filter)
41
- return true if filter == :all
49
+ def after_context(&block)
50
+ store_hook(Vigia::Sail::Context, :after, block)
51
+ end
42
52
 
43
- [ specpaib_example.resource.name, specpaib_example.action.name ].include?(filter)
53
+ def store_hook(rspec_class, filter, block)
54
+ @hooks << { rspec_class: rspec_class, filter: filter, block: block }
44
55
  end
45
56
  end
46
57
  end
@@ -0,0 +1,30 @@
1
+ module Vigia
2
+ module HttpClient
3
+ class Options < OpenStruct
4
+ class << self
5
+ def build(context, in_let_context)
6
+ instance = new
7
+ instance.context = context
8
+ instance.options.each do |name, value|
9
+ instance[name] = context.contextual_object(object: value, context: in_let_context)
10
+ end
11
+ instance.use_uri_template if instance.uri_template
12
+ instance.include_config_headers if Vigia.config.headers.any?
13
+ instance
14
+ end
15
+ end
16
+
17
+ def options
18
+ context.options[:http_client_options] || {}
19
+ end
20
+
21
+ def use_uri_template
22
+ self.url = Vigia::Url.new(uri_template).expand(parameters)
23
+ end
24
+
25
+ def include_config_headers
26
+ self.headers.merge!(Vigia.config.headers)
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,10 @@
1
+ module Vigia
2
+ module HttpClient
3
+ class RequestData < OpenStruct
4
+ end
5
+ class ExpectedRequest < RequestData
6
+ end
7
+ class ClientRequest < RequestData
8
+ end
9
+ end
10
+ end