Skip to content
This repository has been archived by the owner on Dec 5, 2019. It is now read-only.

Commit

Permalink
Merge pull request #112 from thoughtworks/hashie
Browse files Browse the repository at this point in the history
Timeout: one week Request for Comment period expired
Tests passing... executing auto-merge...

(I need a bot)
  • Loading branch information
maxlinc committed Apr 26, 2014
2 parents 0356775 + 6e1e497 commit be93c91
Show file tree
Hide file tree
Showing 23 changed files with 154 additions and 102 deletions.
4 changes: 2 additions & 2 deletions features/configuration/strict_matchers.feature
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ Feature: Strict Matching

Scenario: Default (strict) behavior
When I run `bundle exec ruby requests.rb true`
Then the output should contain:
Then the stdout should contain:
"""
Pacto.configuration.strict_matchers = true
Expand All @@ -87,7 +87,7 @@ Feature: Strict Matching

Scenario: Non-strict matching
When I run `bundle exec ruby requests.rb false`
Then the output should contain:
Then the stdout should contain:
"""
Pacto.configuration.strict_matchers = false
Expand Down
6 changes: 3 additions & 3 deletions features/evolve/existing_services.feature
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Feature: Existing services journey
@no-clobber
Scenario: Ensuring all contracts are valid
When I successfully run `bundle exec rake pacto:meta_validate['contracts']`
Then the output should contain exactly:
Then the stdout should contain exactly:
"""
Validating contracts/www.example.com/service1.json
Validating contracts/www.example.com/service2.json
Expand All @@ -48,7 +48,7 @@ Feature: Existing services journey
puts Faraday.get('http://www.example.com/service2').body
"""
When I successfully run `bundle exec ruby test.rb`
Then the output should contain exactly:
Then the stdout should contain exactly:
"""
{"thoughtworks":"bar"}
{"service2":["bar"]}
Expand Down Expand Up @@ -76,7 +76,7 @@ Feature: Existing services journey
Faraday.get 'http://www.example.com/service1'
Faraday.get 'http://www.example.com/service2'
"""
Then the output should contain exactly:
Then the stdout should contain exactly:
"""
"""
4 changes: 2 additions & 2 deletions features/generate/generation.feature
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Feature: Contract Generation
Scenario: Generating a contract using the rake task
Given a directory named "contracts"
When I successfully run `bundle exec rake pacto:generate['tmp/aruba/requests','tmp/aruba/contracts','http://localhost:8000']`
Then the output should contain "Successfully generated all contracts"
Then the stdout should contain "Successfully generated all contracts"

