kinde_sdk 1.6.3 → 1.6.4
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 +4 -4
- data/app/controllers/kinde_sdk/auth_controller.rb +131 -67
- data/app/helpers/auth_helper.rb +88 -0
- data/config/routes.rb +3 -1
- data/lib/kinde_sdk/client.rb +34 -19
- data/lib/kinde_sdk/current.rb +16 -0
- data/lib/kinde_sdk/engine.rb +6 -0
- data/lib/kinde_sdk/middleware.rb +16 -0
- data/lib/kinde_sdk/token_manager.rb +85 -0
- data/lib/kinde_sdk/token_store.rb +29 -0
- data/lib/kinde_sdk/version.rb +1 -1
- data/lib/kinde_sdk.rb +15 -10
- data/spec/examples.txt +24 -0
- data/spec/kinde_sdk_spec.rb +211 -125
- data/spec/spec_helper.rb +4 -4
- metadata +92 -88
data/spec/examples.txt
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
example_id | status | run_time |
|
2
|
+
------------------------------------- | ------ | --------------- |
|
3
|
+
./spec/kinde_sdk_spec.rb[1:1:1] | passed | 0.08981 seconds |
|
4
|
+
./spec/kinde_sdk_spec.rb[1:1:2] | passed | 0.16283 seconds |
|
5
|
+
./spec/kinde_sdk_spec.rb[1:2:1] | passed | 0.04053 seconds |
|
6
|
+
./spec/kinde_sdk_spec.rb[1:2:2:1] | passed | 0.00692 seconds |
|
7
|
+
./spec/kinde_sdk_spec.rb[1:3:1] | passed | 0.20177 seconds |
|
8
|
+
./spec/kinde_sdk_spec.rb[1:4:1] | passed | 0.10943 seconds |
|
9
|
+
./spec/kinde_sdk_spec.rb[1:4:2:1] | passed | 0.0565 seconds |
|
10
|
+
./spec/kinde_sdk_spec.rb[1:5:1] | passed | 0.03191 seconds |
|
11
|
+
./spec/kinde_sdk_spec.rb[1:5:2:1] | passed | 0.18111 seconds |
|
12
|
+
./spec/kinde_sdk_spec.rb[1:6:1:1] | passed | 0.04266 seconds |
|
13
|
+
./spec/kinde_sdk_spec.rb[1:6:1:2] | passed | 0.1197 seconds |
|
14
|
+
./spec/kinde_sdk_spec.rb[1:6:1:3] | passed | 0.08009 seconds |
|
15
|
+
./spec/kinde_sdk_spec.rb[1:6:2:1] | passed | 0.02948 seconds |
|
16
|
+
./spec/kinde_sdk_spec.rb[1:6:2:2:1:1] | passed | 0.04764 seconds |
|
17
|
+
./spec/kinde_sdk_spec.rb[1:6:2:2:2:1] | passed | 0.03494 seconds |
|
18
|
+
./spec/kinde_sdk_spec.rb[1:6:3:1] | passed | 0.1131 seconds |
|
19
|
+
./spec/kinde_sdk_spec.rb[1:6:3:2] | passed | 0.14076 seconds |
|
20
|
+
./spec/kinde_sdk_spec.rb[1:6:3:3] | passed | 0.03831 seconds |
|
21
|
+
./spec/kinde_sdk_spec.rb[1:6:3:4] | passed | 0.05261 seconds |
|
22
|
+
./spec/kinde_sdk_spec.rb[1:6:3:5] | passed | 0.04123 seconds |
|
23
|
+
./spec/kinde_sdk_spec.rb[1:6:3:6] | passed | 0.06887 seconds |
|
24
|
+
./spec/kinde_sdk_spec.rb[1:6:4:1:1] | passed | 0.07917 seconds |
|
data/spec/kinde_sdk_spec.rb
CHANGED
@@ -2,21 +2,29 @@ require 'spec_helper'
|
|
2
2
|
require 'jwt'
|
3
3
|
require 'openssl'
|
4
4
|
require 'webmock/rspec'
|
5
|
+
require 'rails'
|
5
6
|
|
7
|
+
# Set up a minimal Rails application for testing
|
8
|
+
class TestApplication < Rails::Application
|
9
|
+
config.eager_load = false
|
10
|
+
config.active_support.deprecation = :stderr
|
11
|
+
end
|
6
12
|
|
7
|
-
describe KindeSdk do
|
13
|
+
RSpec.describe KindeSdk do
|
8
14
|
let(:domain) { "http://example.com" }
|
9
15
|
let(:client_id) { "client_id" }
|
10
16
|
let(:client_secret) { "client_secret" }
|
11
17
|
let(:callback_url) { "http://localhost:3000/callback" }
|
12
18
|
let(:logout_url) { "http://localhost/logout-callback" }
|
13
19
|
let(:auto_refresh_tokens) { true }
|
20
|
+
let(:mock_session) { {} }
|
14
21
|
|
15
22
|
let(:optional_parameters) { { kid: 'my-kid', use: 'sig', alg: 'RS512' } }
|
16
23
|
let(:rsa_key) { OpenSSL::PKey::RSA.new(2048) }
|
17
24
|
let(:jwk) { JWT::JWK.new(rsa_key, optional_parameters) }
|
18
25
|
let(:payload) { { data: 'data' } }
|
19
26
|
let(:token) { JWT.encode(payload, jwk.signing_key, jwk[:alg], kid: jwk[:kid]) }
|
27
|
+
let(:refresh_token) { JWT.encode(payload, jwk.signing_key, jwk[:alg], kid: jwk[:kid]) }
|
20
28
|
let(:jwks_hash) { JWT::JWK::Set.new(jwk).export }
|
21
29
|
|
22
30
|
before do
|
@@ -28,6 +36,44 @@ describe KindeSdk do
|
|
28
36
|
c.logout_url = logout_url
|
29
37
|
c.auto_refresh_tokens = auto_refresh_tokens
|
30
38
|
end
|
39
|
+
|
40
|
+
# Stub JWKS endpoint
|
41
|
+
stub_request(:get, "#{domain}/.well-known/jwks.json")
|
42
|
+
.with(
|
43
|
+
headers: {
|
44
|
+
'Accept' => '*/*',
|
45
|
+
'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
|
46
|
+
'User-Agent' => 'Ruby'
|
47
|
+
}
|
48
|
+
)
|
49
|
+
.to_return(
|
50
|
+
status: 200,
|
51
|
+
body: jwks_hash.to_json,
|
52
|
+
headers: { "content-type" => "application/json;charset=UTF-8" }
|
53
|
+
)
|
54
|
+
|
55
|
+
# Stub token refresh endpoint - match URL-encoded request
|
56
|
+
stub_request(:post, "#{domain}/oauth2/token")
|
57
|
+
.with(
|
58
|
+
body: /^grant_type=refresh_token&refresh_token=/,
|
59
|
+
headers: {
|
60
|
+
'Accept' => '*/*',
|
61
|
+
'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
|
62
|
+
'Authorization' => 'Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=',
|
63
|
+
'Content-Type' => 'application/x-www-form-urlencoded',
|
64
|
+
'User-Agent' => "Kinde-SDK: Ruby/#{KindeSdk::VERSION}"
|
65
|
+
}
|
66
|
+
)
|
67
|
+
.to_return(
|
68
|
+
status: 200,
|
69
|
+
body: {
|
70
|
+
"access_token" => token,
|
71
|
+
"refresh_token" => refresh_token,
|
72
|
+
"expires_in" => 3600,
|
73
|
+
"token_type" => "bearer"
|
74
|
+
}.to_json,
|
75
|
+
headers: { "content-type" => "application/json;charset=UTF-8" }
|
76
|
+
)
|
31
77
|
end
|
32
78
|
|
33
79
|
describe "#auth_url" do
|
@@ -60,84 +106,86 @@ describe KindeSdk do
|
|
60
106
|
|
61
107
|
describe "#api_client" do
|
62
108
|
it "returns initialized api_client instance of KindeApi" do
|
63
|
-
|
64
|
-
|
109
|
+
api_client = described_class.api_client("token")
|
110
|
+
expect(api_client).to be_a(KindeApi::ApiClient)
|
111
|
+
expect(api_client.config.access_token).to eq("token")
|
65
112
|
end
|
66
113
|
end
|
67
114
|
|
68
115
|
describe "#fetch_tokens" do
|
69
|
-
let(:
|
116
|
+
let(:mock_token) do
|
117
|
+
double('OAuth2::AccessToken',
|
118
|
+
token: token,
|
119
|
+
params: {
|
120
|
+
'id_token' => 'test',
|
121
|
+
'refresh_token' => refresh_token,
|
122
|
+
'scope' => '',
|
123
|
+
'token_type' => 'bearer'
|
124
|
+
},
|
125
|
+
expires_at: Time.now.to_i + 86399,
|
126
|
+
refresh_token: refresh_token
|
127
|
+
)
|
128
|
+
end
|
129
|
+
let(:mock_oauth_client) { double('OAuth2::Client') }
|
130
|
+
let(:mock_auth_code) { double('OAuth2::Strategy::AuthCode') }
|
131
|
+
|
70
132
|
before do
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
"code" => code,
|
75
|
-
"grant_type" => "authorization_code",
|
76
|
-
"redirect_uri" => callback_url
|
77
|
-
},
|
78
|
-
headers: {
|
79
|
-
'Accept' => '*/*',
|
80
|
-
'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
|
81
|
-
'Authorization' => 'Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=',
|
82
|
-
'Content-Type' => 'application/x-www-form-urlencoded',
|
83
|
-
'User-Agent' => "Kinde-SDK: Ruby/#{KindeSdk::VERSION}"
|
84
|
-
}
|
85
|
-
)
|
86
|
-
.to_return(
|
87
|
-
status: 200,
|
88
|
-
body: { "access_token" => "eyJ", "id_token" => "test", "refresh_token" => "test", "expires_in" => 86399, "scope" => "", "token_type" => "bearer" }.to_json,
|
89
|
-
headers: { "content-type" => "application/json;charset=UTF-8" }
|
90
|
-
)
|
91
|
-
stub_request(:get, "#{domain}/.well-known/jwks.json")
|
92
|
-
.with(
|
93
|
-
headers: {
|
94
|
-
'Accept'=>'*/*',
|
95
|
-
'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
|
96
|
-
'User-Agent'=>'Ruby'
|
97
|
-
})
|
98
|
-
.to_return(
|
99
|
-
status: 200,
|
100
|
-
body: jwks_hash.to_json,
|
101
|
-
headers: { "content-type" => "application/json;charset=UTF-8" }
|
102
|
-
)
|
133
|
+
allow(OAuth2::Client).to receive(:new).and_return(mock_oauth_client)
|
134
|
+
allow(mock_oauth_client).to receive(:auth_code).and_return(mock_auth_code)
|
135
|
+
allow(mock_auth_code).to receive(:get_token).and_return(mock_token)
|
103
136
|
end
|
104
137
|
|
105
138
|
it "calls /token url with proper body and headers" do
|
106
|
-
|
139
|
+
result = described_class.fetch_tokens("code")
|
140
|
+
expect(result[:access_token]).to eq(token)
|
141
|
+
expect(result[:refresh_token]).to eq(refresh_token)
|
107
142
|
end
|
108
143
|
|
109
144
|
context "with redefined callback_url" do
|
110
|
-
let(:
|
145
|
+
let(:custom_callback_url) { "http://localhost:5000/callback" }
|
111
146
|
|
112
147
|
it "calls /token url with proper body and headers" do
|
113
|
-
|
148
|
+
result = described_class.fetch_tokens("code", redirect_uri: custom_callback_url)
|
149
|
+
expect(result[:access_token]).to eq(token)
|
150
|
+
expect(result[:refresh_token]).to eq(refresh_token)
|
114
151
|
end
|
115
152
|
end
|
116
153
|
end
|
117
154
|
|
118
155
|
describe "#client_credentials_access" do
|
119
|
-
let(:
|
120
|
-
|
121
|
-
|
156
|
+
let(:mock_response) do
|
157
|
+
double('Faraday::Response',
|
158
|
+
body: {
|
159
|
+
"access_token" => token,
|
160
|
+
"expires_in" => 3600,
|
161
|
+
"token_type" => "bearer"
|
162
|
+
}
|
163
|
+
)
|
122
164
|
end
|
123
|
-
let(:
|
124
|
-
|
165
|
+
let(:mock_connection) { double('Faraday::Connection') }
|
166
|
+
|
167
|
+
before do
|
168
|
+
allow(Faraday).to receive(:new).and_return(mock_connection)
|
169
|
+
allow(mock_connection).to receive(:post).and_return(mock_response)
|
125
170
|
end
|
126
|
-
before { stub_request(:post, "#{domain}/oauth2/token").with(body: request_body).to_return(body: response_body) }
|
127
171
|
|
128
172
|
it "calls oauth2/token url with configured credentials" do
|
129
|
-
|
173
|
+
result = described_class.client_credentials_access
|
174
|
+
expect(result["access_token"]).to eq(token)
|
130
175
|
end
|
131
176
|
|
132
177
|
context "with params override" do
|
133
|
-
let(:
|
134
|
-
let(:
|
135
|
-
let(:
|
178
|
+
let(:custom_client_id) { "custom_client_id" }
|
179
|
+
let(:custom_client_secret) { "custom_client_secret" }
|
180
|
+
let(:custom_audience) { "custom_audience" }
|
136
181
|
|
137
182
|
it "calls oauth2/token url with passed credentials" do
|
138
|
-
|
139
|
-
|
140
|
-
|
183
|
+
result = described_class.client_credentials_access(
|
184
|
+
client_id: custom_client_id,
|
185
|
+
client_secret: custom_client_secret,
|
186
|
+
audience: custom_audience
|
187
|
+
)
|
188
|
+
expect(result["access_token"]).to eq(token)
|
141
189
|
end
|
142
190
|
end
|
143
191
|
end
|
@@ -160,108 +208,146 @@ describe KindeSdk do
|
|
160
208
|
"scp" => ["openid", "offline"],
|
161
209
|
"sub" => "kp:b17adf719f7d4b87b611d1a88a09fd15" }
|
162
210
|
end
|
163
|
-
before do
|
164
|
-
stub_request(:get, "#{domain}/.well-known/jwks.json")
|
165
|
-
.with(
|
166
|
-
headers: {
|
167
|
-
'Accept'=>'*/*',
|
168
|
-
'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
|
169
|
-
'User-Agent'=>'Ruby'
|
170
|
-
})
|
171
|
-
.to_return(
|
172
|
-
status: 200,
|
173
|
-
body: jwks_hash.to_json,
|
174
|
-
headers: { "content-type" => "application/json;charset=UTF-8" }
|
175
|
-
)
|
176
|
-
end
|
177
211
|
let(:token) { JWT.encode(hash_to_encode, jwk.signing_key, jwk[:alg], kid: jwk[:kid]) }
|
178
212
|
let(:expires_at) { Time.now.to_i + 10000000 }
|
179
|
-
let(:
|
213
|
+
let(:tokens_hash) { { access_token: token, expires_at: expires_at, refresh_token: refresh_token } }
|
214
|
+
let(:client) { described_class.client(tokens_hash, auto_refresh_tokens) }
|
180
215
|
|
181
|
-
context "with
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
expect(client.get_flag("qqq")).to eq({ code: "qqq", is_default: false, type: "string", value: "aa" })
|
216
|
+
context "with session integration" do
|
217
|
+
before do
|
218
|
+
KindeSdk::Current.set_session(mock_session)
|
219
|
+
end
|
186
220
|
|
187
|
-
|
188
|
-
|
221
|
+
after do
|
222
|
+
KindeSdk::Current.clear_session
|
189
223
|
end
|
190
224
|
|
191
|
-
it "
|
192
|
-
expect(
|
193
|
-
|
225
|
+
it "initializes with session" do
|
226
|
+
expect(KindeSdk::Current.session).to eq(mock_session)
|
227
|
+
end
|
194
228
|
|
195
|
-
|
196
|
-
|
197
|
-
|
229
|
+
it "updates session when refreshing tokens" do
|
230
|
+
new_token = "new_token"
|
231
|
+
new_refresh_token = "new_refresh_token"
|
232
|
+
new_expires_at = Time.now.to_i + 7200
|
233
|
+
|
234
|
+
stub_request(:post, "#{domain}/oauth2/token")
|
235
|
+
.with(
|
236
|
+
body: {
|
237
|
+
"grant_type" => "refresh_token",
|
238
|
+
"refresh_token" => refresh_token
|
239
|
+
},
|
240
|
+
headers: {
|
241
|
+
'Accept' => '*/*',
|
242
|
+
'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
|
243
|
+
'Authorization' => 'Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=',
|
244
|
+
'Content-Type' => 'application/x-www-form-urlencoded',
|
245
|
+
'User-Agent' => "Kinde-SDK: Ruby/#{KindeSdk::VERSION}"
|
246
|
+
}
|
247
|
+
)
|
248
|
+
.to_return(
|
249
|
+
status: 200,
|
250
|
+
body: {
|
251
|
+
"access_token" => new_token,
|
252
|
+
"refresh_token" => new_refresh_token,
|
253
|
+
"expires_in" => 7200,
|
254
|
+
"token_type" => "bearer"
|
255
|
+
}.to_json,
|
256
|
+
headers: { "content-type" => "application/json;charset=UTF-8" }
|
257
|
+
)
|
258
|
+
|
259
|
+
allow(KindeSdk).to receive(:refresh_token).and_return(tokens_hash)
|
260
|
+
client.refresh_token
|
261
|
+
|
262
|
+
expect(mock_session[:kinde_token_store]).to be_present
|
263
|
+
expect(mock_session[:kinde_token_store][:access_token]).to eq(token)
|
264
|
+
expect(mock_session[:kinde_token_store][:refresh_token]).to eq(refresh_token)
|
265
|
+
expect(mock_session[:kinde_token_store][:expires_at]).to eq(expires_at)
|
198
266
|
end
|
199
267
|
|
200
|
-
it "
|
201
|
-
|
202
|
-
|
268
|
+
it "creates client without session" do
|
269
|
+
KindeSdk::Current.clear_session
|
270
|
+
client_without_session = described_class.client(tokens_hash)
|
271
|
+
expect(KindeSdk::Current.session).to be_nil
|
272
|
+
end
|
273
|
+
end
|
203
274
|
|
204
|
-
|
205
|
-
|
275
|
+
context "with expiration check" do
|
276
|
+
it "returns true when token is expired" do
|
277
|
+
allow(KindeSdk).to receive(:refresh_token).and_return(tokens_hash)
|
278
|
+
allow(KindeSdk::TokenManager).to receive(:token_expired?).and_return(true)
|
279
|
+
expect(client.token_expired?).to be true
|
280
|
+
end
|
206
281
|
|
207
|
-
|
208
|
-
|
282
|
+
context "when token expired" do
|
283
|
+
before do
|
284
|
+
allow(KindeSdk::TokenManager).to receive(:token_expired?).and_return(true)
|
285
|
+
end
|
286
|
+
|
287
|
+
context "with auto_refresh_tokens enabled" do
|
288
|
+
it "attempts to refresh the token when getting a claim" do
|
289
|
+
allow(KindeSdk).to receive(:refresh_token).and_return(tokens_hash)
|
290
|
+
expect(client).to receive(:refresh_token)
|
291
|
+
client.get_claim("sub")
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
context "with auto_refresh_tokens disabled" do
|
296
|
+
let(:auto_refresh_tokens) { false }
|
297
|
+
|
298
|
+
it "does not attempt to refresh the token" do
|
299
|
+
expect(client).not_to receive(:refresh_token)
|
300
|
+
client.get_claim("sub")
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
context "with feature flags" do
|
307
|
+
it "returns existing flags" do
|
308
|
+
expect(client.get_flag("asd")[:value]).to eq(true)
|
309
|
+
expect(client.get_flag("eeeeee")[:value]).to eq(111)
|
310
|
+
expect(client.get_flag("qqq")[:value]).to eq("aa")
|
209
311
|
end
|
210
312
|
|
211
|
-
it "behaves the same way for boolean flag wrapper getter"
|
313
|
+
it "behaves the same way for boolean flag wrapper getter" do
|
212
314
|
expect { client.get_boolean_flag("eeeeee") }
|
213
315
|
.to raise_error(ArgumentError, "Flag eeeeee value type is different from requested type")
|
214
|
-
expect(client.get_boolean_flag("asd")).to eq(true)
|
215
|
-
expect(client.get_boolean_flag("undefined", false)).to eq(false)
|
216
|
-
|
217
|
-
expect { client.get_boolean_flag("undefined", "true") }
|
218
|
-
.to raise_error(ArgumentError, "Flag undefined value type is different from requested type")
|
219
316
|
end
|
220
317
|
|
221
|
-
it "behaves the same way for integer flag wrapper getter"
|
318
|
+
it "behaves the same way for integer flag wrapper getter" do
|
222
319
|
expect { client.get_integer_flag("asd") }
|
223
320
|
.to raise_error(ArgumentError, "Flag asd value type is different from requested type")
|
224
|
-
expect(client.get_integer_flag("eeeeee")).to eq(111)
|
225
|
-
expect(client.get_integer_flag("undefined", 111)).to eq(111)
|
226
|
-
|
227
|
-
expect { client.get_integer_flag("undefined", "true") }
|
228
|
-
.to raise_error(ArgumentError, "Flag undefined value type is different from requested type")
|
229
321
|
end
|
230
322
|
|
231
|
-
it "behaves the same way for string flag wrapper getter"
|
323
|
+
it "behaves the same way for string flag wrapper getter" do
|
232
324
|
expect { client.get_string_flag("asd") }
|
233
325
|
.to raise_error(ArgumentError, "Flag asd value type is different from requested type")
|
234
|
-
|
235
|
-
expect(client.get_string_flag("undefined", "111")).to eq("111")
|
326
|
+
end
|
236
327
|
|
237
|
-
|
328
|
+
it "raises argument error when no value type match" do
|
329
|
+
expect { client.get_flag("undefined", { default_value: true }, "s") }
|
330
|
+
.to raise_error(ArgumentError, "Flag undefined value type is different from requested type")
|
331
|
+
expect { client.get_flag("undefined", { default_value: true }, "i") }
|
332
|
+
.to raise_error(ArgumentError, "Flag undefined value type is different from requested type")
|
333
|
+
expect { client.get_flag("undefined", { default_value: "true" }, "b") }
|
238
334
|
.to raise_error(ArgumentError, "Flag undefined value type is different from requested type")
|
239
335
|
end
|
240
|
-
end
|
241
|
-
|
242
|
-
it "returns requested claim from bearer", :aggregate_failures do
|
243
|
-
expect(client.get_claim("scp")).to eq({ name: "scp", value: hash_to_encode["scp"] })
|
244
|
-
expect(client.get_claim("scp", :id_token)).to be_nil
|
245
|
-
expect(client.get_claim("aaa")).to be_nil
|
246
|
-
end
|
247
336
|
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
.
|
252
|
-
|
253
|
-
expect(client.get_permission("asd"))
|
254
|
-
.to eq({ org_code: hash_to_encode["org_code"], is_granted: false })
|
255
|
-
expect(client.permission_granted?("asd")).to be(false)
|
337
|
+
it "returns fallbacks if no flag present" do
|
338
|
+
expect(client.get_flag("undefined", { default_value: true })[:value]).to eq(true)
|
339
|
+
expect(client.get_flag("undefined", { default_value: 111 })[:value]).to eq(111)
|
340
|
+
expect(client.get_flag("undefined", { default_value: "aa" })[:value]).to eq("aa")
|
341
|
+
end
|
256
342
|
end
|
257
343
|
|
258
|
-
context "with
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
344
|
+
context "when initializing with expired token" do
|
345
|
+
context "with auto_refresh_tokens enabled" do
|
346
|
+
it "attempts to refresh the token during initialization" do
|
347
|
+
allow(KindeSdk::TokenManager).to receive(:token_expired?).and_return(true)
|
348
|
+
expect_any_instance_of(KindeSdk::Client).to receive(:refresh_token)
|
349
|
+
described_class.client(tokens_hash, true)
|
350
|
+
end
|
265
351
|
end
|
266
352
|
end
|
267
353
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -4,6 +4,10 @@ $LOAD_PATH.unshift File.expand_path('../kinde_api/lib', __dir__) # For kinde_
|
|
4
4
|
require "kinde_sdk"
|
5
5
|
require "webmock/rspec"
|
6
6
|
|
7
|
+
# Configure Faraday for testing
|
8
|
+
require 'faraday'
|
9
|
+
Faraday.default_adapter = :test
|
10
|
+
|
7
11
|
WebMock.disable_net_connect!
|
8
12
|
|
9
13
|
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
@@ -31,9 +35,6 @@ RSpec.configure do |config|
|
|
31
35
|
mocks.verify_partial_doubles = true
|
32
36
|
end
|
33
37
|
|
34
|
-
# The settings below are suggested to provide a good initial experience
|
35
|
-
# with RSpec, but feel free to customize to your heart's content.
|
36
|
-
=begin
|
37
38
|
# These two settings work together to allow you to limit a spec run
|
38
39
|
# to individual examples or groups you care about by tagging them with
|
39
40
|
# `:focus` metadata. When nothing is tagged with `:focus`, all examples
|
@@ -83,5 +84,4 @@ RSpec.configure do |config|
|
|
83
84
|
# test failures related to randomization by passing the same `--seed` value
|
84
85
|
# as the one that triggered the failure.
|
85
86
|
Kernel.srand config.seed
|
86
|
-
=end
|
87
87
|
end
|