Class: Sbmt::Pact::Consumer::MessageInteractionBuilder

Inherits:
Object
  • Object
show all
Defined in:
lib/sbmt/pact/consumer/message_interaction_builder.rb

Defined Under Namespace

Classes: CreateInteractionError, InteractionBuilderError, InteractionMismatchesError, PluginInitError

Constant Summary collapse

DESCRIPTION_PREFIX =
"async: "
META_CONTENT_TYPE_HEADER =
"contentType"
JSON_CONTENT_TYPE =
"application/json"
PROTO_CONTENT_TYPE =
"application/protobuf"
PROTOBUF_PLUGIN_NAME =
"protobuf"
PROTOBUF_PLUGIN_VERSION =
"0.4.0"
WRITE_PACT_FILE_ERRORS =
{
  1 => {reason: :file_not_accessible, status: 1, description: "The pact file was not able to be written"},
  2 => {reason: :internal_error, status: 2, description: "The message pact for the given handle was not found"}
}.freeze
INIT_PLUGIN_ERRORS =
{
  1 => {reason: :internal_error, status: 1, description: "A general panic was caught"},
  2 => {reason: :plugin_load_failed, status: 2, description: "Failed to load the plugin"},
  3 => {reason: :invalid_handle, status: 3, description: "Pact Handle is not valid"}
}.freeze
CREATE_INTERACTION_ERRORS =
{
  1 => {reason: :internal_error, status: 1, description: "A general panic was caught"},
  2 => {reason: :mock_server_already_running, status: 2, description: "The mock server has already been started"},
  3 => {reason: :invalid_handle, status: 3, description: "The interaction handle is invalid"},
  4 => {reason: :invalid_content_type, status: 4, description: "The content type is not valid"},
  5 => {reason: :invalid_contents, status: 5, description: "The contents JSON is not valid JSON"},
  6 => {reason: :plugin_error, status: 6, description: "The plugin returned an error"}
}.freeze

Instance Method Summary collapse

Constructor Details

#initialize(pact_config, description: nil) ⇒ MessageInteractionBuilder

Returns a new instance of MessageInteractionBuilder.



51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/sbmt/pact/consumer/message_interaction_builder.rb', line 51

def initialize(pact_config, description: nil)
  @pact_config = pact_config
  @description = description

  @json_contents = nil
  @proto_contents = nil
  @proto_path = nil
  @proto_message_class = nil
  @proto_include_dirs = []
  @meta = {}
  @headers = {}
  @provider_state_meta = nil
end

Instance Method Details

#build_interaction_jsonObject



144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/sbmt/pact/consumer/message_interaction_builder.rb', line 144

def build_interaction_json
  return JSON.dump(@json_contents) unless proto_interaction?

  contents = {
    "pact:proto": @proto_path,
    "pact:message-type": @proto_message_class,
    "pact:content-type": PROTO_CONTENT_TYPE
  }.merge(@proto_contents)

  contents["pact:protobuf-config"] = {additionalIncludes: @proto_include_dirs} if @proto_include_dirs.present?

  JSON.dump(contents)
end

#execute(&block) ⇒ Object



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/sbmt/pact/consumer/message_interaction_builder.rb', line 120

def execute(&block)
  raise InteractionBuilderError.new("interaction is designed to be used one-time only") if defined?(@used)

  validate!
  pact_handle = init_pact
  init_plugin!(pact_handle) if proto_interaction?

  message_pact = PactFfi::MessageConsumer.new_message_interaction(pact_handle, description)

  configure_interaction!(message_pact)

  # strip out matchers and get raw payload/metadata
  payload,  = fetch_reified_message(pact_handle)
  configure_provider_state(message_pact, )

  yield(payload, )

  write_pacts!(pact_handle, @pact_config.pact_dir)
ensure
  @used = true
  PactFfi::MessageConsumer.free_handle(message_pact)
  PactFfi.free_pact_handle(pact_handle)
end

#given(provider_state, metadata = {}) ⇒ Object



65
66
67
68
# File 'lib/sbmt/pact/consumer/message_interaction_builder.rb', line 65

def given(provider_state,  = {})
  @provider_state_meta = {provider_state => }
  self
end

#upon_receiving(description) ⇒ Object



70
71
72
73
# File 'lib/sbmt/pact/consumer/message_interaction_builder.rb', line 70

def upon_receiving(description)
  @description = description
  self
end

#validate!Object



110
111
112
113
114
115
116
117
118
# File 'lib/sbmt/pact/consumer/message_interaction_builder.rb', line 110

def validate!
  if proto_interaction?
    raise InteractionBuilderError.new("proto_path / proto_message are not defined, please set ones with #with_proto_message") if @proto_contents.blank? || @proto_message_class.blank?
    raise InteractionBuilderError.new("invalid request format, should be a hash") unless @proto_contents.is_a?(Hash)
  else
    raise InteractionBuilderError.new("invalid request format, should be a hash") unless @json_contents.is_a?(Hash)
  end
  raise InteractionBuilderError.new("description is required for message interactions, please set one with #upon_receiving") if @description.blank?
end

#with_header(key, value) ⇒ Object



105
106
107
108
# File 'lib/sbmt/pact/consumer/message_interaction_builder.rb', line 105

def with_header(key, value)
  @headers[key] = value
  self
end

#with_headers(headers_hash) ⇒ Object



100
101
102
103
# File 'lib/sbmt/pact/consumer/message_interaction_builder.rb', line 100

def with_headers(headers_hash)
  @headers = InteractionContents.basic(headers_hash)
  self
end

#with_json_contents(contents_hash) ⇒ Object



75
76
77
78
# File 'lib/sbmt/pact/consumer/message_interaction_builder.rb', line 75

def with_json_contents(contents_hash)
  @json_contents = InteractionContents.basic(contents_hash)
  self
end

#with_metadata(meta_hash) ⇒ Object



95
96
97
98
# File 'lib/sbmt/pact/consumer/message_interaction_builder.rb', line 95

def (meta_hash)
  @meta = InteractionContents.basic(meta_hash)
  self
end

#with_proto_class(proto_path, message_class_name, include_dirs = []) ⇒ Object



80
81
82
83
84
85
86
87
88
# File 'lib/sbmt/pact/consumer/message_interaction_builder.rb', line 80

def with_proto_class(proto_path, message_class_name, include_dirs = [])
  absolute_path = File.expand_path(proto_path)
  raise InteractionBuilderError.new("proto file #{proto_path} does not exist") unless File.exist?(absolute_path)

  @proto_path = absolute_path
  @proto_message_class = message_class_name
  @proto_include_dirs = include_dirs.map { |dir| File.expand_path(dir) }
  self
end

#with_proto_contents(contents_hash) ⇒ Object



90
91
92
93
# File 'lib/sbmt/pact/consumer/message_interaction_builder.rb', line 90

def with_proto_contents(contents_hash)
  @proto_contents = InteractionContents.plugin(contents_hash)
  self
end