pact_broker 1.10.0 → 1.11.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: df97d13a663699e7a3eb4d7f58cc7abe8a1012d2
4
- data.tar.gz: 319a6de81120c2bc7d627fbc2255caf51da2e742
3
+ metadata.gz: 5f09781dc3499bf4830479db69b58d8d26436bea
4
+ data.tar.gz: 74c433ce40b144bd5e2c1cef5efa4a3d892a94f5
5
5
  SHA512:
6
- metadata.gz: 0130cac31b2abaebf71905c841d136a0e6d7fcf4e00186c3e33afb2fda2a8ce4fddceb5fcfe4cd5de9b0650bf6eb8d5cec1f33c422bf17af36292f01665e253b
7
- data.tar.gz: 3a7f9c3663de5c1b1143608727321f97a40af7737d3868034e9bff1b2cfbb86ec131731667963f173484057bd118c6b84f32ca41fa22101f8f2542aaa34e1e56
6
+ metadata.gz: 85c3c79444957b05bcfd754e5d12b69a2d8196439a45e1f6ce1edaf2d2936e850f9656bbb3396d243434bd80a11a659a257b2614b10385c52e5a07b7b14fcfa1
7
+ data.tar.gz: 78782d8518d1bf357c9d434b5ed40d77d6ab83f6f73745e063f22a2f5c747e61f65201af92851206c4b70cdab532d6d51a5d05a8d72cfbd25dfec0834723d80c
data/CHANGELOG.md CHANGED
@@ -2,6 +2,10 @@ Do this to generate your change history
2
2
 
3
3
  $ git log --pretty=format:' * %h - %s (%an, %ad)' vX.Y.Z..HEAD
4
4
 
5
+
6
+ #### 1.11.0 (2016-08-13)
7
+ * 18ffc4a - Add conflict guards to pact merger (Steve Pletcher, Fri Aug 5 12:31:30 2016 -0400)
8
+
5
9
  #### 1.10.0 (2016-08-01)
6
10
  * efdde13 - Add ability to merge pacts via PATCH requests (Steve Pletcher, Thu Jul 28 16:29:22 2016 -0400)
7
11
 
@@ -40,7 +40,10 @@ module PactBroker
40
40
  end
41
41
 
42
42
  def is_conflict?
43
- potential_duplicate_pacticipants?(pact_params.pacticipant_names)
43
+ merge_conflict = request.patch? && resource_exists? &&
44
+ Pacts::Merger.conflict?(pact.json_content, pact_params.json_content)
45
+
46
+ potential_duplicate_pacticipants?(pact_params.pacticipant_names) || merge_conflict
44
47
  end
45
48
 
46
49
  def malformed_request?
@@ -6,6 +6,17 @@ module PactBroker
6
6
 
7
7
  extend self
8
8
 
9
+ def conflict? original_json, additional_json
10
+ original, additional = [original_json, additional_json].map{|str| JSON.parse(str, PACT_PARSING_OPTIONS) }
11
+
12
+ additional["interactions"].any? do |new_interaction|
13
+ original["interactions"].any? do |original_interaction|
14
+ same_description_and_state?(original_interaction, new_interaction) &&
15
+ !same_request_properties?(original_interaction["request"], new_interaction["request"])
16
+ end
17
+ end
18
+ end
19
+
9
20
  # Accepts two hashes representing pacts, outputs a merged hash
10
21
  # Does not make any guarantees about order of interactions
11
22
  def merge_pacts original_json, additional_json
@@ -16,7 +27,7 @@ module PactBroker
16
27
  additional["interactions"].each do |new_interaction|
17
28
  # check to see if this interaction matches an existing interaction
18
29
  overwrite_index = original["interactions"].find_index do |original_interaction|
19
- matching_request?(original_interaction, new_interaction)
30
+ same_description_and_state?(original_interaction, new_interaction)
20
31
  end
21
32
 
22
33
  # overwrite existing interaction if a match is found, otherwise appends the new interaction
@@ -32,21 +43,15 @@ module PactBroker
32
43
 
33
44
  private
34
45
 
35
- def matching_request? original_interaction, new_interaction
36
- same_description_and_state?(original_interaction, new_interaction) &&
37
- same_request_properties?(original_interaction["request"], new_interaction["request"])
38
- end
39
-
40
46
  def same_description_and_state? original, additional
41
47
  original["description"] == additional["description"] &&
42
48
  original["provider_state"] == additional["provider_state"]
43
49
  end
44
50
 
45
51
  def same_request_properties? original, additional