Scenario: Generating a contract programmatically
Given a file named "generate.rb" with:
Expand All @@ -43,7 +43,7 @@ Feature: Contract Generation
puts contract
"""
When I successfully run `bundle exec ruby generate.rb`
Then the output should match this contract:
Then the stdout should match this contract:
"""json
{
"request": {
Expand Down
4 changes: 2 additions & 2 deletions features/steps/pacto_steps.rb
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
end
end

Then(/^the output should match this contract:$/) do |expected_contract|
actual_contract = all_output
Then(/^the stdout should match this contract:$/) do |expected_contract|
actual_contract = all_stdout
expect(actual_contract).to be_json_eql(expected_contract).excluding('description')
end
2 changes: 1 addition & 1 deletion features/stub/templates.feature
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ Feature: Templating

Scenario: ERB Template
When I request "http://example.com/hello"
Then the output should contain:
Then the stdout should contain:
"""
{"message":"!dlrow ,olleH"}
"""
2 changes: 2 additions & 0 deletions features/support/env.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
require 'pacto/test_helper'
require_relative '../../spec/pacto/dummy_server'

Pacto.configuration.hide_deprecations = true

Before do
# Given I successfully run `bundle install` can take a while.
@aruba_timeout_seconds = RUBY_PLATFORM == 'java' ? 60 : 10
Expand Down
2 changes: 1 addition & 1 deletion features/validate/body_only.feature
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ Feature: Validation
end
"""
When I run `bundle exec ruby validate.rb`
Then the output should contain:
Then the stdout should contain:
"""
Validated successfully!
"""
10 changes: 5 additions & 5 deletions features/validate/meta_validation.feature
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Feature: Meta-validation

Scenario: Meta-validation via a rake task
When I successfully run `bundle exec rake pacto:meta_validate['tmp/aruba/contracts/my_contract.json']`
Then the output should contain "All contracts successfully meta-validated"
Then the stdout should contain "All contracts successfully meta-validated"

Scenario: Programmatic meta-validation
Given a file named "meta_validate.rb" with:
Expand All @@ -46,7 +46,7 @@ Feature: Meta-validation
Pacto.validate_contract 'contracts/my_contract.json'
"""
When I successfully run `bundle exec ruby meta_validate.rb`
Then the output should contain "Validating contracts/my_contract.json"
Then the stdout should contain "Validating contracts/my_contract.json"

# The tests from here down should probably be specs instead of relish

Expand All @@ -57,7 +57,7 @@ Feature: Meta-validation
"""
When I run `bundle exec rake pacto:meta_validate['tmp/aruba/contracts/my_contract.json']`
Then the exit status should be 1
And the output should contain "did not match the following type"
And the stdout should contain "did not match the following type"


Scenario: Meta-validation of a contract with empty request and response
Expand All @@ -67,7 +67,7 @@ Feature: Meta-validation
"""
When I run `bundle exec rake pacto:meta_validate['tmp/aruba/contracts/my_contract.json']`
Then the exit status should be 1
And the output should contain "did not contain a required property"
And the stdout should contain "did not contain a required property"

Scenario: Meta-validation of a contracts response body
Given a file named "contracts/my_contract.json" with:
Expand All @@ -88,4 +88,4 @@ Feature: Meta-validation
"""
When I run `bundle exec rake pacto:meta_validate['tmp/aruba/contracts/my_contract.json']`
Then the exit status should be 1
And the output should contain "did not match the following type"
And the stdout should contain "did not match the following type"
2 changes: 1 addition & 1 deletion features/validate/validation.feature
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Feature: Validation
}
"""
When I successfully run `bundle exec rake pacto:validate['http://localhost:8000','tmp/aruba/contracts/simple_contract.json']`
Then the output should contain:
Then the stdout should contain:
""""
Validating contracts in directory tmp/aruba/contracts/simple_contract.json against host http://localhost:8000
Expand Down
5 changes: 3 additions & 2 deletions lib/pacto.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,19 @@
require 'addressable/template'
require 'middleware'
require 'faraday'
require 'hash_deep_merge'
require 'multi_json'
require 'json-schema'
require 'json-generator'
require 'webmock'
require 'ostruct'
require 'erb'
require 'logger'
require 'hashie/dash'
require 'hashie/extensions/coercion'

require 'pacto/logger'
require 'pacto/ui'
require 'pacto/request_pattern'
require 'pacto/core/contract_registry'
require 'pacto/core/validation_registry'
require 'pacto/core/configuration'
Expand All @@ -35,7 +37,6 @@
require 'pacto/generator/filters'
require 'pacto/contract_files'
require 'pacto/contract_list'
require 'pacto/request_pattern'
require 'pacto/uri'

# Validators
Expand Down
38 changes: 23 additions & 15 deletions lib/pacto/contract.rb
Original file line number Diff line number Diff line change
@@ -1,25 +1,29 @@
module Pacto
class Contract
attr_reader :name, :values, :request, :response, :file, :request_pattern

def initialize(request, response, file, name = nil, request_pattern_provider = RequestPattern)
@request = request
@response = response
@file = Addressable::URI.convert_path(file.to_s).to_s
@name = name || @file
@request_pattern = request_pattern_provider.for(request)
@values = {}
class Contract < Hashie::Dash
include Hashie::Extensions::Coercion
property :file, required: true
property :request, required: true
property :response, required: true
property :values, default: {}
# Gotta figure out how to use test doubles w/ coercion
coerce_key :request, RequestClause
coerce_key :response, ResponseClause
property :name
property :request_pattern_provider, default: Pacto::RequestPattern

def initialize(opts)
opts[:file] = Addressable::URI.convert_path(opts[:file].to_s).to_s
opts[:name] ||= opts[:file]
super
end

def stub_contract!(values = {})
@values = values
self.values = values
Pacto.configuration.provider.stub_request!(request, response)
end

def validate_provider(opts = {})
request = @request
response = provider_response
validate_consumer request, response, opts
validate_consumer request, provider_response, opts
end

def validate_consumer(request, response, opts = {})
Expand All @@ -30,10 +34,14 @@ def matches?(request_signature)
request_pattern.matches? request_signature
end

def request_pattern
@request_pattern ||= request_pattern_provider.for(request)
end

private

def provider_response
@request.execute
request.execute
end
end
end
18 changes: 16 additions & 2 deletions lib/pacto/contract_factory.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module Pacto
class ContractFactory
include Logger
attr_reader :schema

def initialize(options = {})
Expand All @@ -14,9 +15,22 @@ def build_from_file(contract_path, host)
contract_definition = File.read(contract_path)
definition = JSON.parse(contract_definition)
schema.validate definition
request = RequestClause.new(host, definition['request'])
definition['request'].merge!('host' => host)
body_to_schema(definition, 'request')
body_to_schema(definition, 'response')
request = RequestClause.new(definition['request'])
response = ResponseClause.new(definition['response'])
Contract.new(request, response, contract_path, definition['name'])
Contract.new(request: request, response: response, file: contract_path, name: definition['name'])
end

private

def body_to_schema(definition, section)
schema = definition[section].delete 'body'
if schema
Pacto::UI.deprecation "Contract format deprecation: #{section}:body will be moved to #{section}:schema"
definition[section]['schema'] = schema
end
end
end
end
2 changes: 1 addition & 1 deletion lib/pacto/core/configuration.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module Pacto
class Configuration
attr_accessor :provider, :strict_matchers,
:contracts_path, :logger, :generator_options
:contracts_path, :logger, :generator_options, :hide_deprecations
attr_reader :hook

def initialize
Expand Down
43 changes: 22 additions & 21 deletions lib/pacto/request_clause.rb
Original file line number Diff line number Diff line change
@@ -1,33 +1,25 @@
module Pacto
class RequestClause
attr_reader :host, :method, :schema
attr_accessor :body
class RequestClause < Hashie::Dash
include Hashie::Extensions::Coercion
# include Hashie::Extensions::IndifferentAccess # remove this if we cleanup string vs symbol
property :host # required?
property :method, required: true
property :schema, default: {}
property :path
property :headers
property :params, default: {}

def initialize(host, definition)
@host = host
@definition = definition
@method = definition['method'].to_s.downcase.to_sym
@schema = definition['body'] || {}
def initialize(definition)
definition['method'] = definition['method'].to_s.downcase.to_sym
super
end

def uri
@uri ||= Pacto::URI.for(host, path, params)
end

def body
JSON::Generator.generate(@definition['body']) if @definition['body']
end

def path
@definition['path']
end

def headers
@definition['headers']
end

def params
@definition['params'] || {}
JSON::Generator.generate(schema)
end

def execute
Expand All @@ -39,5 +31,14 @@ def execute
req.headers = headers
end
end

# FIXME: Send a PR to Hashie so it doesn't coerce values that already match the target class
def self.coerce(value)
if value.is_a? self
value
else
RequestClause.new value
end
end
end
end
12 changes: 4 additions & 8 deletions lib/pacto/response_clause.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
module Pacto
class ResponseClause
attr_reader :status, :headers, :schema

def initialize(definition)
@status = definition['status']
@headers = definition['headers']
@schema = definition['body'] || {}
end
class ResponseClause < Hashie::Dash
property :status
property :headers
property :schema, default: {}

def body
@body ||= JSON::Generator.generate(schema)
Expand Down
4 changes: 4 additions & 0 deletions lib/pacto/ui.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,9 @@
module Pacto
module UI
extend Term::ANSIColor

def self.deprecation(msg)
$stderr.puts yellow(msg) unless Pacto.configuration.hide_deprecations
end
end
end
2 changes: 1 addition & 1 deletion pacto.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Gem::Specification.new do |gem|
gem.add_dependency 'multi_json', '~> 1.8'
gem.add_dependency 'json-schema', '~> 2.0'
gem.add_dependency 'json-generator', '~> 0.0', '>= 0.0.5'
gem.add_dependency 'hash-deep-merge', '~> 0.1'
gem.add_dependency 'hashie', '~> 2.1'
gem.add_dependency 'faraday', '~> 0.9'
gem.add_dependency 'addressable', '~> 2.3'
gem.add_dependency 'json-schema-generator', '~> 0.0', '>= 0.0.7'
Expand Down

0 comments on commit be93c91

Please sign in to comment.