Class: PactBroker::Api::Contracts::PublishContractsSchema

Inherits:
Object
  • Object
show all
Extended by:
DryValidationWorkarounds, Messages
Defined in:
lib/pact_broker/api/contracts/publish_contracts_schema.rb

Constant Summary collapse

SCHEMA =
Dry::Validation.Schema do
  configure do
    predicates(DryValidationPredicates)
    config.messages_file = File.expand_path("../../../locale/en.yml", __FILE__)
  end

  required(:pacticipantName).filled(:str?, :not_blank?)
  required(:pacticipantVersionNumber).filled(:not_blank?, :single_line?)
  optional(:tags).each(:not_blank?, :single_line?)
  optional(:branch).maybe(:not_blank?, :single_line?)
  optional(:buildUrl).maybe(:single_line?)

  required(:contracts).each do
    required(:consumerName).filled(:str?, :not_blank?)
    required(:providerName).filled(:str?, :not_blank?)
    required(:content).filled(:str?)
    required(:contentType).filled(included_in?: ["application/json"])
    required(:specification).filled(included_in?: ["pact"])
    optional(:onConflict).filled(included_in?:["overwrite", "merge"])
  end
end

Class Method Summary collapse

Methods included from DryValidationWorkarounds

flatten_array_of_hashes, flatten_indexed_messages, is_indexed_structure?, select_first_message

Methods included from Messages

message, pluralize, potential_duplicate_pacticipant_message, validation_message

Class Method Details

.add_contract_error(field, message, i, errors) ⇒ Object



95
96
97
98
99
100
101
# File 'lib/pact_broker/api/contracts/publish_contracts_schema.rb', line 95

def self.add_contract_error(field, message, i, errors)
  errors[:contracts] ||= {}
  errors[:contracts][i] ||= {}
  errors[:contracts][i][field] ||= []
  errors[:contracts][i][field] << message
  errors
end

.add_cross_field_validation_errors(params, errors) ⇒ Object



47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/pact_broker/api/contracts/publish_contracts_schema.rb', line 47

def self.add_cross_field_validation_errors(params, errors)
  if params[:contracts].is_a?(Array)
    params[:contracts].each_with_index do | contract, i |
      if contract.is_a?(Hash)
        validate_consumer_name(params, contract, i, errors)
        validate_consumer_name_in_content(params, contract, i, errors)
        validate_provider_name_in_content(contract, i, errors)
        validate_encoding(contract, i, errors)
        validate_content_matches_content_type(contract, i, errors)
      end
    end
  end
  errors
end

.call(params) ⇒ Object



36
37
38
39
40
41
42
43
44
45
# File 'lib/pact_broker/api/contracts/publish_contracts_schema.rb', line 36

def self.call(params)
  dry_results = SCHEMA.call(params&.symbolize_keys).messages(full: true)
  dry_results.then do | results |
    add_cross_field_validation_errors(params&.symbolize_keys, results)
  end.then do | results |
    select_first_message(results)
  end.then do | results |
    flatten_indexed_messages(results)
  end
end

.select_first_message(results) ⇒ Object

Need to fix this whole dry-validation eff up



104
105
106
107
108
109
110
111
# File 'lib/pact_broker/api/contracts/publish_contracts_schema.rb', line 104

def self.select_first_message(results)
  case results
  when Hash then results.each_with_object({}) { |(key, value), new_hash| new_hash[key] = select_first_message(value) }
  when Array then select_first_message_from_array(results)
  else
    results
  end
end

.select_first_message_from_array(results) ⇒ Object



113
114
115
116
117
118
119
# File 'lib/pact_broker/api/contracts/publish_contracts_schema.rb', line 113

def self.select_first_message_from_array(results)
  if results.all?{ |value| value.is_a?(String) }
    results[0...1]
  else
    results.collect { |value| select_first_message(value) }
  end
end

.validate_consumer_name(params, contract, i, errors) ⇒ Object



62
63
64
65
66
# File 'lib/pact_broker/api/contracts/publish_contracts_schema.rb', line 62

def self.validate_consumer_name(params, contract, i, errors)
  if params[:pacticipantName] && contract[:consumerName] && (contract[:consumerName] != params[:pacticipantName])
    add_contract_error(:consumerName, validation_message("consumer_name_in_contract_mismatch_pacticipant_name", { consumer_name_in_contract: contract[:consumerName], pacticipant_name: params[:pacticipantName] } ), i, errors)
  end
end

.validate_consumer_name_in_content(params, contract, i, errors) ⇒ Object



68
69
70
71
72
73
# File 'lib/pact_broker/api/contracts/publish_contracts_schema.rb', line 68

def self.validate_consumer_name_in_content(params, contract, i, errors)
  consumer_name_in_content = contract.dig(:decodedParsedContent, :consumer, :name)
  if consumer_name_in_content && consumer_name_in_content != params[:pacticipantName]
    add_contract_error(:consumerName, validation_message("consumer_name_in_content_mismatch_pacticipant_name", { consumer_name_in_content: consumer_name_in_content, pacticipant_name: params[:pacticipantName] } ), i, errors)
  end
end

.validate_content_matches_content_type(contract, i, errors) ⇒ Object



88
89
90
91
92
# File 'lib/pact_broker/api/contracts/publish_contracts_schema.rb', line 88

def self.validate_content_matches_content_type(contract, i, errors)
  if contract[:decodedParsedContent].nil? && contract[:contentType]
    add_contract_error(:content, validation_message("invalid_content_for_content_type", { content_type: contract[:contentType]}), i, errors)
  end
end

.validate_encoding(contract, i, errors) ⇒ Object



82
83
84
85
86
# File 'lib/pact_broker/api/contracts/publish_contracts_schema.rb', line 82

def self.validate_encoding(contract, i, errors)
  if contract[:decodedContent].nil?
    add_contract_error(:content, message("errors.base64?", scope: nil), i, errors)
  end
end

.validate_provider_name_in_content(contract, i, errors) ⇒ Object



75
76
77
78
79
80
# File 'lib/pact_broker/api/contracts/publish_contracts_schema.rb', line 75

def self.validate_provider_name_in_content(contract, i, errors)
  provider_name_in_content = contract.dig(:decodedParsedContent, :provider, :name)
  if provider_name_in_content && provider_name_in_content != contract[:providerName]
    add_contract_error(:providerName, validation_message("provider_name_in_content_mismatch", { provider_name_in_content: provider_name_in_content, provider_name: contract[:providerName] } ), i, errors)
  end
end