pacto 0.4.0.rc1 → 0.4.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/Gemfile +2 -7
- data/Rakefile +0 -5
- data/appveyor.yml +12 -0
- data/features/configuration/strict_matchers.feature +4 -4
- data/features/generate/generation.feature +8 -10
- data/features/support/env.rb +3 -7
- data/features/validate/validation.feature +3 -3
- data/lib/pacto.rb +5 -4
- data/lib/pacto/actors/json_generator.rb +1 -1
- data/lib/pacto/body_parsing.rb +42 -0
- data/lib/pacto/consumer/faraday_driver.rb +5 -2
- data/lib/pacto/contract.rb +23 -24
- data/lib/pacto/contract_factory.rb +4 -4
- data/lib/pacto/core/configuration.rb +18 -10
- data/lib/pacto/core/http_middleware.rb +1 -1
- data/lib/pacto/core/pacto_request.rb +3 -15
- data/lib/pacto/core/pacto_response.rb +3 -13
- data/lib/pacto/errors.rb +68 -0
- data/lib/pacto/formats/legacy/contract.rb +49 -0
- data/lib/pacto/formats/legacy/contract_builder.rb +129 -0
- data/lib/pacto/formats/legacy/contract_factory.rb +63 -0
- data/lib/pacto/formats/legacy/contract_generator.rb +77 -0
- data/lib/pacto/formats/legacy/generator/filters.rb +46 -0
- data/lib/pacto/formats/legacy/generator_hint.rb +36 -0
- data/lib/pacto/formats/legacy/request_clause.rb +39 -0
- data/lib/pacto/formats/legacy/response_clause.rb +31 -0
- data/lib/pacto/formats/swagger/contract.rb +86 -0
- data/lib/pacto/formats/swagger/contract_factory.rb +45 -0
- data/lib/pacto/formats/swagger/request_clause.rb +53 -0
- data/lib/pacto/formats/swagger/response_clause.rb +31 -0
- data/lib/pacto/generator.rb +4 -4
- data/lib/pacto/handlers/json_handler.rb +19 -0
- data/lib/pacto/handlers/text_handler.rb +17 -0
- data/lib/pacto/request_clause.rb +9 -19
- data/lib/pacto/response_clause.rb +4 -4
- data/lib/pacto/server.rb +41 -2
- data/lib/pacto/stubs/uri_pattern.rb +5 -5
- data/lib/pacto/stubs/webmock_adapter.rb +4 -1
- data/lib/pacto/test_helper.rb +16 -13
- data/lib/pacto/version.rb +1 -1
- data/pacto-server.gemspec +1 -3
- data/pacto.gemspec +1 -1
- data/sample_apis/user_api.rb +16 -0
- data/samples/contracts/user.json +51 -0
- data/samples/cops.rb +3 -0
- data/samples/server_cli.sh +3 -3
- data/spec/fabricators/contract_fabricator.rb +17 -8
- data/spec/fixtures/{deprecated_contracts → contracts/deprecated}/deprecated_contract.json +2 -2
- data/spec/fixtures/contracts/{contract.json → legacy/contract.json} +0 -0
- data/spec/fixtures/contracts/{contract_with_examples.json → legacy/contract_with_examples.json} +0 -0
- data/spec/fixtures/contracts/{simple_contract.json → legacy/simple_contract.json} +1 -1
- data/spec/fixtures/contracts/{strict_contract.json → legacy/strict_contract.json} +0 -0
- data/spec/fixtures/contracts/{templating_contract.json → legacy/templating_contract.json} +0 -0
- data/spec/fixtures/{swagger → contracts/swagger}/petstore.yaml +0 -0
- data/spec/integration/e2e_spec.rb +6 -12
- data/spec/integration/forensics/integration_matcher_spec.rb +5 -11
- data/spec/integration/rspec_spec.rb +12 -12
- data/spec/integration/templating_spec.rb +1 -1
- data/spec/spec_helper.rb +14 -2
- data/spec/unit/pacto/contract_factory_spec.rb +1 -2
- data/spec/unit/pacto/contract_spec.rb +44 -70
- data/spec/unit/pacto/core/investigation_spec.rb +4 -3
- data/spec/unit/pacto/formats/legacy/contract_builder_spec.rb +93 -0
- data/spec/unit/pacto/formats/legacy/contract_factory_spec.rb +29 -0
- data/spec/unit/pacto/formats/legacy/contract_generator_spec.rb +173 -0
- data/spec/unit/pacto/formats/legacy/contract_spec.rb +41 -0
- data/spec/unit/pacto/formats/legacy/generator/filters_spec.rb +104 -0
- data/spec/unit/pacto/formats/legacy/request_clause_spec.rb +79 -0
- data/spec/unit/pacto/formats/legacy/response_clause_spec.rb +45 -0
- data/spec/unit/pacto/formats/swagger/contract_factory_spec.rb +58 -0
- data/spec/unit/pacto/formats/swagger/contract_spec.rb +47 -0
- data/spec/unit/pacto/investigation_registry_spec.rb +1 -2
- data/spec/unit/pacto/pacto_spec.rb +6 -4
- data/spec/unit/pacto/stubs/uri_pattern_spec.rb +7 -8
- data/spec/unit/pacto/stubs/webmock_adapter_spec.rb +2 -4
- data/tasks/release.rake +1 -1
- metadata +53 -53
- data/lib/pacto/contract_builder.rb +0 -125
- data/lib/pacto/exceptions/invalid_contract.rb +0 -12
- data/lib/pacto/generator/filters.rb +0 -42
- data/lib/pacto/generator/hint.rb +0 -26
- data/lib/pacto/generator/native_contract_generator.rb +0 -74
- data/lib/pacto/native_contract_factory.rb +0 -60
- data/lib/pacto/swagger_contract_factory.rb +0 -90
- data/spec/pacto/dummy_server.rb +0 -4
- data/spec/pacto/dummy_server/dummy.rb +0 -51
- data/spec/pacto/dummy_server/jruby_workaround_helper.rb +0 -23
- data/spec/pacto/dummy_server/playback_servlet.rb +0 -22
- data/spec/unit/pacto/contract_builder_spec.rb +0 -89
- data/spec/unit/pacto/generator/filters_spec.rb +0 -100
- data/spec/unit/pacto/generator/native_contract_generator_spec.rb +0 -171
- data/spec/unit/pacto/native_contract_factory_spec.rb +0 -26
- data/spec/unit/pacto/request_clause_spec.rb +0 -75
- data/spec/unit/pacto/response_clause_spec.rb +0 -41
- data/spec/unit/pacto/server/playback_servlet_spec.rb +0 -27
- data/spec/unit/pacto/swagger_contract_factory_spec.rb +0 -56
@@ -6,6 +6,8 @@ module Pacto
|
|
6
6
|
# FIXME: Need case insensitive header lookup, but case-sensitive storage
|
7
7
|
attr_accessor :headers, :body, :method, :uri
|
8
8
|
|
9
|
+
include BodyParsing
|
10
|
+
|
9
11
|
def initialize(data)
|
10
12
|
mash = Hashie::Mash.new data
|
11
13
|
@headers = mash.headers.nil? ? {} : mash.headers
|
@@ -27,7 +29,7 @@ module Pacto
|
|
27
29
|
def to_s
|
28
30
|
string = Pacto::UI.colorize_method(method)
|
29
31
|
string << " #{relative_uri}"
|
30
|
-
string << " with body (#{
|
32
|
+
string << " with body (#{raw_body.bytesize} bytes)" if raw_body
|
31
33
|
string
|
32
34
|
end
|
33
35
|
|
@@ -37,20 +39,6 @@ module Pacto
|
|
37
39
|
end
|
38
40
|
end
|
39
41
|
|
40
|
-
def parsed_body
|
41
|
-
if body.is_a?(String) && content_type == 'application/json'
|
42
|
-
JSON.parse(body)
|
43
|
-
else
|
44
|
-
body
|
45
|
-
end
|
46
|
-
rescue
|
47
|
-
body
|
48
|
-
end
|
49
|
-
|
50
|
-
def content_type
|
51
|
-
headers['Content-Type']
|
52
|
-
end
|
53
|
-
|
54
42
|
def normalize
|
55
43
|
@method = @method.to_s.downcase.to_sym
|
56
44
|
@uri = @uri.normalize if @uri
|
@@ -5,6 +5,8 @@ module Pacto
|
|
5
5
|
attr_accessor :headers, :body, :status, :parsed_body
|
6
6
|
attr_reader :parsed_body
|
7
7
|
|
8
|
+
include BodyParsing
|
9
|
+
|
8
10
|
def initialize(data)
|
9
11
|
mash = Hashie::Mash.new data
|
10
12
|
@headers = mash.headers.nil? ? {} : mash.headers
|
@@ -22,20 +24,8 @@ module Pacto
|
|
22
24
|
|
23
25
|
def to_s
|
24
26
|
string = "STATUS: #{status}"
|
25
|
-
string << " with body (#{
|
27
|
+
string << " with body (#{raw_body.bytesize} bytes)" if raw_body
|
26
28
|
string
|
27
29
|
end
|
28
|
-
|
29
|
-
def parsed_body
|
30
|
-
if body.is_a?(String) && content_type == 'application/json'
|
31
|
-
JSON.parse(body)
|
32
|
-
else
|
33
|
-
body
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def content_type
|
38
|
-
headers['Content-Type']
|
39
|
-
end
|
40
30
|
end
|
41
31
|
end
|
data/lib/pacto/errors.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
module Pacto
|
2
|
+
class InvalidContract < ArgumentError
|
3
|
+
attr_reader :errors
|
4
|
+
|
5
|
+
def initialize(errors)
|
6
|
+
@errors = errors
|
7
|
+
end
|
8
|
+
|
9
|
+
def message
|
10
|
+
@errors.join "\n"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module Errors
|
15
|
+
# Creates an array of strings, representing a formatted exception,
|
16
|
+
# containing backtrace and nested exception info as necessary, that can
|
17
|
+
# be viewed by a human.
|
18
|
+
#
|
19
|
+
# For example:
|
20
|
+
#
|
21
|
+
# ------Exception-------
|
22
|
+
# Class: Crosstest::StandardError
|
23
|
+
# Message: Failure starting the party
|
24
|
+
# ---Nested Exception---
|
25
|
+
# Class: IOError
|
26
|
+
# Message: not enough directories for a party
|
27
|
+
# ------Backtrace-------
|
28
|
+
# nil
|
29
|
+
# ----------------------
|
30
|
+
#
|
31
|
+
# @param exception [::StandardError] an exception
|
32
|
+
# @return [Array<String>] a formatted message
|
33
|
+
def self.formatted_trace(exception)
|
34
|
+
arr = formatted_exception(exception).dup
|
35
|
+
last = arr.pop
|
36
|
+
if exception.respond_to?(:original) && exception.original
|
37
|
+
arr += formatted_exception(exception.original, 'Nested Exception')
|
38
|
+
last = arr.pop
|
39
|
+
end
|
40
|
+
arr += ['Backtrace'.center(22, '-'), exception.backtrace, last].flatten
|
41
|
+
arr
|
42
|
+
end
|
43
|
+
|
44
|
+
# Creates an array of strings, representing a formatted exception that
|
45
|
+
# can be viewed by a human. Thanks to MiniTest for the inspiration
|
46
|
+
# upon which this output has been designed.
|
47
|
+
#
|
48
|
+
# For example:
|
49
|
+
#
|
50
|
+
# ------Exception-------
|
51
|
+
# Class: Crosstest::StandardError
|
52
|
+
# Message: I have failed you
|
53
|
+
# ----------------------
|
54
|
+
#
|
55
|
+
# @param exception [::StandardError] an exception
|
56
|
+
# @param title [String] a custom title for the message
|
57
|
+
# (default: `"Exception"`)
|
58
|
+
# @return [Array<String>] a formatted message
|
59
|
+
def self.formatted_exception(exception, title = 'Exception')
|
60
|
+
[
|
61
|
+
title.center(22, '-'),
|
62
|
+
"Class: #{exception.class}",
|
63
|
+
"Message: #{exception.message}",
|
64
|
+
''.center(22, '-')
|
65
|
+
]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'pacto/formats/legacy/request_clause'
|
3
|
+
require 'pacto/formats/legacy/response_clause'
|
4
|
+
|
5
|
+
module Pacto
|
6
|
+
module Formats
|
7
|
+
module Legacy
|
8
|
+
class Contract < Pacto::Dash
|
9
|
+
include Pacto::Contract
|
10
|
+
|
11
|
+
property :id
|
12
|
+
property :file
|
13
|
+
property :request, required: true
|
14
|
+
# Although I'd like response to be required, it complicates
|
15
|
+
# the partial contracts used the rake generation task...
|
16
|
+
# yet another reason I'd like to deprecate that feature
|
17
|
+
property :response # , required: true
|
18
|
+
property :values, default: {}
|
19
|
+
# Gotta figure out how to use test doubles w/ coercion
|
20
|
+
coerce_key :request, RequestClause
|
21
|
+
coerce_key :response, ResponseClause
|
22
|
+
property :examples
|
23
|
+
property :name, required: true
|
24
|
+
property :adapter, default: proc { Pacto.configuration.adapter }
|
25
|
+
property :consumer, default: proc { Pacto.configuration.default_consumer }
|
26
|
+
property :provider, default: proc { Pacto.configuration.default_provider }
|
27
|
+
|
28
|
+
def initialize(opts)
|
29
|
+
skip_freeze = opts.delete(:skip_freeze)
|
30
|
+
|
31
|
+
if opts[:file]
|
32
|
+
opts[:file] = Addressable::URI.convert_path(File.expand_path(opts[:file])).to_s
|
33
|
+
opts[:name] ||= opts[:file]
|
34
|
+
end
|
35
|
+
opts[:id] ||= (opts[:summary] || opts[:file])
|
36
|
+
super
|
37
|
+
freeze unless skip_freeze
|
38
|
+
end
|
39
|
+
|
40
|
+
def freeze
|
41
|
+
(keys.map(&:to_sym) - [:values, :adapter, :consumer, :provider]).each do | key |
|
42
|
+
send(key).freeze
|
43
|
+
end
|
44
|
+
self
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module Pacto
|
3
|
+
module Formats
|
4
|
+
module Legacy
|
5
|
+
class ContractBuilder < Hashie::Dash # rubocop:disable Metrics/ClassLength
|
6
|
+
extend Forwardable
|
7
|
+
attr_accessor :source
|
8
|
+
|
9
|
+
def initialize(options = {})
|
10
|
+
@schema_generator = options[:schema_generator] ||= JSON::SchemaGenerator
|
11
|
+
@filters = options[:filters] ||= Generator::Filters.new
|
12
|
+
@data = { request: {}, response: {}, examples: {} }
|
13
|
+
@source = 'Pacto' # Currently used by JSONSchemaGeneator, but not really useful
|
14
|
+
end
|
15
|
+
|
16
|
+
def name=(name)
|
17
|
+
@data[:name] = name
|
18
|
+
end
|
19
|
+
|
20
|
+
def add_example(name, pacto_request, pacto_response)
|
21
|
+
@data[:examples][name] ||= {}
|
22
|
+
@data[:examples][name][:request] = clean(pacto_request.to_hash)
|
23
|
+
@data[:examples][name][:response] = clean(pacto_response.to_hash)
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
def infer_all
|
28
|
+
# infer_file # The target file is being chosen inferred by the Generator
|
29
|
+
infer_name
|
30
|
+
infer_schemas
|
31
|
+
end
|
32
|
+
|
33
|
+
def infer_name
|
34
|
+
if @data[:examples].empty?
|
35
|
+
@data[:name] = @data[:request][:path] if @data[:request]
|
36
|
+
return self
|
37
|
+
end
|
38
|
+
|
39
|
+
example, hint = example_and_hint
|
40
|
+
@data[:name] = hint.nil? ? PactoRequest.new(example[:request]).uri.path : hint.service_name
|
41
|
+
self
|
42
|
+
end
|
43
|
+
|
44
|
+
def infer_schemas
|
45
|
+
return self if @data[:examples].empty?
|
46
|
+
|
47
|
+
# TODO: It'd be awesome if we could infer across all examples
|
48
|
+
example, _hint = example_and_hint
|
49
|
+
sample_request_body = example[:request][:body]
|
50
|
+
sample_response_body = example[:response][:body]
|
51
|
+
@data[:request][:schema] = generate_schema(sample_request_body) if sample_request_body && !sample_request_body.empty?
|
52
|
+
@data[:response][:schema] = generate_schema(sample_response_body) if sample_response_body && !sample_response_body.empty?
|
53
|
+
self
|
54
|
+
end
|
55
|
+
|
56
|
+
def without_examples
|
57
|
+
@export_examples = false
|
58
|
+
self
|
59
|
+
end
|
60
|
+
|
61
|
+
def generate_contract(request, response)
|
62
|
+
generate_request(request, response)
|
63
|
+
generate_response(request, response)
|
64
|
+
infer_all
|
65
|
+
self
|
66
|
+
end
|
67
|
+
|
68
|
+
def generate_request(request, response)
|
69
|
+
hint = hint_for(request)
|
70
|
+
request = clean(
|
71
|
+
headers: @filters.filter_request_headers(request, response),
|
72
|
+
http_method: request.method,
|
73
|
+
params: request.uri.query_values,
|
74
|
+
path: hint.nil? ? request.uri.path : hint.path
|
75
|
+
)
|
76
|
+
@data[:request] = request
|
77
|
+
self
|
78
|
+
end
|
79
|
+
|
80
|
+
def generate_response(request, response)
|
81
|
+
response = clean(
|
82
|
+
headers: @filters.filter_response_headers(request, response),
|
83
|
+
status: response.status
|
84
|
+
)
|
85
|
+
@data[:response] = response
|
86
|
+
self
|
87
|
+
end
|
88
|
+
|
89
|
+
def build_hash
|
90
|
+
instance_eval(&block) if block_given?
|
91
|
+
@final_data = @data.dup
|
92
|
+
@final_data.delete(:examples) if exclude_examples?
|
93
|
+
clean(@final_data)
|
94
|
+
end
|
95
|
+
|
96
|
+
def build(&block)
|
97
|
+
Contract.new build_hash(&block)
|
98
|
+
end
|
99
|
+
|
100
|
+
protected
|
101
|
+
|
102
|
+
def example_and_hint
|
103
|
+
example = @data[:examples].values.first
|
104
|
+
example_request = PactoRequest.new example[:request]
|
105
|
+
[example, Pacto::Generator.hint_for(example_request)]
|
106
|
+
end
|
107
|
+
|
108
|
+
def exclude_examples?
|
109
|
+
@export_examples == false
|
110
|
+
end
|
111
|
+
|
112
|
+
def generate_schema(body, generator_options = Pacto.configuration.generator_options)
|
113
|
+
return if body.nil? || body.empty?
|
114
|
+
|
115
|
+
body_schema = @schema_generator.generate @source, body, generator_options
|
116
|
+
MultiJson.load(body_schema)
|
117
|
+
end
|
118
|
+
|
119
|
+
def clean(data)
|
120
|
+
data.delete_if { |_k, v| v.nil? }
|
121
|
+
end
|
122
|
+
|
123
|
+
def hint_for(pacto_request)
|
124
|
+
Pacto::Generator.hint_for(pacto_request)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'pacto/formats/legacy/contract'
|
3
|
+
|
4
|
+
module Pacto
|
5
|
+
module Formats
|
6
|
+
module Legacy
|
7
|
+
# Builds {Pacto::Formats::Legacy::Contract} instances from Pacto's legacy Contract format.
|
8
|
+
class ContractFactory
|
9
|
+
attr_reader :schema
|
10
|
+
|
11
|
+
def initialize(options = {})
|
12
|
+
@schema = options[:schema] || MetaSchema.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def build_from_file(contract_path, host)
|
16
|
+
contract_definition = File.read(contract_path)
|
17
|
+
definition = JSON.parse(contract_definition)
|
18
|
+
schema.validate definition
|
19
|
+
definition['request'].merge!('host' => host)
|
20
|
+
body_to_schema(definition, 'request', contract_path)
|
21
|
+
body_to_schema(definition, 'response', contract_path)
|
22
|
+
method_to_http_method(definition, contract_path)
|
23
|
+
request = RequestClause.new(definition['request'])
|
24
|
+
response = ResponseClause.new(definition['response'])
|
25
|
+
Contract.new(request: request, response: response, file: contract_path, name: definition['name'], examples: definition['examples'])
|
26
|
+
end
|
27
|
+
|
28
|
+
def files_for(contracts_dir)
|
29
|
+
full_path = Pathname.new(contracts_dir).realpath
|
30
|
+
|
31
|
+
if full_path.directory?
|
32
|
+
all_json_files = "#{full_path}/**/*.json"
|
33
|
+
Dir.glob(all_json_files).map do |f|
|
34
|
+
Pathname.new(f)
|
35
|
+
end
|
36
|
+
else
|
37
|
+
[full_path]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def body_to_schema(definition, section, file)
|
44
|
+
schema = definition[section].delete 'body'
|
45
|
+
return nil unless schema
|
46
|
+
|
47
|
+
Pacto::UI.deprecation "Contract format deprecation: #{section}:body will be moved to #{section}:schema (#{file})"
|
48
|
+
definition[section]['schema'] = schema
|
49
|
+
end
|
50
|
+
|
51
|
+
def method_to_http_method(definition, file)
|
52
|
+
method = definition['request'].delete 'method'
|
53
|
+
return nil unless method
|
54
|
+
|
55
|
+
Pacto::UI.deprecation "Contract format deprecation: request:method will be moved to request:http_method (#{file})"
|
56
|
+
definition['request']['http_method'] = method
|
57
|
+
end
|
58
|
+
|
59
|
+
Pacto::ContractFactory.add_factory(:legacy, ContractFactory.new)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'json/schema_generator'
|
3
|
+
require 'pacto/formats/legacy/contract_builder'
|
4
|
+
require 'pacto/formats/legacy/generator/filters'
|
5
|
+
|
6
|
+
module Pacto
|
7
|
+
module Formats
|
8
|
+
module Legacy
|
9
|
+
class ContractGenerator
|
10
|
+
include Logger
|
11
|
+
|
12
|
+
def initialize(_schema_version = 'draft3',
|
13
|
+
schema_generator = JSON::SchemaGenerator,
|
14
|
+
validator = Pacto::MetaSchema.new,
|
15
|
+
filters = Generator::Filters.new,
|
16
|
+
consumer = Pacto::Consumer.new)
|
17
|
+
@contract_builder = ContractBuilder.new(schema_generator: schema_generator, filters: filters)
|
18
|
+
@consumer = consumer
|
19
|
+
@validator = validator
|
20
|
+
end
|
21
|
+
|
22
|
+
def generate(pacto_request, pacto_response)
|
23
|
+
return unless Pacto.generating?
|
24
|
+
logger.debug("Generating Contract for #{pacto_request}, #{pacto_response}")
|
25
|
+
begin
|
26
|
+
contract_file = load_contract_file(pacto_request)
|
27
|
+
|
28
|
+
unless File.exist? contract_file
|
29
|
+
uri = URI(pacto_request.uri)
|
30
|
+
FileUtils.mkdir_p(File.dirname contract_file)
|
31
|
+
raw_contract = save(uri, pacto_request, pacto_response)
|
32
|
+
File.write(contract_file, raw_contract)
|
33
|
+
logger.debug("Generating #{contract_file}")
|
34
|
+
|
35
|
+
Pacto.load_contract contract_file, uri.host
|
36
|
+
end
|
37
|
+
rescue => e
|
38
|
+
raise StandardError, "Error while generating Contract #{contract_file}: #{e.message}", e.backtrace
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def generate_from_partial_contract(request_file, host)
|
43
|
+
contract = Pacto.load_contract request_file, host
|
44
|
+
request, response = @consumer.request(contract)
|
45
|
+
save(request_file, request, response)
|
46
|
+
end
|
47
|
+
|
48
|
+
def save(source, request, response)
|
49
|
+
@contract_builder.source = source
|
50
|
+
# TODO: Get rid of the generate_contract call, just use add_example/infer_all
|
51
|
+
@contract_builder.add_example('default', request, response).generate_contract(request, response) # .infer_all
|
52
|
+
@contract_builder.without_examples if Pacto.configuration.generator_options[:no_examples]
|
53
|
+
contract = @contract_builder.build_hash
|
54
|
+
pretty_contract = MultiJson.encode(contract, pretty: true)
|
55
|
+
# This is because of a discrepency w/ jruby vs MRI pretty json
|
56
|
+
pretty_contract.gsub!(/^$\n/, '')
|
57
|
+
@validator.validate pretty_contract
|
58
|
+
pretty_contract
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def load_contract_file(pacto_request)
|
64
|
+
hint = Pacto::Generator.hint_for(pacto_request)
|
65
|
+
if hint.nil?
|
66
|
+
uri = URI(pacto_request.uri)
|
67
|
+
path = uri.path
|
68
|
+
basename = File.basename(path, '.json') + '.json'
|
69
|
+
File.join(Pacto.configuration.contracts_path, uri.host, File.dirname(path), basename)
|
70
|
+
else
|
71
|
+
File.expand_path(hint.target_file, Pacto.configuration.contracts_path)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|