pacto 0.3.0.pre → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/.rubocop-todo.yml +0 -27
- data/.rubocop.yml +9 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +4 -5
- data/CONTRIBUTING.md +112 -0
- data/Gemfile +5 -0
- data/Guardfile +18 -13
- data/README.md +157 -101
- data/Rakefile +3 -3
- data/features/configuration/strict_matchers.feature +97 -0
- data/features/evolve/README.md +11 -0
- data/features/evolve/existing_services.feature +82 -0
- data/features/generate/README.md +5 -0
- data/features/generate/generation.feature +28 -0
- data/features/steps/pacto_steps.rb +75 -0
- data/features/stub/README.md +2 -0
- data/features/stub/templates.feature +46 -0
- data/features/support/env.rb +11 -5
- data/features/validate/README.md +1 -0
- data/features/validate/body_only.feature +85 -0
- data/features/{journeys/validation.feature → validate/meta_validation.feature} +41 -24
- data/features/validate/validation.feature +36 -0
- data/lib/pacto.rb +61 -33
- data/lib/pacto/contract.rb +18 -15
- data/lib/pacto/contract_factory.rb +14 -11
- data/lib/pacto/contract_files.rb +17 -0
- data/lib/pacto/contract_list.rb +17 -0
- data/lib/pacto/contract_validator.rb +29 -0
- data/lib/pacto/core/configuration.rb +19 -17
- data/lib/pacto/core/contract_registry.rb +43 -0
- data/lib/pacto/core/{callback.rb → hook.rb} +3 -3
- data/lib/pacto/core/modes.rb +33 -0
- data/lib/pacto/core/validation_registry.rb +45 -0
- data/lib/pacto/erb_processor.rb +0 -1
- data/lib/pacto/extensions.rb +18 -4
- data/lib/pacto/generator.rb +34 -49
- data/lib/pacto/generator/filters.rb +41 -0
- data/lib/pacto/hooks/erb_hook.rb +4 -3
- data/lib/pacto/logger.rb +4 -2
- data/lib/pacto/meta_schema.rb +4 -2
- data/lib/pacto/rake_task.rb +28 -25
- data/lib/pacto/request_clause.rb +43 -0
- data/lib/pacto/request_pattern.rb +8 -0
- data/lib/pacto/response_clause.rb +15 -0
- data/lib/pacto/rspec.rb +102 -0
- data/lib/pacto/stubs/uri_pattern.rb +23 -0
- data/lib/pacto/stubs/webmock_adapter.rb +69 -0
- data/lib/pacto/stubs/webmock_helper.rb +71 -0
- data/lib/pacto/ui.rb +7 -0
- data/lib/pacto/uri.rb +9 -0
- data/lib/pacto/validation.rb +57 -0
- data/lib/pacto/validators/body_validator.rb +41 -0
- data/lib/pacto/validators/request_body_validator.rb +23 -0
- data/lib/pacto/validators/response_body_validator.rb +23 -0
- data/lib/pacto/validators/response_header_validator.rb +49 -0
- data/lib/pacto/validators/response_status_validator.rb +24 -0
- data/lib/pacto/version.rb +1 -1
- data/pacto.gemspec +33 -29
- data/resources/contract_schema.json +8 -176
- data/resources/draft-03.json +174 -0
- data/spec/integration/data/strict_contract.json +2 -2
- data/spec/integration/e2e_spec.rb +22 -31
- data/spec/integration/rspec_spec.rb +94 -0
- data/spec/integration/templating_spec.rb +9 -12
- data/{lib → spec}/pacto/server.rb +0 -0
- data/{lib → spec}/pacto/server/dummy.rb +11 -8
- data/{lib → spec}/pacto/server/playback_servlet.rb +1 -1
- data/spec/spec_helper.rb +2 -0
- data/spec/unit/hooks/erb_hook_spec.rb +15 -15
- data/spec/unit/pacto/configuration_spec.rb +2 -10
- data/spec/unit/pacto/contract_factory_spec.rb +16 -13
- data/spec/unit/pacto/contract_files_spec.rb +42 -0
- data/spec/unit/pacto/contract_list_spec.rb +35 -0
- data/spec/unit/pacto/contract_spec.rb +43 -44
- data/spec/unit/pacto/contract_validator_spec.rb +85 -0
- data/spec/unit/pacto/core/configuration_spec.rb +4 -11
- data/spec/unit/pacto/core/contract_registry_spec.rb +119 -0
- data/spec/unit/pacto/core/modes_spec.rb +18 -0
- data/spec/unit/pacto/core/validation_registry_spec.rb +76 -0
- data/spec/unit/pacto/core/validation_spec.rb +60 -0
- data/spec/unit/pacto/extensions_spec.rb +14 -23
- data/spec/unit/pacto/generator/filters_spec.rb +99 -0
- data/spec/unit/pacto/generator_spec.rb +34 -73
- data/spec/unit/pacto/meta_schema_spec.rb +46 -6
- data/spec/unit/pacto/pacto_spec.rb +17 -15
- data/spec/unit/pacto/{request_spec.rb → request_clause_spec.rb} +32 -44
- data/spec/unit/pacto/request_pattern_spec.rb +22 -0
- data/spec/unit/pacto/response_clause_spec.rb +54 -0
- data/spec/unit/pacto/stubs/uri_pattern_spec.rb +28 -0
- data/spec/unit/pacto/stubs/webmock_adapter_spec.rb +205 -0
- data/spec/unit/pacto/stubs/webmock_helper_spec.rb +20 -0
- data/spec/unit/pacto/uri_spec.rb +20 -0
- data/spec/unit/pacto/validators/body_validator_spec.rb +105 -0
- data/spec/unit/pacto/validators/response_header_validator_spec.rb +94 -0
- data/spec/unit/pacto/validators/response_status_validator_spec.rb +20 -0
- metadata +230 -146
- data/features/generation/generation.feature +0 -25
- data/lib/pacto/core/contract_repository.rb +0 -44
- data/lib/pacto/hash_merge_processor.rb +0 -14
- data/lib/pacto/request.rb +0 -57
- data/lib/pacto/response.rb +0 -63
- data/lib/pacto/response_adapter.rb +0 -24
- data/lib/pacto/stubs/built_in.rb +0 -57
- data/spec/unit/pacto/core/contract_repository_spec.rb +0 -133
- data/spec/unit/pacto/hash_merge_processor_spec.rb +0 -20
- data/spec/unit/pacto/response_adapter_spec.rb +0 -25
- data/spec/unit/pacto/response_spec.rb +0 -201
- data/spec/unit/pacto/stubs/built_in_spec.rb +0 -168
@@ -0,0 +1,43 @@
|
|
1
|
+
module Pacto
|
2
|
+
class ContractRegistry
|
3
|
+
def initialize
|
4
|
+
@registry = Hash.new { |hash, key| hash[key] = Set.new }
|
5
|
+
end
|
6
|
+
|
7
|
+
def [](tag)
|
8
|
+
@registry[tag]
|
9
|
+
end
|
10
|
+
|
11
|
+
def register(contract, *tags)
|
12
|
+
tags << :default if tags.empty?
|
13
|
+
|
14
|
+
tags.each do |tag|
|
15
|
+
@registry[tag] << contract
|
16
|
+
end
|
17
|
+
|
18
|
+
self
|
19
|
+
end
|
20
|
+
|
21
|
+
def use(tag, values = {})
|
22
|
+
merged_contracts = @registry[:default] + @registry[tag]
|
23
|
+
|
24
|
+
fail ArgumentError, "contract \"#{tag}\" not found" if merged_contracts.empty?
|
25
|
+
|
26
|
+
merged_contracts.each do |contract|
|
27
|
+
contract.stub_contract! values
|
28
|
+
end
|
29
|
+
|
30
|
+
self
|
31
|
+
end
|
32
|
+
|
33
|
+
def contracts_for(request_signature)
|
34
|
+
all_contracts.select { |c| c.matches? request_signature }
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def all_contracts
|
40
|
+
@registry.values.inject(Set.new, :+)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
module Pacto
|
2
|
-
class
|
2
|
+
class Hook
|
3
3
|
def initialize(&block)
|
4
|
-
@
|
4
|
+
@hook = block
|
5
5
|
end
|
6
6
|
|
7
7
|
def process(contracts, request_signature, response)
|
8
|
-
@
|
8
|
+
@hook.call contracts, request_signature, response
|
9
9
|
end
|
10
10
|
end
|
11
11
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Pacto
|
2
|
+
class << self
|
3
|
+
def generate!
|
4
|
+
modes << :generate
|
5
|
+
end
|
6
|
+
|
7
|
+
def stop_generating!
|
8
|
+
modes.delete :generate
|
9
|
+
end
|
10
|
+
|
11
|
+
def generating?
|
12
|
+
modes.include? :generate
|
13
|
+
end
|
14
|
+
|
15
|
+
def validate!
|
16
|
+
modes << :validate
|
17
|
+
end
|
18
|
+
|
19
|
+
def stop_validating!
|
20
|
+
modes.delete :validate
|
21
|
+
end
|
22
|
+
|
23
|
+
def validating?
|
24
|
+
modes.include? :validate
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def modes
|
30
|
+
@modes ||= []
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Pacto
|
2
|
+
class ValidationRegistry
|
3
|
+
include Singleton
|
4
|
+
attr_reader :validations
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@validations = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def reset!
|
11
|
+
@validations.clear
|
12
|
+
end
|
13
|
+
|
14
|
+
def validated?(request_pattern)
|
15
|
+
matched_validations = @validations.select do |validation|
|
16
|
+
request_pattern.matches? validation.request
|
17
|
+
end
|
18
|
+
matched_validations unless matched_validations.empty?
|
19
|
+
end
|
20
|
+
|
21
|
+
def register_validation(validation)
|
22
|
+
@validations << validation
|
23
|
+
logger.info "Detected #{validation.summary}"
|
24
|
+
validation
|
25
|
+
end
|
26
|
+
|
27
|
+
def unmatched_validations
|
28
|
+
@validations.select do |validation|
|
29
|
+
validation.contract.nil?
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def failed_validations
|
34
|
+
@validations.select do |validation|
|
35
|
+
!validation.successful?
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def logger
|
42
|
+
@logger ||= Logger.instance
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/pacto/erb_processor.rb
CHANGED
data/lib/pacto/extensions.rb
CHANGED
@@ -1,12 +1,25 @@
|
|
1
1
|
module Pacto
|
2
2
|
module Extensions
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
# Adapted from Faraday
|
4
|
+
HeaderKeyMap = Hash.new do |map, key|
|
5
|
+
split_char = key.to_s.include?('-') ? '-' : '_'
|
6
|
+
map[key] = key.to_s.split(split_char). # :user_agent => %w(user agent)
|
7
|
+
each { |w| w.capitalize! }. # => %w(User Agent)
|
8
|
+
join('-') # => "User-Agent"
|
9
|
+
end
|
10
|
+
HeaderKeyMap[:etag] = 'ETag'
|
11
|
+
|
12
|
+
def self.normalize_header_keys(headers)
|
13
|
+
headers.reduce({}) do |normalized, (key, value)|
|
14
|
+
normalized[HeaderKeyMap[key]] = value
|
15
|
+
normalized
|
6
16
|
end
|
17
|
+
end
|
7
18
|
|
19
|
+
module HashSubsetOf
|
20
|
+
# FIXME: Only used by HashMergeProcessor, which I'd like to deprecate
|
8
21
|
def normalize_keys
|
9
|
-
|
22
|
+
reduce({}) do |normalized, (key, value)|
|
10
23
|
normalized[key.to_s.downcase] = value
|
11
24
|
normalized
|
12
25
|
end
|
@@ -15,4 +28,5 @@ module Pacto
|
|
15
28
|
end
|
16
29
|
end
|
17
30
|
|
31
|
+
# FIXME: Let's not extend Hash...
|
18
32
|
Hash.send(:include, Pacto::Extensions::HashSubsetOf)
|
data/lib/pacto/generator.rb
CHANGED
@@ -2,73 +2,58 @@ require 'json/schema_generator'
|
|
2
2
|
|
3
3
|
module Pacto
|
4
4
|
class Generator
|
5
|
-
attr_accessor :request_headers_to_filter
|
6
|
-
attr_accessor :response_headers_to_filter
|
7
|
-
|
8
|
-
INFORMATIONAL_REQUEST_HEADERS =
|
9
|
-
%w{
|
10
|
-
content-length
|
11
|
-
via
|
12
|
-
}
|
13
|
-
|
14
|
-
INFORMATIONAL_RESPONSE_HEADERS =
|
15
|
-
%w{
|
16
|
-
server
|
17
|
-
date
|
18
|
-
content-length
|
19
|
-
connection
|
20
|
-
}
|
21
|
-
|
22
5
|
def initialize(schema_version = 'draft3',
|
23
6
|
schema_generator = JSON::SchemaGenerator,
|
24
|
-
validator = Pacto::MetaSchema.new
|
7
|
+
validator = Pacto::MetaSchema.new,
|
8
|
+
generator_options = Pacto.configuration.generator_options,
|
9
|
+
filters = Pacto::Generator::Filters.new)
|
25
10
|
@schema_version = schema_version
|
26
11
|
@validator = validator
|
27
12
|
@schema_generator = schema_generator
|
28
|
-
@
|
29
|
-
@
|
30
|
-
end
|
31
|
-
|
32
|
-
def generate(request_file, host)
|
33
|
-
contract = Pacto.build_from_file request_file, host
|
34
|
-
request = contract.request
|
35
|
-
response = request.execute
|
36
|
-
save(request_file, request, response)
|
13
|
+
@generator_options = generator_options
|
14
|
+
@filters = filters
|
37
15
|
end
|
38
16
|
|
39
17
|
def save(source, request, response)
|
40
|
-
|
41
|
-
contract = {
|
42
|
-
:request => {
|
43
|
-
:headers => filter_request_headers(request.headers),
|
44
|
-
:method => request.method,
|
45
|
-
:params => request.params,
|
46
|
-
:path => request.path
|
47
|
-
},
|
48
|
-
:response => {
|
49
|
-
:headers => filter_response_headers(response.headers),
|
50
|
-
:status => response.status,
|
51
|
-
:body => MultiJson.load(body_schema)
|
52
|
-
}
|
53
|
-
}
|
18
|
+
contract = generate_contract source, request, response
|
54
19
|
pretty_contract = MultiJson.encode(contract, :pretty => true)
|
55
20
|
# This is because of a discrepency w/ jruby vs MRI pretty json
|
56
|
-
pretty_contract.gsub!
|
21
|
+
pretty_contract.gsub!(/^$\n/, '')
|
57
22
|
@validator.validate pretty_contract
|
58
23
|
pretty_contract
|
59
24
|
end
|
60
25
|
|
61
26
|
private
|
62
27
|
|
63
|
-
def
|
64
|
-
|
65
|
-
|
66
|
-
|
28
|
+
def generate_contract(source, request, response)
|
29
|
+
{
|
30
|
+
:request => generate_request(request, response, source),
|
31
|
+
:response => generate_response(request, response, source)
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
def generate_request(request, response, source)
|
36
|
+
{
|
37
|
+
:headers => @filters.filter_request_headers(request, response),
|
38
|
+
:method => request.method,
|
39
|
+
:params => request.params,
|
40
|
+
:path => request.path,
|
41
|
+
:body => generate_body(source, request.body)
|
42
|
+
}.delete_if { |k, v| v.nil? }
|
43
|
+
end
|
44
|
+
|
45
|
+
def generate_response(request, response, source)
|
46
|
+
{
|
47
|
+
:headers => @filters.filter_response_headers(request, response),
|
48
|
+
:status => response.status,
|
49
|
+
:body => generate_body(source, response.body)
|
50
|
+
}.delete_if { |k, v| v.nil? }
|
67
51
|
end
|
68
52
|
|
69
|
-
def
|
70
|
-
|
71
|
-
|
53
|
+
def generate_body(source, body)
|
54
|
+
if body && !body.empty?
|
55
|
+
body_schema = JSON::SchemaGenerator.generate source, body, @generator_options
|
56
|
+
MultiJson.load(body_schema)
|
72
57
|
end
|
73
58
|
end
|
74
59
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Pacto
|
2
|
+
class Generator
|
3
|
+
class Filters
|
4
|
+
CONNECTION_CONTROL_HEADERS = %w{
|
5
|
+
Via
|
6
|
+
Server
|
7
|
+
Connection
|
8
|
+
Transfer-Encoding
|
9
|
+
Content-Length
|
10
|
+
}
|
11
|
+
|
12
|
+
FRESHNESS_HEADERS =
|
13
|
+
%w{
|
14
|
+
Date
|
15
|
+
Last-Modified
|
16
|
+
ETag
|
17
|
+
}
|
18
|
+
|
19
|
+
HEADERS_TO_FILTER = CONNECTION_CONTROL_HEADERS + FRESHNESS_HEADERS
|
20
|
+
|
21
|
+
def filter_request_headers(request, response)
|
22
|
+
# FIXME: Do we need to handle all these cases in real situations, or just because of stubbing?
|
23
|
+
vary_headers = response.headers['Vary'] || []
|
24
|
+
vary_headers = [vary_headers] if vary_headers.is_a? String
|
25
|
+
vary_headers = vary_headers.map do |h|
|
26
|
+
h.split(',').map(&:strip)
|
27
|
+
end.flatten
|
28
|
+
|
29
|
+
request.headers.select do |header|
|
30
|
+
vary_headers.map(&:downcase).include? header.downcase
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def filter_response_headers(request, response)
|
35
|
+
Pacto::Extensions.normalize_header_keys(response.headers).reject do |header|
|
36
|
+
(HEADERS_TO_FILTER.include? header) || (header.start_with?('X-'))
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/pacto/hooks/erb_hook.rb
CHANGED
@@ -1,17 +1,18 @@
|
|
1
|
+
require_relative '../erb_processor'
|
2
|
+
|
1
3
|
module Pacto
|
2
4
|
module Hooks
|
3
|
-
class ERBHook < Pacto::
|
5
|
+
class ERBHook < Pacto::Hook
|
4
6
|
def initialize
|
5
7
|
@processor = ERBProcessor.new
|
6
8
|
end
|
7
9
|
|
8
10
|
def process(contracts, request_signature, response)
|
9
11
|
bound_values = contracts.empty? ? {} : contracts.first.values
|
10
|
-
bound_values.merge!(
|
12
|
+
bound_values.merge!(:req => { 'HEADERS' => request_signature.headers})
|
11
13
|
response.body = @processor.process response.body, bound_values
|
12
14
|
response.body
|
13
15
|
end
|
14
|
-
|
15
16
|
end
|
16
17
|
end
|
17
18
|
end
|
data/lib/pacto/logger.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
1
3
|
module Pacto
|
2
4
|
class Logger
|
3
5
|
include Singleton
|
@@ -9,13 +11,13 @@ module Pacto
|
|
9
11
|
log ::Logger.new STDOUT
|
10
12
|
end
|
11
13
|
|
12
|
-
def log
|
14
|
+
def log(log)
|
13
15
|
@log = log
|
14
16
|
@log.level = default_level
|
15
17
|
@log.progname = 'Pacto'
|
16
18
|
end
|
17
19
|
|
18
|
-
def level=
|
20
|
+
def level=(level)
|
19
21
|
@log.level = log_levels.fetch(level, default_level)
|
20
22
|
end
|
21
23
|
|
data/lib/pacto/meta_schema.rb
CHANGED
@@ -4,13 +4,15 @@ module Pacto
|
|
4
4
|
|
5
5
|
def initialize(engine = JSON::Validator)
|
6
6
|
@schema = File.join(File.dirname(File.expand_path(__FILE__)), '../../resources/contract_schema.json')
|
7
|
+
@base_schema = File.join(File.dirname(File.expand_path(__FILE__)), '../../resources/draft-03.json')
|
8
|
+
JSON::Validator.validate!(@base_schema, @schema)
|
7
9
|
@engine = engine
|
8
10
|
end
|
9
11
|
|
10
|
-
def validate
|
12
|
+
def validate(definition)
|
11
13
|
errors = engine.fully_validate(schema, definition, :version => :draft3)
|
12
14
|
unless errors.empty?
|
13
|
-
|
15
|
+
fail InvalidContract, errors
|
14
16
|
end
|
15
17
|
end
|
16
18
|
end
|
data/lib/pacto/rake_task.rb
CHANGED
@@ -1,13 +1,7 @@
|
|
1
1
|
require 'pacto'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
def colorize(*args)
|
6
|
-
self
|
7
|
-
end
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
3
|
+
# FIXME: RakeTask is a huge class, refactor this please
|
4
|
+
# rubocop:disable ClassLength
|
11
5
|
module Pacto
|
12
6
|
class RakeTask
|
13
7
|
include Rake::DSL
|
@@ -29,7 +23,7 @@ module Pacto
|
|
29
23
|
desc 'Validates all contracts in a given directory against a given host'
|
30
24
|
task :validate, :host, :dir do |t, args|
|
31
25
|
if args.to_a.size < 2
|
32
|
-
fail 'USAGE: rake pacto:validate[<host>, <contract_dir>]'
|
26
|
+
fail Pacto::UI.yellow('USAGE: rake pacto:validate[<host>, <contract_dir>]')
|
33
27
|
end
|
34
28
|
|
35
29
|
validate_contracts(args[:host], args[:dir])
|
@@ -40,24 +34,26 @@ module Pacto
|
|
40
34
|
desc 'Generates contracts from partial contracts'
|
41
35
|
task :generate, :input_dir, :output_dir, :host do |t, args|
|
42
36
|
if args.to_a.size < 3
|
43
|
-
fail 'USAGE: rake pacto:generate[<request_contract_dir>, <output_dir>, <record_host>]'
|
37
|
+
fail Pacto::UI.yellow('USAGE: rake pacto:generate[<request_contract_dir>, <output_dir>, <record_host>]')
|
44
38
|
end
|
45
39
|
|
46
40
|
generate_contracts(args[:input_dir], args[:output_dir], args[:host])
|
47
41
|
end
|
48
42
|
end
|
49
43
|
|
44
|
+
# FIXME: meta_validate is a big method =(. Needs refactoring
|
45
|
+
# rubocop:disable MethodLength
|
50
46
|
def meta_validate
|
51
47
|
desc 'Validates a directory of contract definitions'
|
52
48
|
task :meta_validate, :dir do |t, args|
|
53
49
|
if args.to_a.size < 1
|
54
|
-
fail 'USAGE: rake pacto:meta_validate[<contract_dir>]'
|
50
|
+
fail Pacto::UI.yellow('USAGE: rake pacto:meta_validate[<contract_dir>]')
|
55
51
|
end
|
56
52
|
|
57
53
|
each_contract(args[:dir]) do |contract_file|
|
58
|
-
puts "Validating #{contract_file}"
|
59
54
|
fail unless Pacto.validate_contract contract_file
|
60
55
|
end
|
56
|
+
puts 'All contracts successfully meta-validated'
|
61
57
|
end
|
62
58
|
end
|
63
59
|
|
@@ -66,31 +62,36 @@ module Pacto
|
|
66
62
|
puts "Validating contracts in directory #{dir} against host #{host}\n\n"
|
67
63
|
|
68
64
|
total_failed = 0
|
69
|
-
|
65
|
+
contracts = []
|
66
|
+
each_contract(dir) do |contract_file|
|
67
|
+
contracts << contract_file
|
70
68
|
print "#{contract_file.split('/').last}:"
|
71
|
-
contract = Pacto.
|
72
|
-
errors = contract.
|
69
|
+
contract = Pacto.load_contract(contract_file, host)
|
70
|
+
errors = contract.validate_provider
|
73
71
|
|
74
72
|
if errors.empty?
|
75
|
-
puts ' OK!'
|
73
|
+
puts Pacto::UI.green(' OK!')
|
76
74
|
else
|
77
75
|
@exit_with_error = true
|
78
76
|
total_failed += 1
|
79
|
-
puts ' FAILED!'
|
77
|
+
puts Pacto::UI.red(' FAILED!')
|
80
78
|
errors.each do |error|
|
81
|
-
puts "\t* #{error}"
|
79
|
+
puts Pacto::UI.red("\t* #{error}")
|
82
80
|
end
|
83
81
|
puts ''
|
84
82
|
end
|
85
83
|
end
|
86
84
|
|
87
85
|
if @exit_with_error
|
88
|
-
fail "#{total_failed} of #{contracts.size} failed. Check output for detailed error messages."
|
86
|
+
fail Pacto::UI.red("#{total_failed} of #{contracts.size} failed. Check output for detailed error messages.")
|
89
87
|
else
|
90
|
-
puts "#{contracts.size} valid contract#{contracts.size > 1 ? 's' : nil}"
|
88
|
+
puts Pacto::UI.green("#{contracts.size} valid contract#{contracts.size > 1 ? 's' : nil}")
|
91
89
|
end
|
92
90
|
end
|
91
|
+
# rubocop:enable MethodLength
|
93
92
|
|
93
|
+
# FIXME: generate_contracts is a big method =(. Needs refactoring
|
94
|
+
# rubocop:disable MethodLength
|
94
95
|
def generate_contracts(input_dir, output_dir, host)
|
95
96
|
WebMock.allow_net_connect!
|
96
97
|
generator = Pacto::Generator.new
|
@@ -107,16 +108,17 @@ module Pacto
|
|
107
108
|
output_file.close
|
108
109
|
rescue InvalidContract => e
|
109
110
|
failed_contracts << contract_file
|
110
|
-
puts e.message
|
111
|
+
puts Pacto::UI.red(e.message)
|
111
112
|
end
|
112
113
|
end
|
113
114
|
|
114
115
|
if failed_contracts.empty?
|
115
|
-
puts 'Successfully generated all contracts'
|
116
|
+
puts Pacto::UI.green('Successfully generated all contracts')
|
116
117
|
else
|
117
|
-
fail "The following contracts could not be generated: #{failed_contracts.join ','}"
|
118
|
+
fail Pacto::UI.red("The following contracts could not be generated: #{failed_contracts.join ','}")
|
118
119
|
end
|
119
120
|
end
|
121
|
+
# rubocop:enable MethodLength
|
120
122
|
|
121
123
|
private
|
122
124
|
|
@@ -124,8 +126,8 @@ module Pacto
|
|
124
126
|
if File.file? dir
|
125
127
|
yield dir
|
126
128
|
else
|
127
|
-
contracts = Dir[File.join(dir, '
|
128
|
-
fail "No contracts found in directory #{dir}"
|
129
|
+
contracts = Dir[File.join(dir, '**/*{.json.erb,.json}')]
|
130
|
+
fail Pacto::UI.yellow("No contracts found in directory #{dir}") if contracts.empty?
|
129
131
|
|
130
132
|
contracts.sort.each do |contract_file|
|
131
133
|
yield contract_file
|
@@ -134,5 +136,6 @@ module Pacto
|
|
134
136
|
end
|
135
137
|
end
|
136
138
|
end
|
139
|
+
# rubocop:enable ClassLength
|
137
140
|
|
138
141
|
Pacto::RakeTask.new.install
|