Skip to content

Commit 6573bd4

Browse files
committedJan 8, 2018
feat(message contracts): read message pact into Ruby object
1 parent 98aca2f commit 6573bd4

File tree

5 files changed

+136
-23
lines changed

5 files changed

+136
-23
lines changed
 

‎lib/pact/consumer_contract/consumer_contract.rb

+12-3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
require 'pact/consumer_contract/service_consumer'
1010
require 'pact/consumer_contract/service_provider'
1111
require 'pact/consumer_contract/interaction'
12+
require 'pact/consumer_contract/message'
1213
require 'pact/consumer_contract/pact_file'
1314

1415
module Pact
@@ -31,10 +32,18 @@ def initialize(attributes = {})
3132

3233
def self.from_hash(hash)
3334
hash = symbolize_keys(hash)
35+
interactions = if hash[:interactions]
36+
hash[:interactions].collect { |hash| Interaction.from_hash(hash)}
37+
elsif hash[:messages]
38+
hash[:messages].collect { |hash| Message.from_hash(hash)}
39+
else
40+
[]
41+
end
42+
3443
new(
3544
:consumer => ServiceConsumer.from_hash(hash[:consumer]),
3645
:provider => ServiceProvider.from_hash(hash[:provider]),
37-
:interactions => hash[:interactions].collect { |hash| Interaction.from_hash(hash)}
46+
:interactions => interactions
3847
)
3948
end
4049

@@ -54,9 +63,9 @@ def self.maintain_backwards_compatiblity_with_producer_keys string
5463
def find_interaction criteria
5564
interactions = find_interactions criteria
5665
if interactions.size == 0
57-
raise "Could not find interaction matching #{criteria} in pact file between #{consumer.name} and #{provider.name}."
66+
raise Pact::Error.new("Could not find interaction matching #{criteria} in pact file between #{consumer.name} and #{provider.name}.")
5867
elsif interactions.size > 1
59-
raise "Found more than 1 interaction matching #{criteria} in pact file between #{consumer.name} and #{provider.name}."
68+
raise Pact::Error.new("Found more than 1 interaction matching #{criteria} in pact file between #{consumer.name} and #{provider.name}.")
6069
end
6170
interactions.first
6271
end

‎lib/pact/consumer_contract/message.rb

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
require 'pact/consumer_contract/message/content'
2+
require 'pact/symbolize_keys'
3+
require 'pact/shared/active_support_support'
4+
require 'pact/matching_rules'
5+
require 'pact/errors'
6+
7+
module Pact
8+
class Message
9+
include ActiveSupportSupport
10+
include SymbolizeKeys
11+
12+
attr_accessor :description, :content, :provider_state
13+
14+
def initialize attributes = {}
15+
@description = attributes[:description]
16+
@request = attributes[:content]
17+
@provider_state = attributes[:provider_state] || attributes[:providerState]
18+
end
19+
20+
def self.from_hash hash
21+
content_hash = Pact::MatchingRules.merge(hash['content'], hash['content']['matchingRules'])
22+
content = Pact::Message::Content.new(content_hash)
23+
new(symbolize_keys(hash).merge(content: content))
24+
end
25+
26+
def to_hash
27+
{
28+
description: description,
29+
provider_state: provider_state,
30+
content: content.to_hash,
31+
}
32+
end
33+
34+
def validate!
35+
raise Pact::InvalidMessageError.new(self) unless description && content
36+
end
37+
38+
def == other
39+
other.is_a?(Message) && to_hash == other.to_hash
40+
end
41+
42+
def matches_criteria? criteria
43+
criteria.each do | key, value |
44+
unless match_criterion self.send(key.to_s), value
45+
return false
46+
end
47+
end
48+
true
49+
end
50+
51+
def match_criterion target, criterion
52+
target == criterion || (criterion.is_a?(Regexp) && criterion.match(target))
53+
end
54+
55+
def eq? other
56+
self == other
57+
end
58+
59+
def description_with_provider_state_quoted
60+
provider_state ? "\"#{description}\" given \"#{provider_state}\"" : "\"#{description}\""
61+
end
62+
63+
def to_s
64+
to_hash.to_s
65+
end
66+
end
67+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module Pact
2+
class Message
3+
class Content < Hash
4+
include ActiveSupportSupport
5+
include SymbolizeKeys
6+
7+
end
8+
end
9+
end

‎lib/pact/errors.rb

