cfoundry 0.4.21 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|