pact_broker-client 1.14.1 → 1.15.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +21 -0
  4. data/README.md +27 -1
  5. data/Rakefile +9 -0
  6. data/doc/pacts/markdown/Pact Broker Client - Pact Broker.md +521 -10
  7. data/lib/pact_broker/client/base_client.rb +1 -1
  8. data/lib/pact_broker/client/cli/broker.rb +63 -0
  9. data/lib/pact_broker/client/cli/can_i_deploy_long_desc.txt +1 -1
  10. data/lib/pact_broker/client/cli/create_webhook_long_desc.txt +1 -0
  11. data/lib/pact_broker/client/command_result.rb +12 -0
  12. data/lib/pact_broker/client/hal.rb +4 -0
  13. data/lib/pact_broker/client/hal/entity.rb +78 -0
  14. data/lib/pact_broker/client/hal/entry_point.rb +13 -0
  15. data/lib/pact_broker/client/hal/http_client.rb +82 -0
  16. data/lib/pact_broker/client/hal/link.rb +79 -0
  17. data/lib/pact_broker/client/pacts.rb +7 -1
  18. data/lib/pact_broker/client/version.rb +1 -1
  19. data/lib/pact_broker/client/versions.rb +0 -1
  20. data/lib/pact_broker/client/webhooks/create.rb +114 -0
  21. data/spec/integration/can_i_deploy_spec.rb +1 -3
  22. data/spec/integration/create_version_tag_spec.rb +1 -3
  23. data/spec/lib/pact_broker/client/can_i_deploy_spec.rb +1 -1
  24. data/spec/lib/pact_broker/client/cli/broker_create_webhook_spec.rb +190 -0
  25. data/spec/lib/pact_broker/client/hal/entity_spec.rb +93 -0
  26. data/spec/lib/pact_broker/client/hal/http_client_spec.rb +105 -0
  27. data/spec/lib/pact_broker/client/hal/link_spec.rb +108 -0
  28. data/spec/lib/pact_broker/client/webhooks/create_spec.rb +61 -0
  29. data/spec/pacts/pact_broker_client-pact_broker.json +499 -9
  30. data/spec/service_providers/pact_broker_client_publish_spec.rb +6 -1
  31. data/spec/service_providers/pact_broker_client_retrieve_all_pacts_for_provider_spec.rb +1 -1
  32. data/spec/service_providers/{pact_broker_client_retrive_pact_spec.rb → pact_broker_client_retrieve_pact_spec.rb} +2 -3
  33. data/spec/service_providers/pact_broker_client_versions_spec.rb +1 -1
  34. data/spec/service_providers/pact_helper.rb +46 -0
  35. data/spec/service_providers/webhooks_create_spec.rb +255 -0
  36. data/spec/spec_helper.rb +32 -0
  37. data/spec/support/latest_pacts_for_provider.json +1 -1
  38. data/spec/support/shared_context.rb +6 -3
  39. metadata +24 -4
@@ -1,6 +1,4 @@
1
- is_windows = !!RbConfig::CONFIG['host_os'] =~ /bccwin|cygwin|djgpp|mingw|mswin|wince/
2
-
3
- describe "pact-broker can-i-deploy", pending: is_windows do
1
+ describe "pact-broker can-i-deploy", skip_windows: true do
4
2
  before(:all) do
5
3
  @pipe = IO.popen("bundle exec pact-stub-service spec/pacts/pact_broker_client-pact_broker.json -p 5000")
6
4
  sleep 2
@@ -1,6 +1,4 @@
1
- is_windows = !!RbConfig::CONFIG['host_os'] =~ /bccwin|cygwin|djgpp|mingw|mswin|wince/
2
-
3
- describe "pact-broker create-version-tag", pending: is_windows do
1
+ describe "pact-broker create-version-tag", skip_windows: true do
4
2
  before(:all) do
5
3
  @pipe = IO.popen("bundle exec pact-stub-service spec/pacts/pact_broker_client-pact_broker.json -p 5001")
6
4
  sleep 2
@@ -76,7 +76,7 @@ module PactBroker
76
76
 
77
77
  context "when a StandardError is raised" do
78
78
  before do