+3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ module Pact
22
class Error < ::StandardError
33
end
44

5+
class InvalidMessageError < Error
6+
end
7+
58
# Raised when the interaction is not defined correctly
69
class InvalidInteractionError < Error
710
def initialize(interaction)

‎spec/lib/pact/consumer_contract/consumer_contract_spec.rb

+45-20
Original file line numberDiff line numberDiff line change
@@ -3,37 +3,66 @@
33

44
module Pact
55
describe ConsumerContract do
6-
76
describe ".from_json" do
7+
88
let(:loaded_pact) { ConsumerContract.from_json(string) }
9-
context "when the top level object is a ConsumerContract" do
10-
let(:string) { '{"interactions":[{"request": {"path":"/path", "method" : "get"}, "response": {"status" : 200}}], "consumer": {"name" : "Bob"} , "provider": {"name" : "Mary"} }' }
119

12-
it "should create a Pact" do
13-
expect(loaded_pact).to be_instance_of ConsumerContract
14-
end
10+
context "with an HTTP contract" do
11+
context "when the top level object is a ConsumerContract" do
12+
let(:string) { '{"interactions":[{"request": {"path":"/path", "method" : "get"}, "response": {"status" : 200}}], "consumer": {"name" : "Bob"} , "provider": {"name" : "Mary"} }' }
1513

16-
it "should have interactions" do
17-
expect(loaded_pact.interactions).to be_instance_of Array
18-
end
14+
it "should create a Pact" do
15+
expect(loaded_pact).to be_instance_of ConsumerContract
16+
end
1917

20-
it "should have a consumer" do
21-
expect(loaded_pact.consumer).to be_instance_of Pact::ServiceConsumer
18+
it "should have interactions" do
19+
expect(loaded_pact.interactions).to be_instance_of Array
20+
end
21+
22+
it "should have a consumer" do
23+
expect(loaded_pact.consumer).to be_instance_of Pact::ServiceConsumer
24+
end
25+
26+
it "should have a provider" do
27+
expect(loaded_pact.provider).to be_instance_of Pact::ServiceProvider
28+
end
2229
end
2330

24-
it "should have a provider" do
25-
expect(loaded_pact.provider).to be_instance_of Pact::ServiceProvider
31+
context "with old 'producer' key" do
32+
let(:string) { File.read('./spec/support/a_consumer-a_producer.json')}
33+
it "should create a Pact" do
34+
expect(loaded_pact).to be_instance_of ConsumerContract
35+
end
36+
37+
it "should have interactions" do
38+
expect(loaded_pact.interactions).to be_instance_of Array
39+
end
40+
41+
it "should have a consumer" do
42+
expect(loaded_pact.consumer).to be_instance_of Pact::ServiceConsumer
43+
end
44+
45+
it "should have a provider" do
46+
expect(loaded_pact.provider).to be_instance_of Pact::ServiceProvider
47+
expect(loaded_pact.provider.name).to eq "an old producer"
48+
end
49+
50+
it "should have a provider_state" do
51+
expect(loaded_pact.interactions.first.provider_state).to eq 'state one'
52+
end
2653
end
2754
end
2855

29-
context "with old 'producer' key" do
30-
let(:string) { File.read('./spec/support/a_consumer-a_producer.json')}
56+
context "with a Message contract" do
57+
let(:string) { '{"messages":[{"content": {"foo": "bar"}}], "consumer": {"name" : "Bob"} , "provider": {"name" : "Mary"}}' }
58+
3159
it "should create a Pact" do
3260
expect(loaded_pact).to be_instance_of ConsumerContract
3361
end
3462

35-
it "should have interactions" do
63+
it "should have messages" do
3664
expect(loaded_pact.interactions).to be_instance_of Array
65+
expect(loaded_pact.interactions.first).to be_instance_of Pact::Message
3766
end
3867

3968
it "should have a consumer" do
@@ -42,12 +71,8 @@ module Pact
4271

4372
it "should have a provider" do
4473
expect(loaded_pact.provider).to be_instance_of Pact::ServiceProvider
45-
expect(loaded_pact.provider.name).to eq "an old producer"
4674
end
4775

48-
it "should have a provider_state" do
49-
expect(loaded_pact.interactions.first.provider_state).to eq 'state one'
50-
end
5176
end
5277
end
5378

0 commit comments

Comments
 (0)
Please sign in to comment.