46
- method_matches = original["method"] == additional["method"]
47
- path_matches = original["path"] == additional["path"]
48
-
49
- method_matches && path_matches && original["headers"] == additional["headers"]
52
+ attributes_match = %w(method path query body headers).all? do |attribute|
53
+ original[attribute] == additional[attribute]
54
+ end
50
55
  end
51
56
  end
52
57
  end
@@ -1,3 +1,3 @@
1
1
  module PactBroker
2
- VERSION = '1.10.0'
2
+ VERSION = '1.11.0'
3
3
  end
@@ -25,7 +25,7 @@ describe "Merging a pact" do
25
25
  end
26
26
 
27
27
  context "when a pact for this consumer version does exist" do
28
- let(:existing_pact_content) { load_fixture('a_consumer-a_provider-2.json') }
28
+ let(:existing_pact_content) { load_fixture('a_consumer-a_provider-3.json') }
29
29
  let(:merged_pact_content) { load_fixture('a_consumer-a_provider-merged.json') }
30
30
 
31
31
  before do
@@ -43,6 +43,14 @@ describe "Merging a pact" do
43
43
  it "returns the merged pact in the response body" do
44
44
  expect(response_body_json).to contain_hash JSON.parse(merged_pact_content)
45
45
  end
46
+
47
+ context "with a conflicting request" do
48
+ let(:existing_pact_content) { load_fixture('a_consumer-a_provider-conflict.json') }
49
+
50
+ it "returns a 409 Conflict" do
51
+ expect(subject.status).to be 409
52
+ end
53
+ end
46
54
  end
47
55
 
48
56
  context "when the pacticipant names in the path do not match those in the pact" do
@@ -0,0 +1,22 @@
1
+ {
2
+ "consumer": {
3
+ "name": "A Consumer"
4
+ },
5
+ "provider": {
6
+ "name": "A Provider"
7
+ },
8
+ "interactions": [
9
+ {
10
+ "description" : "another request for something",
11
+ "provider_state": null,
12
+ "request": {
13
+ "method": "get",
14
+ "path" : "/something_else"
15
+ },
16
+ "response": {
17
+ "status": 200,
18
+ "body" : "something"
19
+ }
20
+ }
21
+ ]
22
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "consumer": {
3
+ "name": "A Consumer"
4
+ },
5
+ "provider": {
6
+ "name": "A Provider"
7
+ },
8
+ "interactions": [
9
+ {
10
+ "description" : "a request for something",
11
+ "provider_state": null,
12
+ "request": {
13
+ "method": "post",
14
+ "path" : "/something"
15
+ },
16
+ "response": {
17
+ "status": 200,
18
+ "body" : "something"
19
+ }
20
+ }
21
+ ]
22
+ }
@@ -10,7 +10,7 @@
10
10
  "description" : "a request for something",
11
11
  "provider_state": null,
12
12
  "request": {
13
- "method": "post",
13
+ "method": "get",
14
14
  "path" : "/something"
15
15
  },
16
16
  "response": {
@@ -19,11 +19,11 @@
19
19
  }
20
20
  },
