Skip to content

Commit

Permalink
Merge pull request #9 from nogates/fix_hooks_with_rspec_integration
Browse files Browse the repository at this point in the history
Fix hooks with rspec integration
  • Loading branch information
nogates committed Dec 11, 2014
2 parents 3b53271 + cb327a6 commit 5c354f4
Show file tree
Hide file tree
Showing 15 changed files with 177 additions and 73 deletions.
35 changes: 19 additions & 16 deletions features/my_blog.feature
Original file line number Diff line number Diff line change
Expand Up @@ -70,32 +70,35 @@ Scenario: Using the blueprint adapter with hooks
Then I configure Vigia with the following options:
| source_file | my_blog/my_blog.apib |
| host | my_blog.host |
Then I configure a "before_group" hook with this block:
Then I configure a "after_group" hook with this block:
"""
group_name = described_class.described_object.name
let("#{ described_class.group.name }_name") { group_name }
'a simple string'
"""
Then I configure a "after_group" hook with this block:
Then I configure a "after_context" hook with this block:
"""
'TODO'
"""
Then I configure a "extend_group" hook with this block:
"""
group_name = described_class.described_object.name
let("#{ described_class.group.name }_name") { group_name }
it 'has the described object name defined' do
expect(group_name).to eql(described_class.described_object.name)
end
"""
Then I configure a "before_context" hook with this block:
Then I configure a "extend_context" hook with this block:
"""
let(:full_string_name) do
"#{ resource_group.name }#{ resource.name }#{ action.name }#{ transactional_example.name }#{ response.name }"
end
"""
Then I configure a "after_context" hook with this block:
"""
it 'has all the properties defined after the example' do
it 'has all the properties defined in the example' do
expect(http_client_options).to be_a(Object)
expect(expectations).to be_a(OpenStruct)
expect(result).to be_a(OpenStruct)
end
"""
Then I run Vigia
And the output should contain the following:
Expand All @@ -113,19 +116,19 @@ Scenario: Using the blueprint adapter with hooks
Running Response 200
has the described object name defined
context default
has all the properties defined in the example
has the expected HTTP code
includes the expected headers
has all the properties defined after the example
POST
has the described object name defined
Example #0
has the described object name defined
Running Response 201
has the described object name defined
context default
has all the properties defined in the example
has the expected HTTP code
includes the expected headers
has all the properties defined after the example
Resource: 1.2 Post
has the described object name defined
GET
Expand All @@ -135,9 +138,9 @@ Scenario: Using the blueprint adapter with hooks
Running Response 200
has the described object name defined
context default
has all the properties defined in the example
has the expected HTTP code
includes the expected headers
has all the properties defined after the example
Resource Group: Comments
has the described object name defined
Resource: Comments
Expand All @@ -149,19 +152,19 @@ Scenario: Using the blueprint adapter with hooks
Running Response 200
has the described object name defined
context default
has all the properties defined in the example
has the expected HTTP code
includes the expected headers
has all the properties defined after the example
POST
has the described object name defined
Example #0
has the described object name defined
Running Response 201
has the described object name defined
context default
has all the properties defined in the example
has the expected HTTP code
includes the expected headers
has all the properties defined after the example
Resource: 2.2 Comment
has the described object name defined
PUT
Expand All @@ -171,19 +174,19 @@ Scenario: Using the blueprint adapter with hooks
Running Response 201
has the described object name defined
context default
has all the properties defined in the example
has the expected HTTP code
includes the expected headers
has all the properties defined after the example
DELETE
has the described object name defined
Example #0
has the described object name defined
Running Response 204
has the described object name defined
context default
has all the properties defined in the example
has the expected HTTP code
includes the expected headers
has all the properties defined after the example
"""
And the total tests line should equal "48 examples, 0 failures"
Expand Down
3 changes: 3 additions & 0 deletions lib/vigia.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
require_relative 'vigia/adapter'
require_relative 'vigia/adapters/blueprint'
require_relative 'vigia/config'
require_relative 'vigia/hooks'
require_relative 'vigia/http_client/options'
require_relative 'vigia/http_client/rest_client'
require_relative 'vigia/http_client/requests'
Expand Down Expand Up @@ -39,3 +40,5 @@ def rspec!
end
end
end

require_relative 'vigia/sail/examples/default'
4 changes: 2 additions & 2 deletions lib/vigia/adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ def initialize(adapter, template)
def preload
instance_exec(&template)

Vigia::Sail::Group.collection = groups
Vigia::Sail::Context.collection = contexts
groups.each { |name, options| Vigia::Sail::Group.register(name, options) }
contexts.each { |name, options| Vigia::Sail::Context.register(name, options) }
end

def after_initialize(&block)
Expand Down
16 changes: 10 additions & 6 deletions lib/vigia/adapters/blueprint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,21 +39,21 @@ class Blueprint < Vigia::Adapter

context :default,
http_client_options: {
headers: -> { adapter.headers_for(resource, action, transactional_example, response) },
headers: -> { adapter.headers_for(action, transactional_example, response) },
method: -> { action.method },
uri_template: -> { resource.uri_template },
parameters: -> { adapter.parameters_for(resource, action) },
payload: -> { adapter.payload_for(transactional_example, response) if adapter.with_payload?(action) }
},
expectations: {
code: -> { response.name.to_i },
headers: -> { adapter.headers_for(resource, action, transactional_example, response, include_payload = false) },
headers: -> { adapter.headers_for(action, transactional_example, response, include_payload = false) },
body: -> { response.body }
}
end

def headers_for(resource, action, transactional_example, response, include_payload = true)
headers = headers_for_response(resource, response)
def headers_for(action, transactional_example, response, include_payload = true)
headers = headers_for_response(response)
headers += headers_for_payload(transactional_example, response) if with_payload?(action) && include_payload
compile_headers(headers)
end
Expand Down Expand Up @@ -82,13 +82,17 @@ def compile_headers(headers)
end
end

def headers_for_response(resource, response)
def headers_for_response(response)
collection = []
collection << [*resource.model.headers.collection]
collection << [*response.headers.collection]
collection.flatten
end

# def resources
# apib.resource_groups.map(&:resources).flatten
# end


def headers_for_payload(transactional_example, response)
payload = get_payload(transactional_example, response)
[ *payload.headers.collection ].flatten
Expand Down
11 changes: 10 additions & 1 deletion lib/vigia/config.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
module Vigia
class Config
attr_accessor :source_file, :host, :custom_examples_paths, :custom_examples, :headers, :http_client_class
attr_accessor :adapter, :hooks, :rspec_config_block, :stderr, :stdout
attr_accessor :adapter, :hooks, :rspec_config_block, :stderr, :stdout, :internal_hosts

def initialize
@host = nil
@source_file = nil
@rspec_config_block = nil
@internal_hosts = []
@headers = {}
@custom_examples_paths = []
@custom_examples = []
Expand Down Expand Up @@ -42,6 +43,10 @@ def after_group(&block)
store_hook(Vigia::Sail::GroupInstance, :after, block)
end

def extend_group(&block)
store_hook(Vigia::Sail::GroupInstance, :extend, block)
end

def before_context(&block)
store_hook(Vigia::Sail::Context, :before, block)
end
Expand All @@ -50,6 +55,10 @@ def after_context(&block)
store_hook(Vigia::Sail::Context, :after, block)
end

def extend_context(&block)
store_hook(Vigia::Sail::Context, :extend, block)
end

def store_hook(rspec_class, filter, block)
@hooks << { rspec_class: rspec_class, filter: filter, block: block }
end
Expand Down
46 changes: 46 additions & 0 deletions lib/vigia/hooks.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
module Vigia
module Hooks

def execute_hook(filter_name, rspec_context)
hooks_for_object(filter_name).each do |hook|
rspec_context.instance_exec(&hook)
end
end

def hooks_for_object(filter_name)
config_hooks(filter_name) + object_hooks(filter_name)
end

def with_hooks(rspec_context)
instance = self

rspec_context.before(:context) do
instance.execute_hook(:before, self)
end

rspec_context.after(:context) do
instance.execute_hook(:after, self)
end

instance.execute_hook(:extend, rspec_context)

yield
end

private

def object_hooks(filter_name)
return [] unless respond_to?(:options)
option_name = "#{ filter_name }_#{ self.class.name.split('::').last.downcase }".to_sym
[ *options[option_name] ].compact

end

def config_hooks(filter_name)
Vigia.config.hooks.each_with_object([]) do |hook, collection|
next unless self.is_a?(hook[:rspec_class]) and filter_name == hook[:filter]
collection << hook[:block]
end
end
end
end
18 changes: 3 additions & 15 deletions lib/vigia/sail/example.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ def run
instance = self
rspec.it instance do
skip if instance.skip?(self) || (respond_to?(:skip?) and send(:skip?))
skip('__vigia__') if instance.disabled?(self) || (respond_to?(:disabled?) and send(:disabled?))

instance_exec(&instance.expectation)
unless instance.disabled?(self) || (respond_to?(:disabled?) and send(:disabled?))
instance_exec(&instance.expectation)
end
end
end

Expand All @@ -50,16 +51,3 @@ def disabled?(in_context)
end
end
end


Vigia::Sail::Example.register(
:code_match,
description: 'has the expected HTTP code',
expectation: -> { expect(result.code).to be(expectations.code) }
)

Vigia::Sail::Example.register(
:include_headers,
description: 'includes the expected headers',
expectation: -> { expect(result[:headers]).to include(expectations[:headers]) }
)
11 changes: 11 additions & 0 deletions lib/vigia/sail/examples/default.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Vigia::Sail::Example.register(
:code_match,
description: 'has the expected HTTP code',
expectation: -> { expect(result.code).to be(expectations.code) }
)

Vigia::Sail::Example.register(
:include_headers,
description: 'includes the expected headers',
expectation: -> { expect(result[:headers]).to include(expectations[:headers]) }
)
38 changes: 8 additions & 30 deletions lib/vigia/sail/rspec_object.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ module Vigia
module Sail
class RSpecObject
class << self
attr_accessor :collection
attr_reader :collection

def register(name, options)
@collection = {} if collection.nil?
@collection.merge!(name => options)
end

def setup_and_run(name, rspec)
name, options = collection.select{ |k,v| k == name }.first
Expand All @@ -11,6 +16,8 @@ def setup_and_run(name, rspec)
end
end

include Vigia::Hooks

attr_reader :name, :options, :rspec

def initialize(name, options, rspec)
Expand All @@ -20,22 +27,6 @@ def initialize(name, options, rspec)

end

def execute_hook(filter_name, rspec_context)
hooks_for_object(filter_name).each do |hook|
rspec_context.instance_exec(&hook)
end
end

def hooks_for_object(filter_name)
config_hooks(filter_name) + object_hooks(filter_name)
end

def with_hooks(rspec_context)
execute_hook(:before, rspec_context)
yield
execute_hook(:after, rspec_context)
end

def contextual_object(option_name: nil, object: nil, context: nil)
context ||= rspec.described_class
object ||= options[option_name]
Expand All @@ -55,19 +46,6 @@ def must_be_a_block(block, error_message)
return block if block.respond_to?(:call)
raise error_message
end

def object_hooks(filter_name)
option_name = "#{ filter_name }_#{ self.class.name.split('::').last.downcase }".to_sym
[ *options[option_name] ].compact

end

def config_hooks(filter_name)
Vigia.config.hooks.each_with_object([]) do |hook, collection|
next unless self.is_a?(hook[:rspec_class]) and filter_name == hook[:filter]
collection << hook[:block]
end
end
end
end
end
Loading

0 comments on commit 5c354f4

Please sign in to comment.