79
- allow(Retry).to receive(:sleep).and_return(0)
79
+ allow(Retry).to receive(:until_true) { |&block| block.call }
80
80
  allow($stderr).to receive(:puts)
81
81
  allow(matrix_client).to receive(:get).and_raise(StandardError.new('error text'))
82
82
  end
@@ -0,0 +1,190 @@
1
+ require 'pact_broker/client/cli/broker'
2
+ require 'pact_broker/client/webhooks/create'
3
+
4
+ module PactBroker
5
+ module Client
6
+ module CLI
7
+ describe Broker do
8
+ describe "create_webhook" do
9
+ before do
10
+ allow($stdout).to receive(:puts)
11
+ allow(PactBroker::Client::Webhooks::Create).to receive(:call).and_return(command_result)
12
+ broker.options = OpenStruct.new(options_hash)
13
+ end
14
+
15
+ let(:broker) { Broker.new }
16
+ let(:data) { 'data' }
17
+ let(:user) { "username:password" }
18
+ let(:command_result) { double('command result', success: success, message: 'message') }
19
+ let(:success) { true }
20
+ let(:header) { ["Foo: bar", "Bar: foo"] }
21
+
22
+ let(:options_hash) do
23
+ {
24
+ request: "POST",
25
+ header: header,
26
+ data: data,
27
+ user: user,
28
+ consumer: "consumer",
29
+ provider: "provider",
30
+ broker_base_url: "http://broker",
31
+ broker_username: "username",
32
+ broker_password: "password",
33
+ contract_content_changed: true,
34
+ verbose: true
35
+ }
36
+ end
37
+
38
+ let(:expected_params) do
39
+ {
40
+ http_method: "POST",
41
+ url: "http://webhook",
42
+ headers: { "Foo" => "bar", "Bar" => "foo"},
43
+ username: "username",
44
+ password: "password",
45
+ body: "data",
46
+ consumer: "consumer",
47
+ provider: "provider",
48
+ events: ["contract_content_changed"]
49
+ }.tap { |it| Pact::Fixture.add_fixture(:create_webhook_params, it) }
50
+ end
51
+
52
+ subject { broker.create_webhook "http://webhook" }
53
+
54
+ it "calls PactBroker::Client::Webhooks::Create with the webhook params" do
55
+ expect(PactBroker::Client::Webhooks::Create).to receive(:call) do | params, _, _ |
56
+ expect(params).to eq expected_params
57
+ command_result
58
+ end
59
+ subject
60
+ end
61
+
62
+ it "calls PactBroker::Client::Webhooks::Create with pact broker details" do
63
+ expect(PactBroker::Client::Webhooks::Create).to receive(:call) do | _, broker_base_url, pact_broker_client_options |
64
+ expect(broker_base_url).to eq "http://broker"
65
+ expect(pact_broker_client_options).to eq(basic_auth: { username: "username", password: "password"}, verbose: true)
66
+ command_result
67
+ end
68
+ subject
69
+ end
70
+
71
+ context "when neither event type is selected" do
72
+ before do
73
+ options_hash.delete(:contract_content_changed)
74
+ broker.options = OpenStruct.new(options_hash)
75
+ end
76
+
77
+ it "raises an error" do
78
+ expect { subject }.to raise_error PactBroker::Client::Error, /You must select at least one/
79
+ end
80
+ end
81
+
82
+ context "with no basic auth" do
83
+ before do
84
+ options_hash.delete(:broker_username)
85
+ options_hash.delete(:broker_password)
86
+ broker.options = OpenStruct.new(options_hash)
87
+ end
88
+
89
+ it "calls Webhooks::Create without basic auth" do
90
+ expect(PactBroker::Client::Webhooks::Create).to receive(:call) do | _, _, pact_broker_client_options |
91
+ expect(pact_broker_client_options).to eq(verbose: true)
92
+ command_result
93
+ end
94
+ subject
95
+ end
96
+ end
97
+
98
+ context "when there are no headers specified" do
99
+ let(:header) { nil }
100
+
101
+ it "calls Webhooks::Create with an empty hash of headers" do
102
+ expect(PactBroker::Client::Webhooks::Create).to receive(:call) do | params, _, _ |
103
+ expect(params[:headers]).to eq({})
104
+ command_result
105
+ end
106
+ subject
107
+ end
108
+ end
109
+
110
+ context "when data is nil" do
111
+ let(:data) { nil }
112
+
113
+ it "alls Webhooks::Create with a nil body" do
114
+ expect(PactBroker::Client::Webhooks::Create).to receive(:call) do | params, _, _ |
115
+ expect(params[:body]).to be nil
116
+ command_result
117
+ end
118
+ subject
119
+ end
120
+ end
121
+
122
+ context "when a file reference is passed for the data" do
123
+ before do
124
+ FileUtils.mkdir_p "tmp"
125
+ File.open("tmp/body.json", "w") { |file| file << "file" }
126
+ end
127
+
128
+ let(:data) { "@tmp/body.json" }
129
+
130
+ it "reads the file and passes it in to the Webhooks::Create call" do
131
+ expect(PactBroker::Client::Webhooks::Create).to receive(:call) do | params, _, _ |
132
+ expect(params[:body]).to eq "file"
133
+ command_result
134
+ end
135
+ subject
136
+ end
137
+
138
+ context "when the file is not found" do
139
+
140
+ let(:data) { "@doesnotexist.json" }
141
+
142
+ it "raises a PactBroker::Client::Error" do
143
+ expect { subject }.to raise_error PactBroker::Client::Error, /Couldn't read data from file/
144
+ end
145
+ end
146
+
147
+ context "when successful" do
148
+ it "prints the message to stdout" do
149
+ expect($stdout).to receive(:puts).with('message')
150
+ subject
151
+ end
152
+ end
153
+
154
+ context "when not successful" do
155
+ let(:success) { false }
156
+
157
+ it "prints the message to stderr" do
158
+ expect($stdout).to receive(:puts).with('message')
159
+ begin
160
+ subject
161
+ rescue SystemExit
162
+ end
163
+ end
164
+
165
+ it "exits with code 1" do
166
+ exited_with_error = false
167
+ begin
168
+ subject
169
+ rescue SystemExit
170
+ exited_with_error = true
171
+ end
172
+ expect(exited_with_error).to be true
173
+ end
174
+ end
175
+
176
+ context "when a PactBroker::Client::Error is raised" do
177
+ before do
178
+ allow(PactBroker::Client::Webhooks::Create).to receive(:call).and_raise(PactBroker::Client::Error, "foo")
179
+ end
180
+
181
+ it "raises a WebhookCreationError which does not show an ugly stack trace" do
182
+ expect { subject }.to raise_error(WebhookCreationError, /foo/)
183
+ end
184
+ end
185
+ end
186
+ end
187
+ end
188
+ end
189
+ end
190
+ end
@@ -0,0 +1,93 @@
1
+ require 'pact_broker/client/hal/entity'
2
+ require 'pact_broker/client/hal/http_client'
3
+
4
+ module PactBroker::Client
5
+ module Hal
6
+ describe Entity do
7
+ let(:http_client) do
8
+ instance_double('Pact::Hal::HttpClient', post: provider_response)
9
+ end
10
+
11
+ let(:provider_response) do
12
+ double('response', body: provider_hash, success?: true)
13
+ end
14
+
15
+ let(:provider_hash) do
16
+ {
17
+ "name" => "Provider"
18
+ }
19
+ end
20
+ let(:pact_hash) do
21
+ {
22
+ "name" => "a name",
23
+
24
+ "_links" => {
25
+ "pb:provider" => {
26
+ "href" => "http://provider"
27
+ },
28
+ "pb:version-tag" => {
29
+ "href" => "http://provider/version/{version}/tag/{tag}"
30
+ }
31
+ }
32
+ }
33
+ end
34
+
35
+ subject(:entity) { Entity.new(pact_hash, http_client) }
36
+
37
+ it "delegates to the properties in the data" do
38
+ expect(subject.name).to eq "a name"
39
+ end
40
+
41
+ describe "post" do
42
+ let(:post_provider) { entity.post("pb:provider", {'some' => 'data'} ) }
43
+
44
+ it "executes an http request" do
45
+ expect(http_client).to receive(:post).with("http://provider", '{"some":"data"}', {})
46
+ post_provider
47
+ end
48
+
49
+ it "returns the entity for the relation" do
50
+ expect(post_provider).to be_a(Entity)
51
+ end
52
+
53
+ context "with template params" do
54
+ let(:post_provider) { entity._link("pb:version-tag").expand(version: "1", tag: "prod").post({'some' => 'data'} ) }
55
+
56
+ it "posts to the expanded URL" do
57
+ expect(http_client).to receive(:post).with("http://provider/version/1/tag/prod", '{"some":"data"}', {})
58
+ post_provider
59
+ end
60
+ end
61
+ end
62
+
63
+ describe "can?" do
64
+ context "when the relation exists" do
65
+ it "returns true" do
66
+ expect(subject.can?('pb:provider')).to be true
67
+ end
68
+ end
69
+
70
+ context "when the relation does not exist" do
71
+ it "returns false" do
72
+ expect(subject.can?('pb:consumer')).to be false
73
+ end
74
+ end
75
+ end
76
+
77
+ describe 'fetch' do
78
+ context 'when the key exist' do
79
+ it 'returns fetched value' do
80
+ expect(subject.fetch('pb:provider')).to be do
81
+ {href: 'http://provider'}
82
+ end
83
+ end
84
+ end
85
+ context "when the key doesn't not exist" do
86
+ it 'returns nil' do
87
+ expect(subject.fetch('i-dont-exist')).to be nil
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,105 @@
1
+ require 'pact_broker/client/hal/http_client'
2
+
3
+ module PactBroker::Client
4
+ module Hal
5
+ describe HttpClient do
6
+ before do
7
+ allow(Retry).to receive(:until_true) { |&block| block.call }
8
+ end
9
+
10
+ subject { HttpClient.new(username: 'foo', password: 'bar') }
11
+
12
+ describe "get" do
13
+ let!(:request) do
14
+ stub_request(:get, "http://example.org/").
15
+ with( headers: {
16
+ 'Accept'=>'application/hal+json',
17
+ 'Authorization'=>'Basic Zm9vOmJhcg=='
18
+ }).
19
+ to_return(status: 200, body: response_body, headers: {'Content-Type' => 'application/json'})
20
+ end
21
+
22
+ let(:response_body) { {some: 'json'}.to_json }
23
+ let(:do_get) { subject.get('http://example.org') }
24
+
25
+ it "performs a get request" do
26
+ do_get
27
+ expect(request).to have_been_made
28
+ end
29
+
30
+ context "with get params" do
31
+ let!(:request) do
32
+ stub_request(:get, "http://example.org/?foo=hello+world&bar=wiffle").
33
+ to_return(status: 200)
34
+ end
35
+
36
+ let(:do_get) { subject.get('http://example.org', { 'foo' => 'hello world', 'bar' => 'wiffle' }) }
37
+
38
+ it "correctly converts and encodes get params" do
39
+ do_get
40
+ expect(request).to have_been_made
41
+ end
42
+ end
43
+
44
+
45
+ it "retries on failure" do
46
+ expect(Retry).to receive(:until_true)
47
+ do_get
48
+ end
49
+
50
+ it "returns a response" do
51
+ expect(do_get.body).to eq({"some" => "json"})
52
+ end
53
+ end
54
+
55
+ describe "post" do
56
+ let!(:request) do
57
+ stub_request(:post, "http://example.org/").
58
+ with( headers: {
59
+ 'Accept'=>'application/hal+json',
60
+ 'Authorization'=>'Basic Zm9vOmJhcg==',
61
+ 'Content-Type'=>'application/json'
62
+ },
63
+ body: request_body).
64
+ to_return(status: 200, body: response_body, headers: {'Content-Type' => 'application/json'})
65
+ end
66
+
67
+ let(:request_body) { {some: 'data'}.to_json }
68
+ let(:response_body) { {some: 'json'}.to_json }
69
+
70
+ let(:do_post) { subject.post('http://example.org/', request_body) }
71
+
72
+ it "performs a post request" do
73
+ do_post
74
+ expect(request).to have_been_made
75
+ end
76
+
77
+ it "calls Retry.until_true" do
78
+ expect(Retry).to receive(:until_true)
79
+ do_post
80
+ end
81
+
82
+ it "returns a response" do
83
+ expect(do_post.body).to eq({"some" => "json"})
84
+ end
85
+
86
+ context "with custom headers" do
87
+ let!(:request) do
88
+ stub_request(:post, "http://example.org/").
89
+ with( headers: {
90
+ 'Accept'=>'foo'
91
+ }).
92
+ to_return(status: 200)
93
+ end
94
+
95
+ let(:do_post) { subject.post('http://example.org/', request_body, {"Accept" => "foo"} ) }
96
+
97
+ it "performs a post request with custom headers" do
98
+ do_post
99
+ expect(request).to have_been_made
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,108 @@
1
+ require 'pact_broker/client/hal/link'
2
+ require 'pact_broker/client/hal/entity'
3
+ require 'pact_broker/client/hal/http_client'
4
+
5
+ module PactBroker::Client
6
+ module Hal
7
+ describe Link do
8
+ let(:http_client) do
9
+ instance_double('PactBroker::Client::Hal::HttpClient', post: response)
10
+ end
11
+
12
+ let(:response) do
13
+ instance_double('PactBroker::Client::Hal::HttpClient::Response', success?: success, body: response_body)
14
+ end
15
+
16
+ let(:success) { true }
17
+
18
+ let(:entity) do
19
+ instance_double('PactBroker::Client::Hal::Entity')
20
+ end
21
+
22
+ let(:attrs) do
23
+ {
24
+ 'href' => 'http://foo/{bar}',
25
+ 'title' => 'title',
26
+ method: :post
27
+ }
28
+ end
29
+
30
+ let(:response_body) do
31
+ {
32
+ 'some' => 'body'
33
+ }
34
+ end
35
+
36
+ subject { Link.new(attrs, http_client) }
37
+
38
+ before do
39
+ allow(PactBroker::Client::Hal::Entity).to receive(:new).and_return(entity)
40
+ end
41
+
42
+ describe "#run" do
43
+ let(:do_run) { subject.run('foo' => 'bar') }
44
+
45
+ it "executes the configured http request" do
46
+ expect(http_client).to receive(:post)
47
+ do_run
48
+ end
49
+
50
+ it "creates an Entity" do
51
+ expect(PactBroker::Client::Hal::Entity).to receive(:new).with(response_body, http_client, response)
52
+ do_run
53
+ end
54
+
55
+ it "returns an Entity" do
56
+ expect(do_run).to eq entity
57
+ end
58
+
59
+ context "when an error response is returned" do
60
+ before do
61
+ allow(PactBroker::Client::Hal::ErrorEntity).to receive(:new).and_return(entity)
62
+ end
63
+
64
+ let(:success) { false }
65
+
66
+ it "creates an ErrorEntity" do
67
+ expect(PactBroker::Client::Hal::ErrorEntity).to receive(:new).with(response_body, http_client, response)
68
+ do_run
69
+ end
70
+ end
71
+ end
72
+
73
+ describe "#get" do
74
+ before do
75
+ allow(http_client).to receive(:get).and_return(response)
76
+ end
77
+
78
+ let(:do_get) { subject.get({ 'foo' => 'bar' }) }
79
+
80
+ it "executes an HTTP Get request" do
81
+ expect(http_client).to receive(:get).with('http://foo/{bar}', { 'foo' => 'bar' }, {})
82
+ do_get
83
+ end
84
+ end
85
+
86
+ describe "#post" do
87
+ let(:do_post) { subject.post({ 'foo' => 'bar' }, { 'Accept' => 'foo' }) }
88
+
89
+ context "with custom headers" do
90
+ it "executes an HTTP Post request with the custom headers" do
91
+ expect(http_client).to receive(:post).with('http://foo/{bar}', '{"foo":"bar"}', { 'Accept' => 'foo' })
92
+ do_post
93
+ end
94
+ end
95
+ end
96
+
97
+ describe "#expand" do
98
+ it "returns a duplicate Link with the expanded href" do
99
+ expect(subject.expand(bar: 'wiffle').href).to eq "http://foo/wiffle"
100
+ end
101
+
102
+ it "returns a duplicate Link with the expanded href with URL escaping" do
103
+ expect(subject.expand(bar: 'wiffle meep').href).to eq "http://foo/wiffle%20meep"
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end