21
21
  {
22
- "description" : "a request for something",
22
+ "description" : "another request for something",
23
23
  "provider_state": null,
24
24
  "request": {
25
25
  "method": "get",
26
- "path" : "/something"
26
+ "path" : "/something_else"
27
27
  },
28
28
  "response": {
29
29
  "status": 200,
@@ -11,7 +11,10 @@
11
11
  "provider_state": null,
12
12
  "request": {
13
13
  "method": "get",
14
- "path" : "/something"
14
+ "path" : "/something",
15
+ "headers" : {
16
+ "Content-Type" : "application/json"
17
+ }
15
18
  },
16
19
  "response": {
17
20
  "status": 200,
@@ -28,86 +28,115 @@ module PactBroker
28
28
  }
29
29
  end
30
30
 
31
- before :each do
32
- @pact_to_merge = load_json_fixture('consumer-provider.json')
33
- end
34
-
35
- it "merges two pacts" do
36
- @pact_to_merge["interactions"] << example_interaction
37
- result = merge_pacts(example_pact, @pact_to_merge)
38
- expect(result["interactions"]).to match_array(example_pact["interactions"].push(example_interaction))
39
- end
40
-
41
- it "is idempotent" do
42
- @pact_to_merge["interactions"] << example_interaction
43
- first_result = merge_pacts(example_pact, @pact_to_merge)
44
- second_result = merge_pacts(first_result, @pact_to_merge)
45
- expect(first_result).to contain_hash second_result
46
- end
47
-
48
- it "overwrites identical interactions" do
49
- @pact_to_merge["interactions"][0]["response"]["body"] = "changed!"
50
- result = merge_pacts(example_pact, @pact_to_merge)
51
-
52
- expect(result["interactions"].length).to eq example_pact["interactions"].length
53
- expect(result["interactions"].first["response"]["body"]).to eq "changed!"
54
- end
55
-
56
- it "appends interactions with a different provider state" do
57
- @pact_to_merge["interactions"][0]["provider_state"] = "upside down"
31
+ describe "#merge" do
58
32
 
59
- result = merge_pacts(example_pact, @pact_to_merge)
60
- expect(result["interactions"].length).to eq example_pact["interactions"].length + 1
61
- end
33
+ before :each do
34
+ @pact_to_merge = load_json_fixture('consumer-provider.json')
35
+ end
62
36
 
63
- it "appends interactions with a different description" do
64
- @pact_to_merge["interactions"][0]["description"] = "getting $$$"
37
+ it "merges two pacts" do
38
+ @pact_to_merge["interactions"] << example_interaction
39
+ result = merge_pacts(example_pact, @pact_to_merge)
40
+ expect(result["interactions"]).to match_array(example_pact["interactions"].push(example_interaction))
41
+ end
65
42
 
66
- result = merge_pacts(example_pact, @pact_to_merge)
67
- expect(result["interactions"].length).to eq example_pact["interactions"].length + 1
68
- end
43
+ it "is idempotent" do
44
+ @pact_to_merge["interactions"] << example_interaction
45
+ first_result = merge_pacts(example_pact, @pact_to_merge)
46
+ second_result = merge_pacts(first_result, @pact_to_merge)
47
+ expect(first_result).to contain_hash second_result
48
+ end
69
49
 
70
- it "appends interactions with a different request method" do
71
- @pact_to_merge["interactions"][0]["request"]["method"] = "delete"
50
+ it "overwrites identical interactions" do
51
+ @pact_to_merge["interactions"][0]["response"]["body"] = "changed!"
52
+ result = merge_pacts(example_pact, @pact_to_merge)
72
53
 
73
- result = merge_pacts(example_pact, @pact_to_merge)
74
- expect(result["interactions"].length).to eq example_pact["interactions"].length + 1
75
- end
54
+ expect(result["interactions"].length).to eq example_pact["interactions"].length
55
+ expect(result["interactions"].first["response"]["body"]).to eq "changed!"
56
+ end
76
57
 
77
- it "appends interactions with a different request path" do
78
- @pact_to_merge["interactions"][0]["request"]["path"] = "/decrypt_all_passwords"
58
+ it "appends interactions with a different provider state" do
59
+ @pact_to_merge["interactions"][0]["provider_state"] = "upside down"
79
60
 
80
- result = merge_pacts(example_pact, @pact_to_merge)
81
- expect(result["interactions"].length).to eq example_pact["interactions"].length + 1
82
- end
61
+ result = merge_pacts(example_pact, @pact_to_merge)
62
+ expect(result["interactions"].length).to eq example_pact["interactions"].length + 1
63
+ end
83
64
 
84
- it "appends interactions which have additional request headers in the new pact" do
85
- @pact_to_merge["interactions"][0]["request"]["headers"] = { "Accept" => "script/javascript" }
65
+ it "appends interactions with a different description" do
66
+ @pact_to_merge["interactions"][0]["description"] = "getting $$$"
86
67
 
87
- result = merge_pacts(example_pact, @pact_to_merge)
88
- expect(result["interactions"].length).to eq example_pact["interactions"].length + 1
89
- end
68
+ result = merge_pacts(example_pact, @pact_to_merge)
69
+ expect(result["interactions"].length).to eq example_pact["interactions"].length + 1
70
+ end
90
71
 
91
- it "appends interactions with different request headers" do
92
- example_pact["interactions"][0]["request"]["headers"] = { "Content-Type" => "script/javascript" }
93
- @pact_to_merge["interactions"][0]["request"]["headers"] = { "Content-Type" => "ayy/lmao" }
72
+ # helper that lets these specs deal with hashes instead of JSON strings
73
+ def merge_pacts(a, b, return_hash = true)
74
+ result = PactBroker::Pacts::Merger.merge_pacts(a.to_json, b.to_json)
94
75
 
95
- result = merge_pacts(example_pact, @pact_to_merge)
96
- expect(result["interactions"].length).to eq example_pact["interactions"].length + 1
76
+ return_hash ? JSON.parse(result) : result
77
+ end
97
78
  end
98
79
 
99
- it "appends interactions with fewer request headers" do
100
- example_pact["interactions"][0]["request"]["headers"] = { "Content-Type" => "script/javascript" }
101
-
102
- result = merge_pacts(example_pact, @pact_to_merge)
103
- expect(result["interactions"].length).to eq example_pact["interactions"].length + 1
104
- end
105
-
106
- # helper that lets these specs deal with hashes instead of JSON strings
107
- def merge_pacts(a, b, return_hash = true)
108
- result = PactBroker::Pacts::Merger.merge_pacts(a.to_json, b.to_json)
109
-
110
- return_hash ? JSON.parse(result) : result
80
+ describe "#conflict?" do
81
+ before :each do
82
+ @pact_to_compare = load_json_fixture('consumer-provider.json')
83
+ end
84
+
85
+ it "returns false if interactions have different descriptions" do
86
+ @pact_to_compare["interactions"][0]["description"] = "something else"
87
+
88
+ expect(compare_pacts(example_pact, @pact_to_compare)).to eq false
89
+ end
90
+
91
+ it "returns false if interactions have different provider states" do
92
+ @pact_to_compare["interactions"][0]["provider_state"] = "some other thing"
93
+ expect(compare_pacts(example_pact, @pact_to_compare)).to eq false
94
+ end
95
+
96
+ context "when interactions have the same desc/state" do
97
+ it "returns false if request parameters are the same" do
98
+ expect(compare_pacts(example_pact, @pact_to_compare)).to eq false
99
+ end
100
+
101
+ it "returns true if requests have a different query" do
102
+ @pact_to_compare["interactions"][0]["request"]["query"] = "foo=bar&baz=qux"
103
+ expect(compare_pacts(example_pact, @pact_to_compare)).to eq true
104
+ end
105
+
106
+ it "returns true if requests have a different body" do
107
+ @pact_to_compare["interactions"][0]["request"]["body"] = { "something" => { "nested" => "deeply" } }
108
+ expect(compare_pacts(example_pact, @pact_to_compare)).to eq true
109
+ end
110
+
111
+ it "returns true if request method is different" do
112
+ @pact_to_compare["interactions"][0]["request"]["method"] = "post"
113
+ expect(compare_pacts(example_pact, @pact_to_compare)).to eq true
114
+ end
115
+
116
+ it "returns true if request path is different" do
117
+ @pact_to_compare["interactions"][0]["request"]["path"] = "/new_path"
118
+ expect(compare_pacts(example_pact, @pact_to_compare)).to eq true
119
+ end
120
+
121
+ it "returns true if request headers are different" do
122
+ @pact_to_compare["interactions"][0]["request"]["headers"]["Content-Type"] = "text/html"
123
+ expect(compare_pacts(example_pact, @pact_to_compare)).to eq true
124
+ end
125
+
126
+ it "returns true if request has additional headers" do
127
+ @pact_to_compare["interactions"][0]["request"]["headers"]["Accept"] = "text/html"
128
+ expect(compare_pacts(example_pact, @pact_to_compare)).to eq true
129
+ end
130
+
131
+ it "returns true if request has missing headers" do
132
+ @pact_to_compare["interactions"][0]["request"]["headers"].delete("Content-Type")
133
+ expect(compare_pacts(example_pact, @pact_to_compare)).to eq true
134
+ end
135
+ end
136
+
137
+ def compare_pacts(a, b)
138
+ PactBroker::Pacts::Merger.conflict?(a.to_json, b.to_json)
139
+ end
111
140
  end
112
141
  end
113
142
  end
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: 1.10.0
4
+ version: 1.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bethany Skurrie
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2016-08-01 00:00:00.000000000 Z
13
+ date: 2016-08-12 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: httparty
@@ -581,6 +581,8 @@ files:
581
581
  - spec/features/publish_pact_spec.rb
582
582
  - spec/features/update_pacticipant_spec.rb
583
583
  - spec/fixtures/a_consumer-a_provider-2.json
584
+ - spec/fixtures/a_consumer-a_provider-3.json
585
+ - spec/fixtures/a_consumer-a_provider-conflict.json
584
586
  - spec/fixtures/a_consumer-a_provider-merged.json
585
587
  - spec/fixtures/a_consumer-a_provider.json
586
588
  - spec/fixtures/consumer-provider.json
@@ -738,6 +740,8 @@ test_files:
738
740
  - spec/features/publish_pact_spec.rb
739
741
  - spec/features/update_pacticipant_spec.rb
740
742
  - spec/fixtures/a_consumer-a_provider-2.json
743
+ - spec/fixtures/a_consumer-a_provider-3.json
744
+ - spec/fixtures/a_consumer-a_provider-conflict.json
741
745
  - spec/fixtures/a_consumer-a_provider-merged.json
742
746
  - spec/fixtures/a_consumer-a_provider.json
743
747
  - spec/fixtures/consumer-provider.json