pact_broker 1.10.0 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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