pact_broker 2.13.0 → 2.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/lib/pact/doc/README.md +5 -0
- data/lib/pact/doc/doc_file.rb +39 -0
- data/lib/pact/doc/generate.rb +11 -0
- data/lib/pact/doc/generator.rb +82 -0
- data/lib/pact/doc/interaction_view_model.rb +124 -0
- data/lib/pact/doc/markdown/consumer_contract_renderer.rb +68 -0
- data/lib/pact/doc/markdown/generator.rb +24 -0
- data/lib/pact/doc/markdown/index_renderer.rb +40 -0
- data/lib/pact/doc/markdown/interaction.erb +14 -0
- data/lib/pact/doc/markdown/interaction_renderer.rb +42 -0
- data/lib/pact/doc/sort_interactions.rb +15 -0
- data/lib/pact_broker/version.rb +1 -1
- data/pact_broker.gemspec +2 -2
- data/spec/lib/pact/doc/generator_spec.rb +80 -0
- data/spec/lib/pact/doc/interaction_view_model_spec.rb +186 -0
- data/spec/lib/pact/doc/markdown/consumer_contract_renderer_spec.rb +47 -0
- data/spec/lib/pact/doc/markdown/index_renderer_spec.rb +29 -0
- data/spec/support/generated_index.md +4 -0
- data/spec/support/generated_markdown.md +55 -0
- data/spec/support/interaction_view_model.json +63 -0
- data/spec/support/interaction_view_model_with_terms.json +50 -0
- data/spec/support/markdown_pact.json +48 -0
- data/spec/support/markdown_pact_with_markdown_chars_in_names.json +11 -0
- data/spec/support/warning_silencer.rb +10 -0
- data/tasks/database/table_dependency_calculator.rb +3 -2
- metadata +43 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6493a06ed84ec11bd1c966faddbe3ddb2b948dc1
|
4
|
+
data.tar.gz: f2edee66e10d7ab2fbc8183ff3a685eca1fb20b6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0ddb05561ad94aeb5a3faef53dd0a96b7ca5550f312810f47e1640303298d3f6ef065e29b30d1b41a5928e46d6cba568bacf7c311c745d4f3af0d66d19cb3342
|
7
|
+
data.tar.gz: 905912e0bb8021d08d1d6f8f9ca9cc6d45cc3eafa0fd51dbbfb33ab8297627d3ad437472b5b3b2cf5de6ef5fdce736a14066591f8221a239c2ac56ad8e41483a
|
data/CHANGELOG.md
CHANGED
@@ -0,0 +1,5 @@
|
|
1
|
+
# Pact::Doc
|
2
|
+
|
3
|
+
The code in pact/doc has been copied from the pact gem to break the runtime dependency between the pact_broker and the pact gem, which requires the pact_mock-service, which requires webrick.
|
4
|
+
|
5
|
+
This was required as there is a vulnerability in webrick <= 1.3.1 that we don't want to include in the pact_broker gem, but webrick > 1.3.1 requires ruby 2.3.0, but we need ruby 2.2 for Travelling Ruby, which we use to package the Ruby codebase so it can be shared with implementations in other langauges.
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Pact
|
2
|
+
module Doc
|
3
|
+
class DocFile
|
4
|
+
|
5
|
+
def initialize consumer_contract, dir, consumer_contract_renderer, file_extension
|
6
|
+
@dir = dir
|
7
|
+
@consumer_contract = consumer_contract
|
8
|
+
@consumer_contract_renderer = consumer_contract_renderer
|
9
|
+
@file_extension = file_extension
|
10
|
+
end
|
11
|
+
|
12
|
+
def write
|
13
|
+
File.open(path, "w") { |io| io << doc_file_contents }
|
14
|
+
end
|
15
|
+
|
16
|
+
def title
|
17
|
+
consumer_contract.provider.name
|
18
|
+
end
|
19
|
+
|
20
|
+
def name
|
21
|
+
"#{consumer_contract.consumer.name} - #{consumer_contract.provider.name}#{file_extension}"
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
attr_reader :dir, :consumer_contract, :consumer_contract_renderer, :file_extension
|
27
|
+
|
28
|
+
|
29
|
+
def path
|
30
|
+
File.join(dir, name)
|
31
|
+
end
|
32
|
+
|
33
|
+
def doc_file_contents
|
34
|
+
consumer_contract_renderer.call(consumer_contract)
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Pact
|
2
|
+
module Doc
|
3
|
+
class Generate
|
4
|
+
|
5
|
+
def self.call pact_dir = Pact.configuration.pact_dir, doc_dir = Pact.configuration.doc_dir, doc_generators = Pact.configuration.doc_generators
|
6
|
+
doc_generators.each{| doc_generator| doc_generator.call pact_dir, doc_dir }
|
7
|
+
end
|
8
|
+
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'pact/doc/doc_file'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module Pact
|
5
|
+
module Doc
|
6
|
+
|
7
|
+
class Generator
|
8
|
+
|
9
|
+
def initialize pact_dir, doc_dir, options
|
10
|
+
@doc_dir = doc_dir
|
11
|
+
@pact_dir = pact_dir
|
12
|
+
@consumer_contract_renderer = options[:consumer_contract_renderer]
|
13
|
+
@doc_type = options[:doc_type]
|
14
|
+
@file_extension = options[:file_extension]
|
15
|
+
@index_renderer = options[:index_renderer]
|
16
|
+
@index_name = options[:index_name]
|
17
|
+
@after = options.fetch(:after, lambda{|pact_dir, target_dir, consumer_contracts| })
|
18
|
+
end
|
19
|
+
|
20
|
+
def call
|
21
|
+
ensure_target_dir_exists_and_is_clean
|
22
|
+
write_index if consumer_contracts.any?
|
23
|
+
write_doc_files
|
24
|
+
perform_after_hook
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
attr_reader :doc_dir, :pact_dir, :consumer_contract_renderer, :doc_type, :file_extension, :index_renderer, :after
|
30
|
+
|
31
|
+
def write_index
|
32
|
+
File.open(index_file_path, "w") { |io| io << index_file_contents }
|
33
|
+
end
|
34
|
+
|
35
|
+
def index_file_path
|
36
|
+
File.join(target_dir, "#{@index_name}#{file_extension}")
|
37
|
+
end
|
38
|
+
|
39
|
+
def index_file_contents
|
40
|
+
index_renderer.call(consumer_contracts.first.consumer.name, index_data)
|
41
|
+
end
|
42
|
+
|
43
|
+
def index_data
|
44
|
+
doc_files.each_with_object({}) do | doc_file, data |
|
45
|
+
data[doc_file.title] = doc_file.name
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def write_doc_files
|
50
|
+
doc_files.each(&:write)
|
51
|
+
end
|
52
|
+
|
53
|
+
def doc_files
|
54
|
+
consumer_contracts.collect do | consumer_contract |
|
55
|
+
DocFile.new(consumer_contract, target_dir, consumer_contract_renderer, file_extension)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def consumer_contracts
|
60
|
+
@consumer_contracts ||= begin
|
61
|
+
Dir.glob("#{pact_dir}/**").collect do |file|
|
62
|
+
Pact::ConsumerContract.from_uri file
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def perform_after_hook
|
68
|
+
after.call(pact_dir, target_dir, consumer_contracts)
|
69
|
+
end
|
70
|
+
|
71
|
+
def ensure_target_dir_exists_and_is_clean
|
72
|
+
FileUtils.rm_rf target_dir
|
73
|
+
FileUtils.mkdir_p target_dir
|
74
|
+
end
|
75
|
+
|
76
|
+
def target_dir
|
77
|
+
File.join(doc_dir, doc_type)
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
require 'pact/shared/active_support_support'
|
2
|
+
require 'pact/reification'
|
3
|
+
require 'cgi'
|
4
|
+
|
5
|
+
module Pact
|
6
|
+
module Doc
|
7
|
+
class InteractionViewModel
|
8
|
+
|
9
|
+
include Pact::ActiveSupportSupport
|
10
|
+
|
11
|
+
def initialize interaction, consumer_contract
|
12
|
+
@interaction = interaction
|
13
|
+
@consumer_contract = consumer_contract
|
14
|
+
end
|
15
|
+
|
16
|
+
def id
|
17
|
+
@id ||= begin
|
18
|
+
full_desc = if has_provider_state?
|
19
|
+
"#{description} given #{interaction.provider_state}"
|
20
|
+
else
|
21
|
+
description
|
22
|
+
end
|
23
|
+
CGI.escapeHTML(full_desc.gsub(/\s+/,'_'))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def request_method
|
28
|
+
interaction.request.method.upcase
|
29
|
+
end
|
30
|
+
|
31
|
+
def request_path
|
32
|
+
interaction.request.path
|
33
|
+
end
|
34
|
+
|
35
|
+
def response_status
|
36
|
+
interaction.response.status
|
37
|
+
end
|
38
|
+
|
39
|
+
def consumer_name
|
40
|
+
markdown_escape @consumer_contract.consumer.name
|
41
|
+
end
|
42
|
+
|
43
|
+
def provider_name
|
44
|
+
markdown_escape @consumer_contract.provider.name
|
45
|
+
end
|
46
|
+
|
47
|
+
def has_provider_state?
|
48
|
+
@interaction.provider_state && !@interaction.provider_state.empty?
|
49
|
+
end
|
50
|
+
|
51
|
+
def provider_state start_of_sentence = false
|
52
|
+
markdown_escape apply_capitals(@interaction.provider_state.strip, start_of_sentence)
|
53
|
+
end
|
54
|
+
|
55
|
+
def description start_of_sentence = false
|
56
|
+
return '' unless @interaction.description
|
57
|
+
markdown_escape apply_capitals(@interaction.description.strip, start_of_sentence)
|
58
|
+
end
|
59
|
+
|
60
|
+
def request
|
61
|
+
fix_json_formatting JSON.pretty_generate(clean_request)
|
62
|
+
end
|
63
|
+
|
64
|
+
def response
|
65
|
+
fix_json_formatting JSON.pretty_generate(clean_response)
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
attr_reader :interaction, :consumer_contract
|
71
|
+
|
72
|
+
def clean_request
|
73
|
+
reified_request = Reification.from_term(interaction.request)
|
74
|
+
ordered_clean_hash(reified_request).tap do | hash |
|
75
|
+
hash[:body] = reified_request[:body] if reified_request[:body]
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def clean_response
|
80
|
+
ordered_clean_hash Reification.from_term(interaction.response)
|
81
|
+
end
|
82
|
+
|
83
|
+
# Remove empty body and headers hashes from response, and empty headers from request,
|
84
|
+
# as an empty hash means "allow anything" - it's more intuitive and cleaner to just
|
85
|
+
# remove the empty hashes from display.
|
86
|
+
def ordered_clean_hash source
|
87
|
+
ordered_keys.each_with_object({}) do |key, target|
|
88
|
+
if source.key? key
|
89
|
+
target[key] = source[key] unless value_is_an_empty_hash(source[key])
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def value_is_an_empty_hash value
|
95
|
+
value.is_a?(Hash) && value.empty?
|
96
|
+
end
|
97
|
+
|
98
|
+
def ordered_keys
|
99
|
+
[:method, :path, :query, :status, :headers, :body]
|
100
|
+
end
|
101
|
+
|
102
|
+
def remove_key_if_empty key, hash
|
103
|
+
hash.delete(key) if hash[key].is_a?(Hash) && hash[key].empty?
|
104
|
+
end
|
105
|
+
|
106
|
+
def apply_capitals string, start_of_sentence = false
|
107
|
+
start_of_sentence ? capitalize_first_letter(string) : lowercase_first_letter(string)
|
108
|
+
end
|
109
|
+
|
110
|
+
def capitalize_first_letter string
|
111
|
+
string[0].upcase + string[1..-1]
|
112
|
+
end
|
113
|
+
|
114
|
+
def lowercase_first_letter string
|
115
|
+
string[0].downcase + string[1..-1]
|
116
|
+
end
|
117
|
+
|
118
|
+
def markdown_escape string
|
119
|
+
return nil unless string
|
120
|
+
string.gsub('*','\*').gsub('_','\_')
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'pact/doc/markdown/interaction_renderer'
|
2
|
+
require 'pact/doc/sort_interactions'
|
3
|
+
|
4
|
+
module Pact
|
5
|
+
module Doc
|
6
|
+
module Markdown
|
7
|
+
class ConsumerContractRenderer
|
8
|
+
|
9
|
+
def initialize consumer_contract
|
10
|
+
@consumer_contract = consumer_contract
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.call consumer_contract
|
14
|
+
new(consumer_contract).call
|
15
|
+
end
|
16
|
+
|
17
|
+
def call
|
18
|
+
title + summaries_title + summaries.join + interactions_title + full_interactions.join
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
attr_reader :consumer_contract
|
24
|
+
|
25
|
+
def title
|
26
|
+
"### A pact between #{consumer_name} and #{provider_name}\n\n"
|
27
|
+
end
|
28
|
+
|
29
|
+
def interaction_renderers
|
30
|
+
@interaction_renderers ||= sorted_interactions.collect{|interaction| InteractionRenderer.new interaction, @consumer_contract}
|
31
|
+
end
|
32
|
+
|
33
|
+
def summaries_title
|
34
|
+
"#### Requests from #{consumer_name} to #{provider_name}\n\n"
|
35
|
+
end
|
36
|
+
|
37
|
+
def interactions_title
|
38
|
+
"#### Interactions\n\n"
|
39
|
+
end
|
40
|
+
|
41
|
+
def summaries
|
42
|
+
interaction_renderers.collect(&:render_summary)
|
43
|
+
end
|
44
|
+
|
45
|
+
def full_interactions
|
46
|
+
interaction_renderers.collect(&:render_full_interaction)
|
47
|
+
end
|
48
|
+
|
49
|
+
def sorted_interactions
|
50
|
+
SortInteractions.call(consumer_contract.interactions)
|
51
|
+
end
|
52
|
+
|
53
|
+
def consumer_name
|
54
|
+
markdown_escape consumer_contract.consumer.name
|
55
|
+
end
|
56
|
+
|
57
|
+
def provider_name
|
58
|
+
markdown_escape consumer_contract.provider.name
|
59
|
+
end
|
60
|
+
|
61
|
+
def markdown_escape string
|
62
|
+
string.gsub('*','\*').gsub('_','\_')
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'pact/doc/generator'
|
2
|
+
require 'pact/doc/markdown/consumer_contract_renderer'
|
3
|
+
require 'pact/doc/markdown/index_renderer'
|
4
|
+
|
5
|
+
module Pact
|
6
|
+
module Doc
|
7
|
+
module Markdown
|
8
|
+
class Generator < Pact::Doc::Generator
|
9
|
+
def initialize pact_dir, doc_dir
|
10
|
+
super(pact_dir, doc_dir,
|
11
|
+
consumer_contract_renderer: ConsumerContractRenderer,
|
12
|
+
doc_type: 'markdown',
|
13
|
+
file_extension: '.md',
|
14
|
+
index_renderer: IndexRenderer,
|
15
|
+
index_name: 'README')
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.call pact_dir, doc_dir
|
19
|
+
new(pact_dir, doc_dir).call
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Pact
|
2
|
+
module Doc
|
3
|
+
module Markdown
|
4
|
+
class IndexRenderer
|
5
|
+
attr_reader :consumer_name
|
6
|
+
attr_reader :docs # Hash of pact title => file_name
|
7
|
+
|
8
|
+
def initialize consumer_name, docs
|
9
|
+
@consumer_name = consumer_name
|
10
|
+
@docs = docs
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.call consumer_name, docs
|
14
|
+
new(consumer_name, docs).call
|
15
|
+
end
|
16
|
+
|
17
|
+
def call
|
18
|
+
title + "\n\n" + table_of_contents + "\n"
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def table_of_contents
|
24
|
+
docs.collect do | title, file_name |
|
25
|
+
item title, file_name
|
26
|
+
end.join("\n")
|
27
|
+
end
|
28
|
+
|
29
|
+
def title
|
30
|
+
"### Pacts for #{consumer_name}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def item title, file_name
|
34
|
+
"* [#{title}](#{file_name})"
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<a name="<%= interaction.id %>"></a>
|
2
|
+
<%= if interaction.has_provider_state?
|
3
|
+
"Given **#{interaction.provider_state}**, upon receiving"
|
4
|
+
else
|
5
|
+
"Upon receiving"
|
6
|
+
end
|
7
|
+
%> **<%= interaction.description %>** from <%= interaction.consumer_name %>, with
|
8
|
+
```json
|
9
|
+
<%= interaction.request %>
|
10
|
+
```
|
11
|
+
<%= interaction.provider_name %> will respond with:
|
12
|
+
```json
|
13
|
+
<%= interaction.response %>
|
14
|
+
```
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'pact/doc/interaction_view_model'
|
3
|
+
|
4
|
+
module Pact
|
5
|
+
module Doc
|
6
|
+
module Markdown
|
7
|
+
class InteractionRenderer
|
8
|
+
attr_reader :interaction
|
9
|
+
|
10
|
+
def initialize interaction, pact
|
11
|
+
@interaction = InteractionViewModel.new(interaction, pact)
|
12
|
+
end
|
13
|
+
|
14
|
+
def render_summary
|
15
|
+
suffix = interaction.has_provider_state? ? " given #{interaction.provider_state}" : ""
|
16
|
+
"* [#{interaction.description(true)}](##{interaction.id})#{suffix}\n\n"
|
17
|
+
end
|
18
|
+
|
19
|
+
def render_full_interaction
|
20
|
+
render('/interaction.erb')
|
21
|
+
end
|
22
|
+
|
23
|
+
def render template_file
|
24
|
+
ERB.new(template_string(template_file)).result(binding)
|
25
|
+
end
|
26
|
+
|
27
|
+
# The template file is written with only ASCII range characters, so we
|
28
|
+
# can read as UTF-8. But rendered strings must have same encoding as
|
29
|
+
# script encoding because it will joined to strings which are produced by
|
30
|
+
# string literal.
|
31
|
+
def template_string(template_file)
|
32
|
+
File.read(template_contents(template_file), external_encoding: Encoding::UTF_8).force_encoding(__ENCODING__)
|
33
|
+
end
|
34
|
+
|
35
|
+
def template_contents(template_file)
|
36
|
+
File.dirname(__FILE__) + template_file
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Pact
|
2
|
+
module Doc
|
3
|
+
class SortInteractions
|
4
|
+
def self.call interactions
|
5
|
+
interactions.sort{|a, b| sortable_id(a) <=> sortable_id(b)}
|
6
|
+
end
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def self.sortable_id interaction
|
11
|
+
"#{interaction.description.downcase} #{interaction.response.status} #{(interaction.provider_state || '').downcase}"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/pact_broker/version.rb
CHANGED
data/pact_broker.gemspec
CHANGED
@@ -31,15 +31,15 @@ Gem::Specification.new do |gem|
|
|
31
31
|
gem.add_runtime_dependency 'semver2', '~> 3.4.2'
|
32
32
|
gem.add_runtime_dependency 'rack', '~>2.0'
|
33
33
|
gem.add_runtime_dependency 'redcarpet', '>=3.3.2', '~>3.3'
|
34
|
-
gem.add_runtime_dependency 'pact'
|
34
|
+
gem.add_runtime_dependency 'pact-support'
|
35
35
|
gem.add_runtime_dependency 'padrino-core', '~>0.14.1'
|
36
36
|
gem.add_runtime_dependency 'haml', '~>4.0'
|
37
37
|
gem.add_runtime_dependency 'sucker_punch', '~>2.0'
|
38
38
|
gem.add_runtime_dependency 'rack-protection', '~>2.0'
|
39
39
|
gem.add_runtime_dependency 'dry-types', '~> 0.10.3' # https://travis-ci.org/pact-foundation/pact_broker/jobs/249448621
|
40
40
|
gem.add_runtime_dependency 'table_print', '~> 1.5'
|
41
|
-
gem.add_runtime_dependency 'webrick', '~>1.3.0' # Webrick requires Ruby version >= 2.5.0dev. TODO remove dependency on Pact gem.
|
42
41
|
|
42
|
+
gem.add_development_dependency 'pact', '~>1.14'
|
43
43
|
gem.add_development_dependency 'bundler-audit', '~>0.4'
|
44
44
|
gem.add_development_dependency 'sqlite3', '~>1.3'
|
45
45
|
gem.add_development_dependency 'pry-byebug'
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'pact/doc/generator'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module Pact
|
5
|
+
module Doc
|
6
|
+
describe Generator do
|
7
|
+
|
8
|
+
let(:doc_dir) { './tmp/doc' }
|
9
|
+
let(:pact_dir) { './tmp/pacts' }
|
10
|
+
let(:file_name) { "Some Consumer - Some Provider#{file_extension}" }
|
11
|
+
let(:consumer_contract_renderer) { double("ConsumerContractRenderer", :call => doc_content) }
|
12
|
+
let(:doc_content) { "doc_content" }
|
13
|
+
let(:index_content) { "index_content" }
|
14
|
+
let(:expected_doc_path) { "#{doc_dir}/#{doc_type}/#{file_name}" }
|
15
|
+
let(:expected_index_path) { "#{doc_dir}/#{doc_type}/#{index_name}#{file_extension}" }
|
16
|
+
let(:doc_type) { 'markdown' }
|
17
|
+
let(:file_extension) { ".md" }
|
18
|
+
let(:actual_file_contents) { File.read(expected_doc_path) }
|
19
|
+
let(:actual_index_contents) { File.read(expected_index_path)}
|
20
|
+
let(:index_renderer) { double("IndexRenderer", :call => index_content)}
|
21
|
+
let(:index_name) { 'README' }
|
22
|
+
let(:after_hook) { double("hook", :call => nil)}
|
23
|
+
|
24
|
+
before do
|
25
|
+
FileUtils.rm_rf doc_dir
|
26
|
+
FileUtils.rm_rf pact_dir
|
27
|
+
FileUtils.mkdir_p doc_dir
|
28
|
+
FileUtils.mkdir_p pact_dir
|
29
|
+
FileUtils.cp './spec/support/markdown_pact.json', pact_dir
|
30
|
+
end
|
31
|
+
|
32
|
+
let(:options) { { consumer_contract_renderer: consumer_contract_renderer, doc_type: doc_type, file_extension: file_extension, index_renderer: index_renderer, index_name: index_name } }
|
33
|
+
|
34
|
+
subject { Generator.new(pact_dir, doc_dir, options) }
|
35
|
+
|
36
|
+
context "when there are existing files" do
|
37
|
+
let(:existing_doc_file_path) { File.join(doc_dir, doc_type, "leftover") }
|
38
|
+
|
39
|
+
before do
|
40
|
+
FileUtils.mkdir_p File.dirname(existing_doc_file_path)
|
41
|
+
FileUtils.touch existing_doc_file_path
|
42
|
+
end
|
43
|
+
|
44
|
+
it "clears the existing files" do
|
45
|
+
expect(File.exist?(existing_doc_file_path)).to be true
|
46
|
+
subject.call
|
47
|
+
expect(File.exist?(existing_doc_file_path)).to be false
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
it "creates an index" do
|
52
|
+
expect(index_renderer).to receive(:call).with("Some Consumer", {"Some Provider"=>"Some Consumer - Some Provider.md"})
|
53
|
+
subject.call
|
54
|
+
expect(actual_index_contents).to eq(index_content)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "creates documentation" do
|
58
|
+
subject.call
|
59
|
+
expect(actual_file_contents).to eq(doc_content)
|
60
|
+
end
|
61
|
+
|
62
|
+
context "with an after hook specified" do
|
63
|
+
|
64
|
+
subject { Generator.new(pact_dir, doc_dir, options.merge(:after => after_hook)) }
|
65
|
+
|
66
|
+
it "executes the hook" do
|
67
|
+
expect(after_hook).to receive(:call).with(pact_dir, "#{doc_dir}/#{doc_type}", instance_of(Array))
|
68
|
+
subject.call
|
69
|
+
end
|
70
|
+
|
71
|
+
it "passes in the consumer_contracts" do
|
72
|
+
expect(after_hook).to receive(:call) do | _, _, consumer_contracts |
|
73
|
+
expect(consumer_contracts.first).to be_instance_of(Pact::ConsumerContract)
|
74
|
+
end
|
75
|
+
subject.call
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,186 @@
|
|
1
|
+
require 'pact/doc/interaction_view_model'
|
2
|
+
|
3
|
+
module Pact
|
4
|
+
module Doc
|
5
|
+
describe InteractionViewModel do
|
6
|
+
let(:consumer_contract) { Pact::ConsumerContract.from_uri './spec/support/interaction_view_model.json' }
|
7
|
+
let(:interaction_with_request_with_body_and_headers) { consumer_contract.find_interaction description: "a request with a body and headers" }
|
8
|
+
let(:interaction_with_request_without_body_and_headers) { consumer_contract.find_interaction description: "a request with an empty body and empty headers" }
|
9
|
+
let(:interaction_with_response_with_body_and_headers) { consumer_contract.find_interaction description: "a response with a body and headers" }
|
10
|
+
let(:interaction_with_response_without_body_and_headers) { consumer_contract.find_interaction description: "a response with an empty body and empty headers" }
|
11
|
+
let(:interaction) { consumer_contract.interactions.first }
|
12
|
+
|
13
|
+
subject { InteractionViewModel.new interaction, consumer_contract}
|
14
|
+
|
15
|
+
describe "id" do
|
16
|
+
context "with HTML characters in the description" do
|
17
|
+
before do
|
18
|
+
interaction.description = "an alligator with > 100 legs exists"
|
19
|
+
interaction.provider_state = "a thing exists"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "escapes the HTML characters" do
|
23
|
+
expect(subject.id).to eq "an_alligator_with_>_100_legs_exists_given_a_thing_exists"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "consumer_name" do
|
29
|
+
context "with markdown characters in the name" do
|
30
|
+
it "escapes the markdown characters" do
|
31
|
+
expect(subject.consumer_name).to eq "a\\*consumer"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "provider_name" do
|
37
|
+
context "with markdown characters in the name" do
|
38
|
+
it "escapes the markdown characters" do
|
39
|
+
expect(subject.provider_name).to eq "a\\_provider"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "request" do
|
45
|
+
let(:interaction) { interaction_with_request_with_body_and_headers }
|
46
|
+
|
47
|
+
it "includes the method" do
|
48
|
+
expect(subject.request).to include('"method"')
|
49
|
+
expect(subject.request).to include('"get"')
|
50
|
+
end
|
51
|
+
|
52
|
+
it "includes the body" do
|
53
|
+
expect(subject.request).to include('"body"')
|
54
|
+
expect(subject.request).to include('"a body"')
|
55
|
+
end
|
56
|
+
|
57
|
+
it "includes the headers" do
|
58
|
+
expect(subject.request).to include('"headers"')
|
59
|
+
expect(subject.request).to include('"a header"')
|
60
|
+
end
|
61
|
+
|
62
|
+
it "includes the query" do
|
63
|
+
expect(subject.request).to include('"query"')
|
64
|
+
expect(subject.request).to include('"some=thing"')
|
65
|
+
end
|
66
|
+
|
67
|
+
it "includes the path" do
|
68
|
+
expect(subject.request).to include('"path"')
|
69
|
+
expect(subject.request).to include('"/path"')
|
70
|
+
end
|
71
|
+
|
72
|
+
it "renders the keys in a meaningful order" do
|
73
|
+
expect(subject.request).to match /"method".*"path".*"query".*"headers".*"body"/m
|
74
|
+
end
|
75
|
+
|
76
|
+
context "when the body hash is empty" do
|
77
|
+
let(:interaction) { interaction_with_request_without_body_and_headers }
|
78
|
+
|
79
|
+
it "includes the body" do
|
80
|
+
expect(subject.request).to include("body")
|
81
|
+
end
|
82
|
+
end
|
83
|
+
context "when the headers hash is empty" do
|
84
|
+
let(:interaction) { interaction_with_request_without_body_and_headers }
|
85
|
+
|
86
|
+
it "does not include the headers" do
|
87
|
+
expect(subject.request).to_not include("headers")
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context "when a Pact::Term is present" do
|
92
|
+
let(:consumer_contract) { Pact::ConsumerContract.from_uri './spec/support/interaction_view_model_with_terms.json'}
|
93
|
+
let(:interaction) { consumer_contract.interactions.first }
|
94
|
+
|
95
|
+
it "uses the generated value" do
|
96
|
+
expect(subject.request).to_not include("Term")
|
97
|
+
expect(subject.request).to include("sunny")
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe "response" do
|
103
|
+
let(:interaction) { interaction_with_response_with_body_and_headers }
|
104
|
+
|
105
|
+
it "includes the status" do
|
106
|
+
expect(subject.response).to include('"status"')
|
107
|
+
end
|
108
|
+
|
109
|
+
it "includes the body" do
|
110
|
+
expect(subject.response).to include('"body"')
|
111
|
+
expect(subject.response).to include('"a body"')
|
112
|
+
end
|
113
|
+
it "includes the headers" do
|
114
|
+
expect(subject.response).to include('"headers"')
|
115
|
+
expect(subject.response).to include('"a header"')
|
116
|
+
end
|
117
|
+
|
118
|
+
it "renders the keys in a meaningful order" do
|
119
|
+
expect(subject.response).to match /"status".*"headers".*"body"/m
|
120
|
+
end
|
121
|
+
|
122
|
+
context "when the body hash is empty" do
|
123
|
+
let(:interaction) { interaction_with_response_without_body_and_headers }
|
124
|
+
|
125
|
+
it "does not include the body" do
|
126
|
+
expect(subject.response).to_not include("body")
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
context "when the headers hash is empty" do
|
131
|
+
let(:interaction) { interaction_with_response_without_body_and_headers }
|
132
|
+
|
133
|
+
it "does not include the headers" do
|
134
|
+
expect(subject.response).to_not include("headers")
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
context "when a Pact::Term is present" do
|
139
|
+
let(:consumer_contract) { Pact::ConsumerContract.from_uri './spec/support/interaction_view_model_with_terms.json'}
|
140
|
+
let(:interaction) { consumer_contract.interactions.first }
|
141
|
+
|
142
|
+
it "uses the generated value" do
|
143
|
+
expect(subject.response).to_not include("Term")
|
144
|
+
expect(subject.response).to include("rainy")
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
describe "description" do
|
150
|
+
context "with a nil description" do
|
151
|
+
let(:interaction) do
|
152
|
+
interaction_with_request_with_body_and_headers.description = nil
|
153
|
+
interaction_with_request_with_body_and_headers
|
154
|
+
end
|
155
|
+
|
156
|
+
it "does not blow up" do
|
157
|
+
expect(subject.description(true)).to eq ''
|
158
|
+
expect(subject.description(false)).to eq ''
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
context "with markdown characters in the name" do
|
163
|
+
let(:interaction) do
|
164
|
+
interaction_with_request_with_body_and_headers.description = 'a *description'
|
165
|
+
interaction_with_request_with_body_and_headers
|
166
|
+
end
|
167
|
+
it "escapes the markdown characters" do
|
168
|
+
expect(subject.description).to eq "a \\*description"
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
describe "provider_state" do
|
174
|
+
context "with markdown characters in the name" do
|
175
|
+
let(:interaction) do
|
176
|
+
interaction_with_request_with_body_and_headers.provider_state = 'a *provider state'
|
177
|
+
interaction_with_request_with_body_and_headers
|
178
|
+
end
|
179
|
+
it "escapes the markdown characters" do
|
180
|
+
expect(subject.provider_state).to eq "a \\*provider state"
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'pact/doc/markdown/consumer_contract_renderer'
|
3
|
+
require 'pact/support'
|
4
|
+
|
5
|
+
module Pact
|
6
|
+
module Doc
|
7
|
+
module Markdown
|
8
|
+
describe ConsumerContractRenderer do
|
9
|
+
|
10
|
+
subject { ConsumerContractRenderer.new(consumer_contract) }
|
11
|
+
let(:consumer_contract) { Pact::ConsumerContract.from_uri './spec/support/markdown_pact.json' }
|
12
|
+
|
13
|
+
let(:expected_output) { File.read("./spec/support/generated_markdown.md", external_encoding: Encoding::UTF_8) }
|
14
|
+
|
15
|
+
describe "#call" do
|
16
|
+
|
17
|
+
context "with markdown characters in the pacticipant names" do
|
18
|
+
let(:consumer_contract) { Pact::ConsumerContract.from_uri './spec/support/markdown_pact_with_markdown_chars_in_names.json' }
|
19
|
+
|
20
|
+
it "escapes the markdown characters" do
|
21
|
+
expect(subject.call).to include '### A pact between Some\*Consumer\*App and Some\_Provider\_App'
|
22
|
+
expect(subject.call).to include '#### Requests from Some\*Consumer\*App to Some\_Provider\_App'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context "with ruby's default external encoding is not UTF-8" do
|
27
|
+
around do |example|
|
28
|
+
back = nil
|
29
|
+
WarningSilencer.enable { back, Encoding.default_external = Encoding.default_external, Encoding::ASCII_8BIT }
|
30
|
+
example.run
|
31
|
+
WarningSilencer.enable { Encoding.default_external = back }
|
32
|
+
end
|
33
|
+
|
34
|
+
it "renders the interactions" do
|
35
|
+
expect(subject.call).to eq(expected_output)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
it "renders the interactions" do
|
40
|
+
expect(subject.call).to eq(expected_output)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'pact/doc/markdown/index_renderer'
|
3
|
+
|
4
|
+
module Pact
|
5
|
+
module Doc
|
6
|
+
module Markdown
|
7
|
+
describe IndexRenderer do
|
8
|
+
|
9
|
+
let(:consumer_name) { "Some Consumer" }
|
10
|
+
let(:docs) { {"Some Provider" => "Some Provider.md", "Some other provider" => "Some other provider.md"} }
|
11
|
+
let(:subject) { IndexRenderer.new(consumer_name, docs) }
|
12
|
+
let(:expected_content) { File.read('./spec/support/generated_index.md')}
|
13
|
+
|
14
|
+
describe "#call" do
|
15
|
+
it "renders the index" do
|
16
|
+
expect(subject.call).to eq expected_content
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe ".call" do
|
21
|
+
it "renders the index" do
|
22
|
+
expect(IndexRenderer.call(consumer_name, docs) ).to eq expected_content
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
### A pact between Some Consumer and Some Provider
|
2
|
+
|
3
|
+
#### Requests from Some Consumer to Some Provider
|
4
|
+
|
5
|
+
* [A request for alligators in Brüssel](#a_request_for_alligators_in_Brüssel_given_alligators_exist) given alligators exist
|
6
|
+
|
7
|
+
* [A request for polar bears](#a_request_for_polar_bears)
|
8
|
+
|
9
|
+
#### Interactions
|
10
|
+
|
11
|
+
<a name="a_request_for_alligators_in_Brüssel_given_alligators_exist"></a>
|
12
|
+
Given **alligators exist**, upon receiving **a request for alligators in Brüssel** from Some Consumer, with
|
13
|
+
```json
|
14
|
+
{
|
15
|
+
"method": "get",
|
16
|
+
"path": "/alligators"
|
17
|
+
}
|
18
|
+
```
|
19
|
+
Some Provider will respond with:
|
20
|
+
```json
|
21
|
+
{
|
22
|
+
"status": 200,
|
23
|
+
"headers": {
|
24
|
+
"Content-Type": "application/json"
|
25
|
+
},
|
26
|
+
"body": {
|
27
|
+
"alligators": [
|
28
|
+
{
|
29
|
+
"name": "Bob",
|
30
|
+
"phoneNumber": "12345678"
|
31
|
+
}
|
32
|
+
]
|
33
|
+
}
|
34
|
+
}
|
35
|
+
```
|
36
|
+
<a name="a_request_for_polar_bears"></a>
|
37
|
+
Upon receiving **a request for polar bears** from Some Consumer, with
|
38
|
+
```json
|
39
|
+
{
|
40
|
+
"method": "get",
|
41
|
+
"path": "/polar-bears"
|
42
|
+
}
|
43
|
+
```
|
44
|
+
Some Provider will respond with:
|
45
|
+
```json
|
46
|
+
{
|
47
|
+
"status": 404,
|
48
|
+
"headers": {
|
49
|
+
"Content-Type": "application/json"
|
50
|
+
},
|
51
|
+
"body": {
|
52
|
+
"message": "Sorry, due to climate change, the polar bears are currently unavailable."
|
53
|
+
}
|
54
|
+
}
|
55
|
+
```
|
@@ -0,0 +1,63 @@
|
|
1
|
+
{
|
2
|
+
"provider": {
|
3
|
+
"name": "a_provider"
|
4
|
+
},
|
5
|
+
"consumer": {
|
6
|
+
"name": "a*consumer"
|
7
|
+
},
|
8
|
+
"interactions": [
|
9
|
+
{
|
10
|
+
"description": "a request with a body and headers",
|
11
|
+
"request": {
|
12
|
+
"method": "get",
|
13
|
+
"path": "/path",
|
14
|
+
"query": "some=thing",
|
15
|
+
"headers": {
|
16
|
+
"key": "a header"
|
17
|
+
},
|
18
|
+
"body": {
|
19
|
+
"key": "a body"
|
20
|
+
}
|
21
|
+
},
|
22
|
+
"response": {}
|
23
|
+
},
|
24
|
+
{
|
25
|
+
"description": "a request with an empty body and empty headers",
|
26
|
+
"request": {
|
27
|
+
"method": "get",
|
28
|
+
"path": "/",
|
29
|
+
"headers": {},
|
30
|
+
"body": {}
|
31
|
+
},
|
32
|
+
"response": {}
|
33
|
+
},
|
34
|
+
{
|
35
|
+
"description": "a response with a body and headers",
|
36
|
+
"request": {
|
37
|
+
"method": "get",
|
38
|
+
"path": "/"
|
39
|
+
},
|
40
|
+
"response": {
|
41
|
+
"headers": {
|
42
|
+
"key": "a header"
|
43
|
+
},
|
44
|
+
"body": {
|
45
|
+
"key": "a body"
|
46
|
+
},
|
47
|
+
"status": 200
|
48
|
+
}
|
49
|
+
},
|
50
|
+
{
|
51
|
+
"description": "a response with an empty body and empty headers",
|
52
|
+
"request": {
|
53
|
+
"method": "get",
|
54
|
+
"path": "/"
|
55
|
+
},
|
56
|
+
"response": {
|
57
|
+
"status": 200,
|
58
|
+
"headers": {},
|
59
|
+
"body": {}
|
60
|
+
}
|
61
|
+
}
|
62
|
+
]
|
63
|
+
}
|
@@ -0,0 +1,50 @@
|
|
1
|
+
{
|
2
|
+
"provider": {
|
3
|
+
"name": "a provider"
|
4
|
+
},
|
5
|
+
"consumer": {
|
6
|
+
"name": "a consumer"
|
7
|
+
},
|
8
|
+
"interactions": [
|
9
|
+
{
|
10
|
+
"description": "an interaction with terms",
|
11
|
+
"request": {
|
12
|
+
"method": "post",
|
13
|
+
"path": "/path",
|
14
|
+
"query": "some=thing",
|
15
|
+
"headers": {
|
16
|
+
"key": "a header"
|
17
|
+
},
|
18
|
+
"body": {
|
19
|
+
"term": {
|
20
|
+
"json_class": "Pact::Term",
|
21
|
+
"data": {
|
22
|
+
"generate": "sunny",
|
23
|
+
"matcher": {
|
24
|
+
"json_class": "Regexp",
|
25
|
+
"o": 0,
|
26
|
+
"s": "sun"
|
27
|
+
}
|
28
|
+
}
|
29
|
+
}
|
30
|
+
}
|
31
|
+
},
|
32
|
+
"response": {
|
33
|
+
"status": 200,
|
34
|
+
"body": {
|
35
|
+
"term": {
|
36
|
+
"json_class": "Pact::Term",
|
37
|
+
"data": {
|
38
|
+
"generate": "rainy",
|
39
|
+
"matcher": {
|
40
|
+
"json_class": "Regexp",
|
41
|
+
"o": 0,
|
42
|
+
"s": "rain"
|
43
|
+
}
|
44
|
+
}
|
45
|
+
}
|
46
|
+
}
|
47
|
+
}
|
48
|
+
}
|
49
|
+
]
|
50
|
+
}
|
@@ -0,0 +1,48 @@
|
|
1
|
+
{
|
2
|
+
"provider": {
|
3
|
+
"name": "Some Provider"
|
4
|
+
},
|
5
|
+
"consumer": {
|
6
|
+
"name": "Some Consumer"
|
7
|
+
},
|
8
|
+
"interactions": [
|
9
|
+
{
|
10
|
+
"description": "a request for alligators in Brüssel",
|
11
|
+
"provider_state": "alligators exist",
|
12
|
+
"request": {
|
13
|
+
"method": "get",
|
14
|
+
"path": "/alligators"
|
15
|
+
},
|
16
|
+
"response": {
|
17
|
+
"headers" : {"Content-Type": "application/json"},
|
18
|
+
"status" : 200,
|
19
|
+
"body" : {
|
20
|
+
"alligators": [{
|
21
|
+
"name": "Bob",
|
22
|
+
"phoneNumber" : {
|
23
|
+
"json_class": "Pact::Term",
|
24
|
+
"data": {
|
25
|
+
"generate": "12345678",
|
26
|
+
"matcher": {"json_class":"Regexp","o":0,"s":"\\d+"}
|
27
|
+
}
|
28
|
+
}
|
29
|
+
}]
|
30
|
+
}
|
31
|
+
}
|
32
|
+
},{
|
33
|
+
"description": "a request for polar bears",
|
34
|
+
"provider_state": null,
|
35
|
+
"request": {
|
36
|
+
"method": "get",
|
37
|
+
"path": "/polar-bears"
|
38
|
+
},
|
39
|
+
"response": {
|
40
|
+
"headers" : {"Content-Type": "application/json"},
|
41
|
+
"status" : 404,
|
42
|
+
"body" : {
|
43
|
+
"message": "Sorry, due to climate change, the polar bears are currently unavailable."
|
44
|
+
}
|
45
|
+
}
|
46
|
+
}
|
47
|
+
]
|
48
|
+
}
|
@@ -20,8 +20,9 @@ module PactBroker
|
|
20
20
|
.collect{|it| @connection.foreign_key_list(it)
|
21
21
|
.collect{|fk| {from: it, to: fk[:table]} } }
|
22
22
|
.flatten
|
23
|
-
.uniq
|
24
|
-
|
23
|
+
.uniq
|
24
|
+
table_names = @connection.tables - [:schema_migrations, :schema_info]
|
25
|
+
check(table_names, dependencies, ordered_table_names)
|
25
26
|
ordered_table_names
|
26
27
|
end
|
27
28
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pact_broker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.13.
|
4
|
+
version: 2.13.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bethany Skurrie
|
@@ -165,19 +165,19 @@ dependencies:
|
|
165
165
|
- !ruby/object:Gem::Version
|
166
166
|
version: '3.3'
|
167
167
|
- !ruby/object:Gem::Dependency
|
168
|
-
name: pact
|
168
|
+
name: pact-support
|
169
169
|
requirement: !ruby/object:Gem::Requirement
|
170
170
|
requirements:
|
171
|
-
- - "
|
171
|
+
- - ">="
|
172
172
|
- !ruby/object:Gem::Version
|
173
|
-
version: '
|
173
|
+
version: '0'
|
174
174
|
type: :runtime
|
175
175
|
prerelease: false
|
176
176
|
version_requirements: !ruby/object:Gem::Requirement
|
177
177
|
requirements:
|
178
|
-
- - "
|
178
|
+
- - ">="
|
179
179
|
- !ruby/object:Gem::Version
|
180
|
-
version: '
|
180
|
+
version: '0'
|
181
181
|
- !ruby/object:Gem::Dependency
|
182
182
|
name: padrino-core
|
183
183
|
requirement: !ruby/object:Gem::Requirement
|
@@ -263,19 +263,19 @@ dependencies:
|
|
263
263
|
- !ruby/object:Gem::Version
|
264
264
|
version: '1.5'
|
265
265
|
- !ruby/object:Gem::Dependency
|
266
|
-
name:
|
266
|
+
name: pact
|
267
267
|
requirement: !ruby/object:Gem::Requirement
|
268
268
|
requirements:
|
269
269
|
- - "~>"
|
270
270
|
- !ruby/object:Gem::Version
|
271
|
-
version: 1.
|
272
|
-
type: :
|
271
|
+
version: '1.14'
|
272
|
+
type: :development
|
273
273
|
prerelease: false
|
274
274
|
version_requirements: !ruby/object:Gem::Requirement
|
275
275
|
requirements:
|
276
276
|
- - "~>"
|
277
277
|
- !ruby/object:Gem::Version
|
278
|
-
version: 1.
|
278
|
+
version: '1.14'
|
279
279
|
- !ruby/object:Gem::Dependency
|
280
280
|
name: bundler-audit
|
281
281
|
requirement: !ruby/object:Gem::Requirement
|
@@ -602,6 +602,17 @@ files:
|
|
602
602
|
- example/example_data.sql
|
603
603
|
- example/pact_broker_database.sqlite3
|
604
604
|
- lib/db.rb
|
605
|
+
- lib/pact/doc/README.md
|
606
|
+
- lib/pact/doc/doc_file.rb
|
607
|
+
- lib/pact/doc/generate.rb
|
608
|
+
- lib/pact/doc/generator.rb
|
609
|
+
- lib/pact/doc/interaction_view_model.rb
|
610
|
+
- lib/pact/doc/markdown/consumer_contract_renderer.rb
|
611
|
+
- lib/pact/doc/markdown/generator.rb
|
612
|
+
- lib/pact/doc/markdown/index_renderer.rb
|
613
|
+
- lib/pact/doc/markdown/interaction.erb
|
614
|
+
- lib/pact/doc/markdown/interaction_renderer.rb
|
615
|
+
- lib/pact/doc/sort_interactions.rb
|
605
616
|
- lib/pact_broker.rb
|
606
617
|
- lib/pact_broker/api.rb
|
607
618
|
- lib/pact_broker/api/contracts/pacticipant_name_contract.rb
|
@@ -919,6 +930,10 @@ files:
|
|
919
930
|
- spec/integration/endpoints/group_spec.rb
|
920
931
|
- spec/integration/ui/index_spec.rb
|
921
932
|
- spec/integration/webhooks/certificate_spec.rb
|
933
|
+
- spec/lib/pact/doc/generator_spec.rb
|
934
|
+
- spec/lib/pact/doc/interaction_view_model_spec.rb
|
935
|
+
- spec/lib/pact/doc/markdown/consumer_contract_renderer_spec.rb
|
936
|
+
- spec/lib/pact/doc/markdown/index_renderer_spec.rb
|
922
937
|
- spec/lib/pact_broker/api/contracts/put_pact_params_contract_spec.rb
|
923
938
|
- spec/lib/pact_broker/api/contracts/verification_contract_spec.rb
|
924
939
|
- spec/lib/pact_broker/api/contracts/webhook_contract_spec.rb
|
@@ -1040,12 +1055,19 @@ files:
|
|
1040
1055
|
- spec/spec_helper.rb
|
1041
1056
|
- spec/support/database_cleaner.rb
|
1042
1057
|
- spec/support/fixture_helpers.rb
|
1058
|
+
- spec/support/generated_index.md
|
1059
|
+
- spec/support/generated_markdown.md
|
1060
|
+
- spec/support/interaction_view_model.json
|
1061
|
+
- spec/support/interaction_view_model_with_terms.json
|
1062
|
+
- spec/support/markdown_pact.json
|
1063
|
+
- spec/support/markdown_pact_with_markdown_chars_in_names.json
|
1043
1064
|
- spec/support/migration_helpers.rb
|
1044
1065
|
- spec/support/rspec_match_hash.rb
|
1045
1066
|
- spec/support/rspec_matchers.rb
|
1046
1067
|
- spec/support/shared_examples_for_responses.rb
|
1047
1068
|
- spec/support/ssl_webhook_server.rb
|
1048
1069
|
- spec/support/test_data_builder.rb
|
1070
|
+
- spec/support/warning_silencer.rb
|
1049
1071
|
- tasks/database.rb
|
1050
1072
|
- tasks/database/table_dependency_calculator.rb
|
1051
1073
|
- tasks/db.rake
|
@@ -1170,6 +1192,10 @@ test_files:
|
|
1170
1192
|
- spec/integration/endpoints/group_spec.rb
|
1171
1193
|
- spec/integration/ui/index_spec.rb
|
1172
1194
|
- spec/integration/webhooks/certificate_spec.rb
|
1195
|
+
- spec/lib/pact/doc/generator_spec.rb
|
1196
|
+
- spec/lib/pact/doc/interaction_view_model_spec.rb
|
1197
|
+
- spec/lib/pact/doc/markdown/consumer_contract_renderer_spec.rb
|
1198
|
+
- spec/lib/pact/doc/markdown/index_renderer_spec.rb
|
1173
1199
|
- spec/lib/pact_broker/api/contracts/put_pact_params_contract_spec.rb
|
1174
1200
|
- spec/lib/pact_broker/api/contracts/verification_contract_spec.rb
|
1175
1201
|
- spec/lib/pact_broker/api/contracts/webhook_contract_spec.rb
|
@@ -1291,9 +1317,16 @@ test_files:
|
|
1291
1317
|
- spec/spec_helper.rb
|
1292
1318
|
- spec/support/database_cleaner.rb
|
1293
1319
|
- spec/support/fixture_helpers.rb
|
1320
|
+
- spec/support/generated_index.md
|
1321
|
+
- spec/support/generated_markdown.md
|
1322
|
+
- spec/support/interaction_view_model.json
|
1323
|
+
- spec/support/interaction_view_model_with_terms.json
|
1324
|
+
- spec/support/markdown_pact.json
|
1325
|
+
- spec/support/markdown_pact_with_markdown_chars_in_names.json
|
1294
1326
|
- spec/support/migration_helpers.rb
|
1295
1327
|
- spec/support/rspec_match_hash.rb
|
1296
1328
|
- spec/support/rspec_matchers.rb
|
1297
1329
|
- spec/support/shared_examples_for_responses.rb
|
1298
1330
|
- spec/support/ssl_webhook_server.rb
|
1299
1331
|
- spec/support/test_data_builder.rb
|
1332
|
+
- spec/support/warning_silencer.rb
|