forked from pact-foundation/pact_broker
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: copy pact/doc code into pact_broker repo to assist in break…
…ing the depdendency on webrick
- Loading branch information
Showing
23 changed files
with
1,049 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# Pact::Doc | ||
|
||
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. | ||
|
||
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
module Pact | ||
module Doc | ||
class DocFile | ||
|
||
def initialize consumer_contract, dir, consumer_contract_renderer, file_extension | ||
@dir = dir | ||
@consumer_contract = consumer_contract | ||
@consumer_contract_renderer = consumer_contract_renderer | ||
@file_extension = file_extension | ||
end | ||
|
||
def write | ||
File.open(path, "w") { |io| io << doc_file_contents } | ||
end | ||
|
||
def title | ||
consumer_contract.provider.name | ||
end | ||
|
||
def name | ||
"#{consumer_contract.consumer.name} - #{consumer_contract.provider.name}#{file_extension}" | ||
end | ||
|
||
private | ||
|
||
attr_reader :dir, :consumer_contract, :consumer_contract_renderer, :file_extension | ||
|
||
|
||
def path | ||
File.join(dir, name) | ||
end | ||
|
||
def doc_file_contents | ||
consumer_contract_renderer.call(consumer_contract) | ||
end | ||
|
||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
module Pact | ||
module Doc | ||
class Generate | ||
|
||
def self.call pact_dir = Pact.configuration.pact_dir, doc_dir = Pact.configuration.doc_dir, doc_generators = Pact.configuration.doc_generators | ||
doc_generators.each{| doc_generator| doc_generator.call pact_dir, doc_dir } | ||
end | ||
|
||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
require 'pact/doc/doc_file' | ||
require 'fileutils' | ||
|
||
module Pact | ||
module Doc | ||
|
||
class Generator | ||
|
||
def initialize pact_dir, doc_dir, options | ||
@doc_dir = doc_dir | ||
@pact_dir = pact_dir | ||
@consumer_contract_renderer = options[:consumer_contract_renderer] | ||
@doc_type = options[:doc_type] | ||
@file_extension = options[:file_extension] | ||
@index_renderer = options[:index_renderer] | ||
@index_name = options[:index_name] | ||
@after = options.fetch(:after, lambda{|pact_dir, target_dir, consumer_contracts| }) | ||
end | ||
|
||
def call | ||
ensure_target_dir_exists_and_is_clean | ||
write_index if consumer_contracts.any? | ||
write_doc_files | ||
perform_after_hook | ||
end | ||
|
||
private | ||
|
||
attr_reader :doc_dir, :pact_dir, :consumer_contract_renderer, :doc_type, :file_extension, :index_renderer, :after | ||
|
||
def write_index | ||
File.open(index_file_path, "w") { |io| io << index_file_contents } | ||
end | ||
|
||
def index_file_path | ||
File.join(target_dir, "#{@index_name}#{file_extension}") | ||
end | ||
|
||
def index_file_contents | ||
index_renderer.call(consumer_contracts.first.consumer.name, index_data) | ||
end | ||
|
||
def index_data | ||
doc_files.each_with_object({}) do | doc_file, data | | ||
data[doc_file.title] = doc_file.name | ||
end | ||
end | ||
|
||
def write_doc_files | ||
doc_files.each(&:write) | ||
end | ||
|
||
def doc_files | ||
consumer_contracts.collect do | consumer_contract | | ||
DocFile.new(consumer_contract, target_dir, consumer_contract_renderer, file_extension) | ||
end | ||
end | ||
|
||
def consumer_contracts | ||
@consumer_contracts ||= begin | ||
Dir.glob("#{pact_dir}/**").collect do |file| | ||
Pact::ConsumerContract.from_uri file | ||
end | ||
end | ||
end | ||
|
||
def perform_after_hook | ||
after.call(pact_dir, target_dir, consumer_contracts) | ||
end | ||
|
||
def ensure_target_dir_exists_and_is_clean | ||
FileUtils.rm_rf target_dir | ||
FileUtils.mkdir_p target_dir | ||
end | ||
|
||
def target_dir | ||
File.join(doc_dir, doc_type) | ||
end | ||
|
||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
require 'pact/shared/active_support_support' | ||
require 'pact/reification' | ||
require 'cgi' | ||
|
||
module Pact | ||
module Doc | ||
class InteractionViewModel | ||
|
||
include Pact::ActiveSupportSupport | ||
|
||
def initialize interaction, consumer_contract | ||
@interaction = interaction | ||
@consumer_contract = consumer_contract | ||
end | ||
|
||
def id | ||
@id ||= begin | ||
full_desc = if has_provider_state? | ||
"#{description} given #{interaction.provider_state}" | ||
else | ||
description | ||
end | ||
CGI.escapeHTML(full_desc.gsub(/\s+/,'_')) | ||
end | ||
end | ||
|
||
def request_method | ||
interaction.request.method.upcase | ||
end | ||
|
||
def request_path | ||
interaction.request.path | ||
end | ||
|
||
def response_status | ||
interaction.response.status | ||
end | ||
|
||
def consumer_name | ||
markdown_escape @consumer_contract.consumer.name | ||
end | ||
|
||
def provider_name | ||
markdown_escape @consumer_contract.provider.name | ||
end | ||
|
||
def has_provider_state? | ||
@interaction.provider_state && !@interaction.provider_state.empty? | ||
end | ||
|
||
def provider_state start_of_sentence = false | ||
markdown_escape apply_capitals(@interaction.provider_state.strip, start_of_sentence) | ||
end | ||
|
||
def description start_of_sentence = false | ||
return '' unless @interaction.description | ||
markdown_escape apply_capitals(@interaction.description.strip, start_of_sentence) | ||
end | ||
|
||
def request | ||
fix_json_formatting JSON.pretty_generate(clean_request) | ||
end | ||
|
||
def response | ||
fix_json_formatting JSON.pretty_generate(clean_response) | ||
end | ||
|
||
private | ||
|
||
attr_reader :interaction, :consumer_contract | ||
|
||
def clean_request | ||
reified_request = Reification.from_term(interaction.request) | ||
ordered_clean_hash(reified_request).tap do | hash | | ||
hash[:body] = reified_request[:body] if reified_request[:body] | ||
end | ||
end | ||
|
||
def clean_response | ||
ordered_clean_hash Reification.from_term(interaction.response) | ||
end | ||
|
||
# Remove empty body and headers hashes from response, and empty headers from request, | ||
# as an empty hash means "allow anything" - it's more intuitive and cleaner to just | ||
# remove the empty hashes from display. | ||
def ordered_clean_hash source | ||
ordered_keys.each_with_object({}) do |key, target| | ||
if source.key? key | ||
target[key] = source[key] unless value_is_an_empty_hash(source[key]) | ||
end | ||
end | ||
end | ||
|
||
def value_is_an_empty_hash value | ||
value.is_a?(Hash) && value.empty? | ||
end | ||
|
||
def ordered_keys | ||
[:method, :path, :query, :status, :headers, :body] | ||
end | ||
|
||
def remove_key_if_empty key, hash | ||
hash.delete(key) if hash[key].is_a?(Hash) && hash[key].empty? | ||
end | ||
|
||
def apply_capitals string, start_of_sentence = false | ||
start_of_sentence ? capitalize_first_letter(string) : lowercase_first_letter(string) | ||
end | ||
|
||
def capitalize_first_letter string | ||
string[0].upcase + string[1..-1] | ||
end | ||
|
||
def lowercase_first_letter string | ||
string[0].downcase + string[1..-1] | ||
end | ||
|
||
def markdown_escape string | ||
return nil unless string | ||
string.gsub('*','\*').gsub('_','\_') | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
require 'pact/doc/markdown/interaction_renderer' | ||
require 'pact/doc/sort_interactions' | ||
|
||
module Pact | ||
module Doc | ||
module Markdown | ||
class ConsumerContractRenderer | ||
|
||
def initialize consumer_contract | ||
@consumer_contract = consumer_contract | ||
end | ||
|
||
def self.call consumer_contract | ||
new(consumer_contract).call | ||
end | ||
|
||
def call | ||
title + summaries_title + summaries.join + interactions_title + full_interactions.join | ||
end | ||
|
||
private | ||
|
||
attr_reader :consumer_contract | ||
|
||
def title | ||
"### A pact between #{consumer_name} and #{provider_name}\n\n" | ||
end | ||
|
||
def interaction_renderers | ||
@interaction_renderers ||= sorted_interactions.collect{|interaction| InteractionRenderer.new interaction, @consumer_contract} | ||
end | ||
|
||
def summaries_title | ||
"#### Requests from #{consumer_name} to #{provider_name}\n\n" | ||
end | ||
|
||
def interactions_title | ||
"#### Interactions\n\n" | ||
end | ||
|
||
def summaries | ||
interaction_renderers.collect(&:render_summary) | ||
end | ||
|
||
def full_interactions | ||
interaction_renderers.collect(&:render_full_interaction) | ||
end | ||
|
||
def sorted_interactions | ||
SortInteractions.call(consumer_contract.interactions) | ||
end | ||
|
||
def consumer_name | ||
markdown_escape consumer_contract.consumer.name | ||
end | ||
|
||
def provider_name | ||
markdown_escape consumer_contract.provider.name | ||
end | ||
|
||
def markdown_escape string | ||
string.gsub('*','\*').gsub('_','\_') | ||
end | ||
|
||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
require 'pact/doc/generator' | ||
require 'pact/doc/markdown/consumer_contract_renderer' | ||
require 'pact/doc/markdown/index_renderer' | ||
|
||
module Pact | ||
module Doc | ||
module Markdown | ||
class Generator < Pact::Doc::Generator | ||
def initialize pact_dir, doc_dir | ||
super(pact_dir, doc_dir, | ||
consumer_contract_renderer: ConsumerContractRenderer, | ||
doc_type: 'markdown', | ||
file_extension: '.md', | ||
index_renderer: IndexRenderer, | ||
index_name: 'README') | ||
end | ||
|
||
def self.call pact_dir, doc_dir | ||
new(pact_dir, doc_dir).call | ||
end | ||
end | ||
end | ||
end | ||
end |
Oops, something went wrong.