cfoundry 0.4.21 → 0.5.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.
- data/Rakefile +47 -24
- data/lib/cfoundry/auth_token.rb +48 -0
- data/lib/cfoundry/baseclient.rb +96 -277
- data/lib/cfoundry/client.rb +2 -0
- data/lib/cfoundry/concerns/login_helpers.rb +13 -0
- data/lib/cfoundry/errors.rb +21 -13
- data/lib/cfoundry/rest_client.rb +290 -0
- data/lib/cfoundry/test_support.rb +3 -0
- data/lib/cfoundry/trace_helpers.rb +9 -9
- data/lib/cfoundry/uaaclient.rb +66 -74
- data/lib/cfoundry/upload_helpers.rb +2 -0
- data/lib/cfoundry/v1/app.rb +2 -2
- data/lib/cfoundry/v1/base.rb +4 -51
- data/lib/cfoundry/v1/client.rb +7 -30
- data/lib/cfoundry/v1/model.rb +22 -5
- data/lib/cfoundry/v1/model_magic.rb +30 -15
- data/lib/cfoundry/v2/app.rb +2 -5
- data/lib/cfoundry/v2/base.rb +10 -74
- data/lib/cfoundry/v2/client.rb +19 -30
- data/lib/cfoundry/v2/domain.rb +1 -4
- data/lib/cfoundry/v2/model.rb +1 -3
- data/lib/cfoundry/v2/model_magic.rb +13 -23
- data/lib/cfoundry/version.rb +1 -1
- data/lib/cfoundry/zip.rb +1 -1
- data/spec/cfoundry/auth_token_spec.rb +77 -0
- data/spec/cfoundry/baseclient_spec.rb +54 -30
- data/spec/cfoundry/errors_spec.rb +10 -13
- data/spec/cfoundry/rest_client_spec.rb +238 -0
- data/spec/cfoundry/trace_helpers_spec.rb +10 -5
- data/spec/cfoundry/uaaclient_spec.rb +141 -114
- data/spec/cfoundry/upload_helpers_spec.rb +129 -0
- data/spec/cfoundry/v1/base_spec.rb +2 -2
- data/spec/cfoundry/v1/client_spec.rb +17 -0
- data/spec/cfoundry/v1/model_magic_spec.rb +43 -0
- data/spec/cfoundry/v2/base_spec.rb +256 -33
- data/spec/cfoundry/v2/client_spec.rb +68 -0
- data/spec/cfoundry/v2/model_magic_spec.rb +49 -0
- data/spec/fixtures/apps/with_vmcignore/ignored_dir/file_in_ignored_dir.txt +1 -0
- data/spec/fixtures/apps/with_vmcignore/ignored_file.txt +1 -0
- data/spec/fixtures/apps/with_vmcignore/non_ignored_dir/file_in_non_ignored_dir.txt +1 -0
- data/spec/fixtures/apps/with_vmcignore/non_ignored_dir/ignored_file.txt +1 -0
- data/spec/fixtures/apps/with_vmcignore/non_ignored_file.txt +1 -0
- data/spec/fixtures/empty_file +0 -0
- data/spec/spec_helper.rb +4 -4
- data/spec/support/randoms.rb +3 -0
- data/spec/support/shared_examples/client_login_examples.rb +46 -0
- data/spec/support/{summaries.rb → shared_examples/model_summary_examples.rb} +0 -0
- data/spec/support/v1_fake_helper.rb +144 -0
- metadata +101 -37
- data/lib/cfoundry/spec_helper.rb +0 -1
@@ -0,0 +1,238 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe CFoundry::RestClient do
|
4
|
+
let(:token) { nil }
|
5
|
+
let(:rest_client) { CFoundry::RestClient.new("https://api.cloudfoundry.com", token) }
|
6
|
+
|
7
|
+
describe '#request' do
|
8
|
+
let(:path) { "some-path" }
|
9
|
+
let(:url) { "https://api.cloudfoundry.com/some-path" }
|
10
|
+
let(:method) { "GET" }
|
11
|
+
let(:options) { {} }
|
12
|
+
|
13
|
+
def check_request(method = :get, &block)
|
14
|
+
request_stub = stub_request(method, url).to_return do |req|
|
15
|
+
block.call(req)
|
16
|
+
{}
|
17
|
+
end
|
18
|
+
subject
|
19
|
+
expect(request_stub).to have_been_requested
|
20
|
+
end
|
21
|
+
|
22
|
+
subject { rest_client.request(method, path, options) }
|
23
|
+
|
24
|
+
describe 'headers' do
|
25
|
+
%w[Authorization Proxy-User X-Request-Id Content-Type].each do |header_name|
|
26
|
+
it "should not include the #{header_name} by default" do
|
27
|
+
check_request do |req|
|
28
|
+
expect(req.headers).not_to have_key(header_name)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should not provide specific accept mimetypes by default" do
|
34
|
+
check_request do |req|
|
35
|
+
expect(req.headers["Accept"]).to eql("*/*")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should always include a content length' do
|
40
|
+
check_request do |req|
|
41
|
+
expect(req.headers["Content-Length"]).to eql(0)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context "when a payload is passed" do
|
46
|
+
context "when the payload is a string" do
|
47
|
+
let(:options) { { :payload => "some payload"} }
|
48
|
+
|
49
|
+
it 'includes a content length matching the payload size' do
|
50
|
+
check_request do |req|
|
51
|
+
expect(req.headers["Content-Length"]).to eql("some payload".length)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context "when the payload is a hash and the content-type is JSON" do
|
57
|
+
let(:options) { { :payload => { "key" => "value" }, :content => :json } }
|
58
|
+
|
59
|
+
it 'includes a content length matching the JSON encoded length' do
|
60
|
+
check_request do |req|
|
61
|
+
expect(req.headers["Content-Length"]).to eql('{"key":"value"}'.length)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context "when the payload is a hash (i.e. multipart upload)" do
|
67
|
+
let(:method) { "PUT" }
|
68
|
+
let(:options) { { :payload => { "key" => "value" } } }
|
69
|
+
|
70
|
+
it 'includes a nonzero content length' do
|
71
|
+
check_request(:put) do |req|
|
72
|
+
expect(req.headers["Content-Length"].to_i).to be > 0
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'and the token is set' do
|
79
|
+
let(:token_header) { "bearer something" }
|
80
|
+
let(:token) { CFoundry::AuthToken.new(token_header) }
|
81
|
+
|
82
|
+
it 'should include Authorization in the header' do
|
83
|
+
check_request do |req|
|
84
|
+
expect(req.headers["Authorization"]).to eq(token_header)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context 'and the request_id is set' do
|
90
|
+
before { rest_client.request_id = "SomeRequestId" }
|
91
|
+
|
92
|
+
it 'should include X-Request-Id in the header' do
|
93
|
+
check_request do |req|
|
94
|
+
expect(req.headers["X-Request-Id"]).to eq "SomeRequestId"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context 'and the proxy is set' do
|
100
|
+
before { rest_client.instance_variable_set(:@proxy, "some proxy") }
|
101
|
+
|
102
|
+
it 'should include X-Request-Id in the header' do
|
103
|
+
check_request do |req|
|
104
|
+
expect(req.headers["Proxy-User"]).to eq "some proxy"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
context 'and the content is passed in' do
|
110
|
+
let(:options) { {:content => "text/xml"} }
|
111
|
+
|
112
|
+
it 'should include Content-Type in the header' do
|
113
|
+
check_request do |req|
|
114
|
+
expect(req.headers["Content-Type"]).to eq "text/xml"
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
context 'and custom headers are passed in' do
|
120
|
+
let(:options) { {:headers => {"X-Foo" => "Bar"}} }
|
121
|
+
|
122
|
+
it 'should include the custom header in the header' do
|
123
|
+
check_request do |req|
|
124
|
+
expect(req.headers["X-Foo"]).to eq "Bar"
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
context 'and it overrides an existing one' do
|
129
|
+
let(:options) { { :content => "text/xml", :headers => { "Content-Type" => "text/html" } } }
|
130
|
+
|
131
|
+
it 'uses the custom header' do
|
132
|
+
check_request do |req|
|
133
|
+
expect(req.headers["Content-Type"]).to eq "text/html"
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
describe 'payload' do
|
141
|
+
|
142
|
+
end
|
143
|
+
|
144
|
+
describe 'errors' do
|
145
|
+
end
|
146
|
+
|
147
|
+
describe "the return value" do
|
148
|
+
before do
|
149
|
+
stub_request(:get, url).to_return({
|
150
|
+
:status => 201,
|
151
|
+
:headers => { "Content-Type" => "application/json"},
|
152
|
+
:body => '{ "foo": 1 }'
|
153
|
+
})
|
154
|
+
end
|
155
|
+
|
156
|
+
it "returns a request hash and a response hash" do
|
157
|
+
expect(subject).to be_an(Array)
|
158
|
+
expect(subject.length).to eq(2)
|
159
|
+
end
|
160
|
+
|
161
|
+
describe "the returned request hash" do
|
162
|
+
it "returns a hash of :headers, :url, :body and :method" do
|
163
|
+
expect(subject[0]).to eq({
|
164
|
+
:url => url,
|
165
|
+
:method => "GET",
|
166
|
+
:headers => { "Content-Length" => 0 },
|
167
|
+
:body => nil
|
168
|
+
})
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
describe "the returned response hash" do
|
173
|
+
it "returns a hash of :headers, :status, :body" do
|
174
|
+
expect(subject[1]).to eq({
|
175
|
+
:status => "201",
|
176
|
+
:headers => { "content-type" => "application/json"},
|
177
|
+
:body => '{ "foo": 1 }'
|
178
|
+
})
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
describe "when the path starts with a slash" do
|
184
|
+
let(:path) { "/some-path/some-segment" }
|
185
|
+
|
186
|
+
it "doesn't add a double slash" do
|
187
|
+
stub = stub_request(:get, "https://api.cloudfoundry.com/some-path/some-segment")
|
188
|
+
subject
|
189
|
+
expect(stub).to have_been_requested
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
describe "when the path does not start with a slash" do
|
194
|
+
let(:path) { "some-path/some-segment" }
|
195
|
+
|
196
|
+
it "doesn't add a double slash" do
|
197
|
+
stub = stub_request(:get, "https://api.cloudfoundry.com/some-path/some-segment")
|
198
|
+
subject
|
199
|
+
expect(stub).to have_been_requested
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
describe 'trace' do
|
204
|
+
before do
|
205
|
+
rest_client.trace = true
|
206
|
+
stub_request(:get, url).to_return(:status => 200, :headers => { "content-type" => "application/json" }, :body => '{"some": "json"}')
|
207
|
+
end
|
208
|
+
|
209
|
+
it "prints the request and the response" do
|
210
|
+
mock(rest_client).print_request({:headers=>{"Content-Length"=>0}, :url=>"https://api.cloudfoundry.com/some-path", :method=>"GET", :body=>nil})
|
211
|
+
mock(rest_client).print_response({ :status => "200", :headers => { "content-type" => "application/json" }, :body => '{"some": "json"}' })
|
212
|
+
subject
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
describe "following redirects" do
|
217
|
+
before do
|
218
|
+
stub_request(:post, "https://api.cloudfoundry.com/apps").to_return(
|
219
|
+
:status => 301,
|
220
|
+
:headers => { "location" => "https://api.cloudfoundry.com/apps/some-guid" }
|
221
|
+
)
|
222
|
+
stub_request(:get, "https://api.cloudfoundry.com/apps/some-guid").to_return(
|
223
|
+
:status => 200,
|
224
|
+
:body => '{"some": "json"}'
|
225
|
+
)
|
226
|
+
end
|
227
|
+
|
228
|
+
it "follows redirects correctly, returning the response to the 2nd redirect" do
|
229
|
+
request, response = rest_client.request("POST", "apps")
|
230
|
+
expect(response).to eql(
|
231
|
+
:status => "200",
|
232
|
+
:headers => {},
|
233
|
+
:body => '{"some": "json"}'
|
234
|
+
)
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
@@ -2,8 +2,14 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe CFoundry::TraceHelpers do
|
4
4
|
let(:fake_class) { Class.new { include CFoundry::TraceHelpers } }
|
5
|
-
let(:request)
|
6
|
-
|
5
|
+
let(:request) do
|
6
|
+
{
|
7
|
+
:method => "GET",
|
8
|
+
:url => "http://api.cloudfoundry.com/foo",
|
9
|
+
:headers => { "bb-foo" => "bar", "accept" => "*/*" }
|
10
|
+
}
|
11
|
+
end
|
12
|
+
let(:response) { { :status => 404, :body => "not found", :headers => {} } }
|
7
13
|
|
8
14
|
shared_examples "request_trace tests" do
|
9
15
|
it { should include request_trace }
|
@@ -12,7 +18,7 @@ describe CFoundry::TraceHelpers do
|
|
12
18
|
end
|
13
19
|
|
14
20
|
shared_examples "response_trace tests" do
|
15
|
-
before {
|
21
|
+
before { response[:body] = response_body }
|
16
22
|
|
17
23
|
it "traces the provided response" do
|
18
24
|
fake_class.new.response_trace(response).should == response_trace
|
@@ -33,7 +39,7 @@ describe CFoundry::TraceHelpers do
|
|
33
39
|
context "with a request body" do
|
34
40
|
let(:body_trace) { "REQUEST_BODY: Some body text" }
|
35
41
|
|
36
|
-
before { request
|
42
|
+
before { request[:body] = "Some body text" }
|
37
43
|
|
38
44
|
include_examples "request_trace tests"
|
39
45
|
end
|
@@ -53,7 +59,6 @@ describe CFoundry::TraceHelpers do
|
|
53
59
|
end
|
54
60
|
|
55
61
|
context "with a JSON response body" do
|
56
|
-
|
57
62
|
let(:response_body) { "{\"name\": \"vcap\",\"build\": 2222,\"support\": \"http://support.cloudfoundry.com\"}" }
|
58
63
|
let(:response_trace) { "RESPONSE: [404]\nRESPONSE_HEADERS:\n\nRESPONSE_BODY:\n#{MultiJson.dump(MultiJson.load(response_body), :pretty => true)}" }
|
59
64
|
|
@@ -3,13 +3,28 @@ require "spec_helper"
|
|
3
3
|
describe CFoundry::UAAClient do
|
4
4
|
let(:target) { "https://uaa.example.com" }
|
5
5
|
let(:uaa) { CFoundry::UAAClient.new(target) }
|
6
|
+
let(:auth_header) { "bearer access-token" }
|
7
|
+
|
8
|
+
before do
|
9
|
+
uaa.token = CFoundry::AuthToken.new(auth_header)
|
10
|
+
end
|
11
|
+
|
12
|
+
shared_examples "UAA wrapper" do
|
13
|
+
it "converts UAA errors to CFoundry equivalents" do
|
14
|
+
mock(uaa).wrap_uaa_errors { nil }
|
15
|
+
subject
|
16
|
+
end
|
17
|
+
end
|
6
18
|
|
7
19
|
describe '#prompts' do
|
8
20
|
subject { uaa.prompts }
|
9
21
|
|
22
|
+
include_examples "UAA wrapper"
|
23
|
+
|
10
24
|
# GET (target)/login
|
11
25
|
it "receives the prompts from /login" do
|
12
26
|
stub_request(:get, "#{target}/login").to_return :status => 200,
|
27
|
+
:headers => {'Content-Type' => 'application/json'},
|
13
28
|
:body => <<EOF
|
14
29
|
{
|
15
30
|
"timestamp": "2012-11-08T13:32:18+0000",
|
@@ -42,54 +57,37 @@ EOF
|
|
42
57
|
describe '#authorize' do
|
43
58
|
let(:username) { "foo@bar.com" }
|
44
59
|
let(:password) { "test" }
|
60
|
+
let(:creds) { {:username => username, :password => password} }
|
61
|
+
let(:state) { 'somestate' }
|
62
|
+
let(:redirect_uri) { 'https://uaa.cloudfoundry.com/redirect/vmc' }
|
63
|
+
let(:auth) { Object.new }
|
45
64
|
|
46
|
-
subject { uaa.authorize(
|
65
|
+
subject { uaa.authorize(username, password) }
|
47
66
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
"#{target}/oauth/authorize"
|
52
|
-
).with(
|
53
|
-
:query => {
|
54
|
-
"client_id" => uaa.client_id,
|
55
|
-
"redirect_uri" => uaa.redirect_uri,
|
56
|
-
"response_type" => "token"
|
57
|
-
}
|
58
|
-
).to_return(
|
59
|
-
:status => 302,
|
60
|
-
:headers => {
|
61
|
-
"Location" => "#{uaa.redirect_uri}#access_token=bar&token_type=foo&fizz=buzz&foo=bar"
|
62
|
-
}
|
63
|
-
)
|
67
|
+
before { stub(uaa).token_issuer.stub!.implicit_grant_with_creds { auth } }
|
68
|
+
|
69
|
+
include_examples "UAA wrapper"
|
64
70
|
|
65
|
-
|
71
|
+
it 'returns the token on successful authentication' do
|
72
|
+
stub(uaa).token_issuer.mock!.implicit_grant_with_creds(creds) { auth }
|
73
|
+
expect(subject).to eq auth
|
66
74
|
end
|
67
75
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
).with(
|
73
|
-
:query => {
|
74
|
-
"client_id" => uaa.client_id,
|
75
|
-
"redirect_uri" => uaa.redirect_uri,
|
76
|
-
"response_type" => "token"
|
77
|
-
}
|
78
|
-
).to_return(
|
79
|
-
:status => 401,
|
80
|
-
:headers => {
|
81
|
-
"Location" => "#{uaa.redirect_uri}#access_token=bar&token_type=foo&fizz=buzz&foo=bar"
|
82
|
-
},
|
83
|
-
:body => <<EOF
|
84
|
-
{
|
85
|
-
"error": "unauthorized",
|
86
|
-
"error_description": "Bad credentials"
|
87
|
-
}
|
88
|
-
EOF
|
89
|
-
)
|
76
|
+
context 'when authorization fails' do
|
77
|
+
context 'in the expected way' do
|
78
|
+
it 'raises a CFoundry::Denied error' do
|
79
|
+
stub(uaa).token_issuer.stub!.implicit_grant_with_creds { raise CF::UAA::BadResponse.new("401: FooBar") }
|
90
80
|
|
91
|
-
|
92
|
-
|
81
|
+
expect { subject }.to raise_error(CFoundry::Denied, "401: Authorization failed")
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context 'in an unexpected way' do
|
86
|
+
it 'raises a CFoundry::Denied error' do
|
87
|
+
stub(uaa).token_issuer.stub!.implicit_grant_with_creds { raise CF::UAA::BadResponse.new("no_status_code") }
|
88
|
+
expect { subject }.to raise_error(CFoundry::Denied, "400: Authorization failed")
|
89
|
+
end
|
90
|
+
end
|
93
91
|
end
|
94
92
|
end
|
95
93
|
|
@@ -97,10 +95,25 @@ EOF
|
|
97
95
|
subject { uaa.users }
|
98
96
|
|
99
97
|
it 'requests /Users' do
|
100
|
-
|
101
|
-
:
|
102
|
-
|
103
|
-
|
98
|
+
stub_request(:get, "#{target}/Users").with(
|
99
|
+
:headers => { "authorization" => auth_header }
|
100
|
+
).to_return(
|
101
|
+
:headers => {'Content-Type' => 'application/json'},
|
102
|
+
:body => '{ "resources": [] }'
|
103
|
+
)
|
104
|
+
expect(subject).to eq({'resources' => []})
|
105
|
+
end
|
106
|
+
|
107
|
+
context "when there is no token" do
|
108
|
+
before { uaa.token = nil }
|
109
|
+
|
110
|
+
it "doesn't blow up" do
|
111
|
+
stub_request(:get, "#{target}/Users").to_return(
|
112
|
+
:headers => {'Content-Type' => 'application/json'},
|
113
|
+
:body => '{ "resources": [] }'
|
114
|
+
)
|
115
|
+
expect(subject).to eq({'resources' => []})
|
116
|
+
end
|
104
117
|
end
|
105
118
|
end
|
106
119
|
|
@@ -111,30 +124,21 @@ EOF
|
|
111
124
|
|
112
125
|
subject { uaa.change_password(guid, new, old) }
|
113
126
|
|
127
|
+
include_examples "UAA wrapper"
|
128
|
+
|
114
129
|
it 'sends a password change request' do
|
115
|
-
req = stub_request(
|
116
|
-
:put,
|
117
|
-
"#{target}/Users/#{guid}/password"
|
118
|
-
).with(
|
119
|
-
:body => {
|
120
|
-
:password => new,
|
121
|
-
:oldPassword => old
|
122
|
-
},
|
130
|
+
req = stub_request(:put, "#{target}/Users/#{guid}/password").with(
|
123
131
|
:headers => {
|
124
|
-
"Content-Type" => "application/json",
|
125
|
-
"Accept" => "application/json"
|
132
|
+
"Content-Type" => "application/json;charset=utf-8",
|
133
|
+
"Accept" => "application/json;charset=utf-8",
|
134
|
+
"Authorization" => auth_header
|
126
135
|
}
|
127
136
|
).to_return(
|
128
137
|
:status => 200,
|
129
|
-
:
|
130
|
-
|
131
|
-
"status": "ok",
|
132
|
-
"message": "password_updated"
|
133
|
-
}
|
134
|
-
EOF
|
138
|
+
:headers => {'Content-Type' => 'application/json'},
|
139
|
+
:body => '{ "status": "ok", "message": "password_updated" }'
|
135
140
|
)
|
136
141
|
|
137
|
-
|
138
142
|
subject
|
139
143
|
|
140
144
|
expect(req).to have_been_requested
|
@@ -147,21 +151,22 @@ EOF
|
|
147
151
|
|
148
152
|
subject { uaa.password_score(password) }
|
149
153
|
|
154
|
+
include_examples "UAA wrapper"
|
155
|
+
|
150
156
|
before do
|
151
|
-
|
152
|
-
:body =>
|
153
|
-
:headers => {
|
157
|
+
stub_request(:post, "#{target}/password/score").with(
|
158
|
+
:body => 'password=password',
|
159
|
+
:headers => {
|
160
|
+
'Accept' => 'application/json;charset=utf-8',
|
161
|
+
'Content-Type' => 'application/x-www-form-urlencoded;charset=utf-8',
|
162
|
+
}
|
154
163
|
).to_return(
|
155
164
|
:status => 200,
|
165
|
+
:headers => {'Content-Type' => 'application/json'},
|
156
166
|
:body => response
|
157
167
|
)
|
158
168
|
end
|
159
169
|
|
160
|
-
it 'sends a password change request' do
|
161
|
-
subject
|
162
|
-
expect(@request).to have_been_requested
|
163
|
-
end
|
164
|
-
|
165
170
|
context 'when the score is 0 and the required is 0' do
|
166
171
|
let(:response) { MultiJson.encode "score" => 0, "requiredScore" => 0 }
|
167
172
|
it { should == :good }
|
@@ -198,69 +203,91 @@ EOF
|
|
198
203
|
end
|
199
204
|
end
|
200
205
|
|
201
|
-
describe
|
202
|
-
|
206
|
+
describe "#add_user" do
|
207
|
+
let(:email) { 'test@test.com' }
|
208
|
+
let(:password) { 'secret' }
|
209
|
+
|
210
|
+
subject { uaa.add_user(email, password) }
|
211
|
+
|
212
|
+
context 'with valid data' do
|
213
|
+
it "should add a user" do
|
214
|
+
req =
|
215
|
+
stub_request(:post, "https://uaa.example.com/Users").with(
|
216
|
+
:body =>
|
217
|
+
{ :userName => email,
|
218
|
+
:emails => [{ :value => email }],
|
219
|
+
:password => password,
|
220
|
+
:name => { :givenName => email, :familyName => email }
|
221
|
+
}
|
222
|
+
).to_return(
|
223
|
+
:status => 200,
|
224
|
+
:body => '{ "id" : "id" }',
|
225
|
+
:headers => { "Content-Type" => 'application/json' }
|
226
|
+
)
|
227
|
+
|
228
|
+
expect(subject).to eq({"id" => "id"})
|
229
|
+
expect(req).to have_been_requested
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
203
233
|
|
204
|
-
|
205
|
-
|
234
|
+
describe "#wrap_uaa_errors" do
|
235
|
+
subject { uaa.send(:wrap_uaa_errors) { raise error } }
|
206
236
|
|
207
|
-
|
208
|
-
|
209
|
-
}
|
237
|
+
context "when the block raises CF::UAA::BadResponse" do
|
238
|
+
let(:error) { CF::UAA::BadResponse }
|
210
239
|
|
211
|
-
it
|
212
|
-
expect {subject}.to
|
240
|
+
it "raises CFoundry::BadResponse" do
|
241
|
+
expect { subject }.to raise_exception(CFoundry::BadResponse)
|
213
242
|
end
|
214
243
|
end
|
215
244
|
|
245
|
+
context "when the block raises CF::UAA::NotFound" do
|
246
|
+
let(:error) { CF::UAA::NotFound }
|
216
247
|
|
217
|
-
|
218
|
-
|
219
|
-
stub_request(:get, 'https://uaa.example.com/foo').to_return :status => error_code,
|
220
|
-
:body => "{\"error_description\":\"Something detailed\"}"
|
221
|
-
}
|
222
|
-
|
223
|
-
it 'raises the correct error' do
|
224
|
-
expect {subject}.to raise_error CFoundry::Denied, "#{error_code}: Something detailed"
|
248
|
+
it "raises CFoundry::NotFound" do
|
249
|
+
expect { subject }.to raise_exception(CFoundry::NotFound)
|
225
250
|
end
|
226
251
|
end
|
227
252
|
|
253
|
+
context "when the block raises CF::UAA::InvalidToken" do
|
254
|
+
let(:error) { CF::UAA::InvalidToken }
|
228
255
|
|
229
|
-
|
230
|
-
|
231
|
-
|
256
|
+
it "raises CFoundry::Denied" do
|
257
|
+
expect { subject }.to raise_exception(CFoundry::Denied)
|
258
|
+
end
|
232
259
|
end
|
233
260
|
|
234
|
-
context
|
235
|
-
let(:
|
236
|
-
include_examples "Denied tests"
|
237
|
-
end
|
261
|
+
context "when the block raises CF::UAA::TargetError" do
|
262
|
+
let(:error) { CF::UAA::TargetError.new({ "error" => "foo", "error_description" => "bar" }) }
|
238
263
|
|
239
|
-
|
240
|
-
|
241
|
-
|
264
|
+
it "raises CFoundry::UAAError" do
|
265
|
+
expect { subject }.to raise_exception(CFoundry::UAAError, "foo: bar")
|
266
|
+
end
|
242
267
|
end
|
268
|
+
end
|
243
269
|
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
270
|
+
describe "#token_issuer" do
|
271
|
+
it "has logging level 0 if #trace is true" do
|
272
|
+
uaa.trace = true
|
273
|
+
expect(uaa.send(:token_issuer).logger.level).to eq 0
|
274
|
+
end
|
249
275
|
|
250
|
-
|
251
|
-
|
252
|
-
|
276
|
+
it "has logging level 1 if #trace is false" do
|
277
|
+
uaa.trace = false
|
278
|
+
expect(uaa.send(:token_issuer).logger.level).to eq 1
|
253
279
|
end
|
280
|
+
end
|
254
281
|
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
282
|
+
describe "#scim" do
|
283
|
+
it "has logging level 0 if #trace is true" do
|
284
|
+
uaa.trace = true
|
285
|
+
expect(uaa.send(:scim).logger.level).to eq 0
|
286
|
+
end
|
260
287
|
|
261
|
-
|
262
|
-
|
263
|
-
|
288
|
+
it "has logging level 1 if #trace is false" do
|
289
|
+
uaa.trace = false
|
290
|
+
expect(uaa.send(:scim).logger.level).to eq 1
|
264
291
|
end
|
265
292
|
end
|
266
293
|
end
|