yodlicious 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Gemfile +1 -0
- data/README.md +45 -3
- data/lib/yodlicious.rb +1 -1
- data/lib/yodlicious/parameter_translator.rb +1 -1
- data/lib/yodlicious/version.rb +1 -1
- data/lib/yodlicious/{yodlicious.rb → yodlee_api.rb} +90 -18
- data/spec/integration_spec.rb +437 -11
- data/spec/spec_helper.rb +2 -1
- data/spec/unit/parameter_translator_spec.rb +2 -2
- data/spec/unit/{yodlicious_spec.rb → yodlee_api_spec.rb} +104 -1
- data/yodlicious.png +0 -0
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bc007491e579889f0318b9f292d786eced0cf8bb
|
4
|
+
data.tar.gz: 8349f9cace5145555c1c12a61eca28fbc708e2c0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6baf54a65da2268c40a0d3543f2c2fb5ffcca19753a7e58e1ee328a93999e563e0a465b770b221b6f333148e52411fdf2efba2aaade036601d153785262b1966
|
7
|
+
data.tar.gz: 6c5dcc17e8df67652690bcc51d30c2870edc0310846e773fba2adf8bef8af998ce7665ccf08ba18eda0be690a2b0732a536077e82172364aae9e11f40299dc57
|
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
-
|
1
|
+
![image of yodlicious](https://github.com/liftforward/yodlicious/blob/master/yodlicious.png)
|
2
2
|
|
3
|
-
|
3
|
+
# Yodlicious 0.0.1 [ ![Codeship Status for liftforward/yodlicious](https://codeship.com/projects/71603f00-9393-0132-dcd0-1a9a253548c0/status?branch=master)](https://codeship.com/projects/62288)
|
4
|
+
|
5
|
+
Yodlicisous is a ruby gem wrapping the Yodlee REST(ish) API. We had to build this for our integration with Yodlee which was somewhat more painful than it should have been so we figured we share to be a good neighbor.
|
4
6
|
|
5
7
|
## Installation
|
6
8
|
|
@@ -37,6 +39,7 @@ yodlee_api = Yodlicious::YodleeApi.new(config)
|
|
37
39
|
|
38
40
|
```
|
39
41
|
When in a Rails app it can be more convenient to use a global default configuration. To use global defaults:
|
42
|
+
|
40
43
|
```ruby
|
41
44
|
#/<myproject>/config/initializers/yodlicious.rb
|
42
45
|
require 'yodlicious'
|
@@ -50,12 +53,14 @@ Yodlicious::Config.cobranded_password = ENV['YODLEE_COBRANDED_PASSWORD']
|
|
50
53
|
Yodlicious::Config.logger = Rails.logger
|
51
54
|
```
|
52
55
|
and wherever you want to use the api simply create a new one and it will pickup the global defaults.
|
56
|
+
|
53
57
|
```ruby
|
54
58
|
yodlee_api = Yodlicious::YodleeApi.new
|
55
59
|
```
|
56
60
|
If for any reason you need to, you can pass a hash into the constructor and it will use any provided hash values over the defaults. Note this is done on each value not the entire hash.
|
57
61
|
|
58
62
|
You can also update an existing instances of the YodleeApi's configuration with the configure method. For example:
|
63
|
+
|
59
64
|
```ruby
|
60
65
|
|
61
66
|
yodlee_api = Yodlicious::YodleeApi.new { base_url: 'http://yodlee.com/blablabla' }
|
@@ -65,6 +70,7 @@ yodlee_api.configure { base_url: 'https://secure.yodlee.com/blablabla }
|
|
65
70
|
puts yodlee_api.base_url
|
66
71
|
```
|
67
72
|
will output
|
73
|
+
|
68
74
|
```
|
69
75
|
https://secure.yodlee.com/blablabla
|
70
76
|
```
|
@@ -86,7 +92,7 @@ yodlee_api = Yodlicious::YodleeApi.new(config)
|
|
86
92
|
|
87
93
|
## Working with the API
|
88
94
|
|
89
|
-
The Yodlee Api responses are somewhat
|
95
|
+
The Yodlee Api responses are somewhat varied (especially the errors) and as such we build Yodlicious as a pretty thin layer around their request/response model. We didn't attempt to map all their JSON responses into models or anything fancy like that. Instead we simply created a method for each API endpoint which takes the required parameters and return a response object. That said, Response object does provide some conveniences to make up for the inconsistent delivery of errors from Yodlee's APIs.
|
90
96
|
|
91
97
|
### Starting your cobranded session
|
92
98
|
|
@@ -99,16 +105,51 @@ pry(main)> response.success?
|
|
99
105
|
=> true
|
100
106
|
```
|
101
107
|
As you probably suspect the call to cobranded_login wraps the ```/authenticate/coblogin``` endpoint call. If this is a success the YodleeApi instance will cache the cobranded session id yodlee returned and use it on all subsequent api calls. You can also access this value if desired with YodleeApi#cobranded_session_token.
|
108
|
+
|
102
109
|
```
|
103
110
|
pry(main)> yodlee_api.cobranded_session_token
|
104
111
|
=> "12162013_1:a0b1ac3e32a2e656f8f5bd21de23ae1721ffd9dab8bee9f29811f5959bbf102f16c98354eba252bb030dc96e267bd2489a40562f18e09ee8ba9038d19280cc43"
|
105
112
|
```
|
106
113
|
At this point something has probably gone wrong for you and you want to see the response json from ```/authenticate/coblogin```. To do this simply use ```response#body```.
|
114
|
+
|
107
115
|
```
|
108
116
|
pry(main)> response.body
|
109
117
|
=> {"Error"=>[{"errorDetail"=>"Invalid Cobrand Credentials"}]}
|
110
118
|
```
|
111
119
|
|
120
|
+
### Starting a user session
|
121
|
+
|
122
|
+
Once the cobranded session is active a number of API endpoints will work however most of the interesting ones require you to register or login under a user account. It is within these accounts that you can add the user's bank accounts and whatnot to aggregate their financial data. There are 3 methods offered to allow you to #register_user, #login_user, or do either #login_or_register_user. After executing any of these the user session will be started and the user's session token will be cached in the YodleeApi instance and used on subsequent calls to api endpoints. As with all api calls if the call was not successful you'll need to look at the body of the response to determine what went wrong.
|
123
|
+
|
124
|
+
### Registering a new user
|
125
|
+
|
126
|
+
```
|
127
|
+
pry(main)> response = yodlee_api.register_user 'my-username', 'my-password123', 'my-email@my-domain.com'
|
128
|
+
pry(main)> yodlee_api.user_session_token
|
129
|
+
=> "12162013_1:69761d51a4010e6382ccb49b854513dbccad0f835a873d37884b68826acefaa5b8d41b634f4cc83d97d86e7df861f70860a4e4d8a3f08d5b5440eae504af5f19"
|
130
|
+
```
|
131
|
+
|
132
|
+
### Login existing user
|
133
|
+
|
134
|
+
```
|
135
|
+
pry(main)> response = yodlee_api.user_login 'my-username', 'my-password123'
|
136
|
+
pry(main)> yodlee_api.user_session_token
|
137
|
+
=> "12162013_1:69761d51a4010e6382ccb49b854513dbccad0f835a873d37884b68826acefaa5b8d41b634f4cc83d97d86e7df861f70860a4e4d8a3f08d5b5440eae504af5f19"
|
138
|
+
```
|
139
|
+
|
140
|
+
### Convenience for doing both
|
141
|
+
|
142
|
+
In case you have a situation where you don't know if the user is already registered there is #login_or_register_user
|
143
|
+
|
144
|
+
```
|
145
|
+
pry(main)> response = yodlee_api.login_or_register_user 'my-username', 'my-password123', 'my-email@my-domain.com'
|
146
|
+
pry(main)> yodlee_api.user_session_token
|
147
|
+
=> "12162013_1:69761d51a4010e6382ccb49b854513dbccad0f835a873d37884b68826acefaa5b8d41b634f4cc83d97d86e7df861f70860a4e4d8a3f08d5b5440eae504af5f19"
|
148
|
+
```
|
149
|
+
### other API methods
|
150
|
+
|
151
|
+
TODO
|
152
|
+
|
112
153
|
## Contributing
|
113
154
|
|
114
155
|
1. Fork it ( https://github.com/liftforward/yodlicious/fork )
|
@@ -120,6 +161,7 @@ pry(main)> response.body
|
|
120
161
|
### Running the integration suite
|
121
162
|
|
122
163
|
To run the Yodlicious integration tests you'll need an approved yodlee account. This is more than the one offered here [https://devnow.yodlee.com/user/register]. (Some of the integration suite will work against the devnow APIs but not all. On my todo list is to separate them out to make testing easier.) The integration suite expects these values to be set in the following environment variables:
|
164
|
+
|
123
165
|
```
|
124
166
|
YODLEE_BASE_URL="https://consolidatedsdk.yodlee.com/yodsoap/srest/my-cobranded-path/v1.0"
|
125
167
|
YODLEE_COBRANDED_USERNAME="my-cobranded-user"
|
data/lib/yodlicious.rb
CHANGED
@@ -8,7 +8,7 @@ require File.dirname(__FILE__) + "/yodlicious/version"
|
|
8
8
|
require File.dirname(__FILE__) + "/yodlicious/config"
|
9
9
|
require File.dirname(__FILE__) + "/yodlicious/parameter_translator"
|
10
10
|
require File.dirname(__FILE__) + "/yodlicious/response"
|
11
|
-
require File.dirname(__FILE__) + "/yodlicious/
|
11
|
+
require File.dirname(__FILE__) + "/yodlicious/yodlee_api"
|
12
12
|
|
13
13
|
class Faraday::Adapter::NetHttp
|
14
14
|
def net_http_connection(env)
|
@@ -17,7 +17,7 @@ module Yodlicious
|
|
17
17
|
params["credentialFields[#{i}].valueIdentifier"] = field['valueIdentifier']
|
18
18
|
params["credentialFields[#{i}].valueMask"] = field['valueMask']
|
19
19
|
params["credentialFields[#{i}].isEditable"] = field['isEditable']
|
20
|
-
params["credentialFields[#{i}].value"] = field['
|
20
|
+
params["credentialFields[#{i}].value"] = field['fieldValue']
|
21
21
|
|
22
22
|
i += 1
|
23
23
|
}
|
data/lib/yodlicious/version.rb
CHANGED
@@ -121,7 +121,12 @@ module Yodlicious
|
|
121
121
|
end
|
122
122
|
|
123
123
|
def unregister_user
|
124
|
-
user_session_execute_api '/jsonsdk/UserRegistration/unregister'
|
124
|
+
response = user_session_execute_api '/jsonsdk/UserRegistration/unregister'
|
125
|
+
if response.success?
|
126
|
+
@user_auth = nil
|
127
|
+
end
|
128
|
+
|
129
|
+
response
|
125
130
|
end
|
126
131
|
|
127
132
|
def site_search search_string
|
@@ -141,34 +146,101 @@ module Yodlicious
|
|
141
146
|
end
|
142
147
|
|
143
148
|
|
144
|
-
def add_site_account_and_wait site_id, site_login_form, refresh_interval = 0.5,
|
145
|
-
|
149
|
+
def add_site_account_and_wait site_id, site_login_form, refresh_interval = 0.5, max_trys = 5
|
150
|
+
add_site_account_response = add_site_account(site_id, site_login_form)
|
146
151
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
response.body['siteRefreshInfo']['siteRefreshMode']['refreshMode'] == 'NORMAL'
|
152
|
-
|
153
|
-
site_account_id = response.body['siteAccountId']
|
154
|
-
trys = 1
|
152
|
+
if add_site_account_response.success?
|
153
|
+
if normal_site_refresh_in_progress?(add_site_account_response.body['siteRefreshInfo'])
|
154
|
+
site_account_id = add_site_account_response.body['siteAccountId']
|
155
|
+
try = 1
|
155
156
|
begin
|
156
|
-
|
157
|
-
|
157
|
+
debug_log "try #{try} to get refresh_info for #{site_id}"
|
158
|
+
try += 1
|
158
159
|
sleep(refresh_interval)
|
159
160
|
refresh_info_response = get_site_refresh_info site_account_id
|
160
|
-
|
161
|
-
end
|
161
|
+
add_site_account_response.body['siteRefreshInfo'] = refresh_info_response.body unless refresh_info_response.fail?
|
162
|
+
end while should_retry_get_site_refresh_info? refresh_info_response, try, max_trys
|
162
163
|
end
|
163
164
|
|
164
|
-
|
165
|
+
add_site_account_response
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
def should_retry_get_site_refresh_info? response, try, max_trys
|
170
|
+
return response.success? && try < max_trys && (response.body['code'] == 801 || (response.body['code'] == 0 &&
|
171
|
+
response.body['siteRefreshStatus']['siteRefreshStatus'] != 'REFRESH_COMPLETED' &&
|
172
|
+
response.body['siteRefreshStatus']['siteRefreshStatus'] != 'REFRESH_TIMED_OUT' &&
|
173
|
+
response.body['siteRefreshStatus']['siteRefreshStatus'] != 'LOGIN_SUCCESS' ))
|
174
|
+
end
|
175
|
+
|
176
|
+
def normal_site_refresh_in_progress? site_refresh_info
|
177
|
+
return site_refresh_info['siteRefreshMode']['refreshMode'] == 'NORMAL' &&
|
178
|
+
['REFRESH_TRIGGERED','PARTIAL_COMPLETE'].include?(site_refresh_info['siteRefreshStatus']['siteRefreshStatus'])
|
179
|
+
end
|
180
|
+
|
181
|
+
def get_mfa_response_for_site site_account_id
|
182
|
+
user_session_execute_api '/jsonsdk/Refresh/getMFAResponseForSite', { memSiteAccId: site_account_id }
|
183
|
+
end
|
184
|
+
|
185
|
+
def get_mfa_response_for_site_and_wait site_account_id, refresh_interval=0.5, max_trys=5
|
186
|
+
response = get_mfa_response_for_site site_account_id
|
187
|
+
|
188
|
+
try = 1
|
189
|
+
while should_retry_get_mfa_response? response, try, max_trys
|
190
|
+
debug_log "try #{try} to get mfa message for #{site_account_id}"
|
191
|
+
try += 1
|
192
|
+
sleep(refresh_interval)
|
193
|
+
response = get_mfa_response_for_site site_account_id
|
165
194
|
end
|
195
|
+
|
196
|
+
response
|
197
|
+
end
|
198
|
+
|
199
|
+
def should_retry_get_mfa_response? response, try, max_trys
|
200
|
+
return response.success? && response.body['errorCode'].nil? && response.body['isMessageAvailable'] != true && try < max_trys
|
201
|
+
end
|
202
|
+
|
203
|
+
def put_mfa_request_for_site site_account_id, mfa_type, field_info
|
204
|
+
params = {
|
205
|
+
'memSiteAccId' => site_account_id,
|
206
|
+
'userResponse.objectInstanceType' => "com.yodlee.core.mfarefresh.#{mfa_type}"
|
207
|
+
}
|
208
|
+
|
209
|
+
case mfa_type.to_sym
|
210
|
+
when :MFATokenResponse
|
211
|
+
params['userResponse.token']=field_info['fieldValue']
|
212
|
+
when :MFAImageResponse
|
213
|
+
params['userResponse.imageString']=field_info['fieldValue']
|
214
|
+
when :MFAQuesAnsResponse
|
215
|
+
questionsArray = field_info['questionAndAnswerValues']
|
216
|
+
i = 0
|
217
|
+
while i < questionsArray.length do
|
218
|
+
puts "questionsArray= #{questionsArray[i].class} #{i}"
|
219
|
+
params["userResponse.quesAnsDetailArray[#{i}].answer"]=questionsArray[i]['fieldValue']
|
220
|
+
params["userResponse.quesAnsDetailArray[#{i}].answerFieldType"]=questionsArray[i]['answerFieldType']
|
221
|
+
params["userResponse.quesAnsDetailArray[#{i}].metaData"]=questionsArray[i]['metaData']
|
222
|
+
params["userResponse.quesAnsDetailArray[#{i}].question"]=questionsArray[i]['question']
|
223
|
+
params["userResponse.quesAnsDetailArray[#{i}].questionFieldType"]=questionsArray[i]['questionFieldType']
|
224
|
+
i += 1
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
user_session_execute_api '/jsonsdk/Refresh/putMFARequestForSite', params
|
166
229
|
end
|
167
230
|
|
168
231
|
def get_site_refresh_info site_account_id
|
169
232
|
user_session_execute_api '/jsonsdk/Refresh/getSiteRefreshInfo', { memSiteAccId: site_account_id }
|
170
233
|
end
|
171
234
|
|
235
|
+
def get_content_service_info_by_routing_number routing_number, no_trim = true
|
236
|
+
params = {
|
237
|
+
routingNumber: routing_number,
|
238
|
+
notrim: no_trim
|
239
|
+
}
|
240
|
+
|
241
|
+
cobranded_session_execute_api '/jsonsdk/RoutingNumberService/getContentServiceInfoByRoutingNumber', params
|
242
|
+
end
|
243
|
+
|
172
244
|
def get_item_summaries
|
173
245
|
user_session_execute_api '/jsonsdk/DataService/getItemSummaries', { 'bridgetAppId' => '10003200' }
|
174
246
|
end
|
@@ -233,7 +305,7 @@ module Yodlicious
|
|
233
305
|
connection = Faraday.new(url: base_url, ssl: ssl_opts, request: { proxy: proxy_opts })
|
234
306
|
|
235
307
|
response = connection.post("#{base_url}#{uri}", params)
|
236
|
-
debug_log "response=#{response.status}
|
308
|
+
debug_log "response=#{response.status} success?=#{response.success?} body=#{response.body} "
|
237
309
|
|
238
310
|
case response.status
|
239
311
|
when 200
|
@@ -265,7 +337,7 @@ module Yodlicious
|
|
265
337
|
end
|
266
338
|
|
267
339
|
def debug_log msg
|
268
|
-
logger.
|
340
|
+
logger.debug msg
|
269
341
|
end
|
270
342
|
|
271
343
|
def info_log msg
|
data/spec/integration_spec.rb
CHANGED
@@ -97,6 +97,31 @@ describe 'the yodlee api client integration tests', integration: true do
|
|
97
97
|
end
|
98
98
|
end
|
99
99
|
|
100
|
+
describe '#unregister_user' do
|
101
|
+
context 'Given a valid cobranded credentials and base_url' do
|
102
|
+
context 'Given a user who it logged into the api' do
|
103
|
+
context 'When #unregister_user is called the response' do
|
104
|
+
subject {
|
105
|
+
api.cobranded_login
|
106
|
+
api.login_or_register_user "testuser#{rand(100...200)}", 'testpassword143', 'test@test.com'
|
107
|
+
expect(api.user_session_token).not_to be_nil
|
108
|
+
api.unregister_user
|
109
|
+
}
|
110
|
+
|
111
|
+
|
112
|
+
it 'is expected to offer a valid response' do
|
113
|
+
is_expected.to be_kind_of(Yodlicious::Response)
|
114
|
+
is_expected.to be_success
|
115
|
+
expect(api.user_session_token).to be_nil
|
116
|
+
end
|
117
|
+
|
118
|
+
after { api.unregister_user }
|
119
|
+
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
100
125
|
describe 'the yodlicious login_or_register_user method' do
|
101
126
|
before { api.cobranded_login }
|
102
127
|
|
@@ -131,7 +156,7 @@ describe 'the yodlee api client integration tests', integration: true do
|
|
131
156
|
end
|
132
157
|
end
|
133
158
|
|
134
|
-
describe '
|
159
|
+
describe '#get_site_info' do
|
135
160
|
context 'Given a valid cobranded credentials and base_url' do
|
136
161
|
before {
|
137
162
|
api.cobranded_login
|
@@ -152,8 +177,40 @@ describe 'the yodlee api client integration tests', integration: true do
|
|
152
177
|
end
|
153
178
|
end
|
154
179
|
|
180
|
+
|
181
|
+
describe '#get_content_service_info_by_routing_number' do
|
182
|
+
context 'Given a valid cobranded credentials and base_url' do
|
183
|
+
before { api.cobranded_login }
|
184
|
+
|
185
|
+
context 'When #get_content_service_info_by_routing_number is called with a valid routing number the result' do
|
186
|
+
subject { api.get_content_service_info_by_routing_number 999988181 }
|
187
|
+
|
188
|
+
it 'is expected to contain valid content services info' do
|
189
|
+
is_expected.not_to be_nil
|
190
|
+
is_expected.to be_kind_of(Yodlicious::Response)
|
191
|
+
is_expected.to be_success
|
192
|
+
expect(subject.body['errorOccurred']).to be_nil
|
193
|
+
expect(subject.body['siteId']).to eq(16441)
|
194
|
+
expect(subject.body['contentServiceDisplayName']).to eq('Dag Site (US) - Bank')
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
context 'When #get_content_service_info_by_routing_number is called with an invalid routing number' do
|
199
|
+
subject { api.get_content_service_info_by_routing_number -23423 }
|
200
|
+
|
201
|
+
it 'is expected to contain valid error details' do
|
202
|
+
is_expected.not_to be_nil
|
203
|
+
is_expected.to be_kind_of(Yodlicious::Response)
|
204
|
+
is_expected.to be_fail
|
205
|
+
expect(subject.body['errorOccurred']).to be_truthy
|
206
|
+
expect(subject.body['exceptionType']).to eq('com.yodlee.core.routingnumberservice.InvalidRoutingNumberException')
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
155
212
|
#todo reorganize this spec to use given-when-then
|
156
|
-
describe '
|
213
|
+
describe '#add_site_account_and_wait' do
|
157
214
|
context 'Given a user who has registered and does not have any accounts' do
|
158
215
|
before {
|
159
216
|
api.cobranded_login
|
@@ -164,7 +221,7 @@ describe 'the yodlee api client integration tests', integration: true do
|
|
164
221
|
}
|
165
222
|
|
166
223
|
let(:seconds_between_retry) { 3 }
|
167
|
-
let(:
|
224
|
+
let(:max_retrys) { 10 }
|
168
225
|
|
169
226
|
after {
|
170
227
|
begin
|
@@ -175,10 +232,10 @@ describe 'the yodlee api client integration tests', integration: true do
|
|
175
232
|
|
176
233
|
context 'When a invalid username and password for an account is added' do
|
177
234
|
before {
|
178
|
-
dag_login_form['componentList'][0]['
|
179
|
-
dag_login_form['componentList'][1]['
|
235
|
+
dag_login_form['componentList'][0]['fieldValue'] = 'invalid_username'
|
236
|
+
dag_login_form['componentList'][1]['fieldValue'] = 'invalid_password'
|
180
237
|
}
|
181
|
-
subject { api.add_site_account_and_wait(16441, dag_login_form, seconds_between_retry,
|
238
|
+
subject { api.add_site_account_and_wait(16441, dag_login_form, seconds_between_retry, max_retrys) }
|
182
239
|
|
183
240
|
it 'is expected to respond with siteRefreshStatus=LOGIN_FAILURE and refreshMode=NORMAL a siteAccountId' do
|
184
241
|
# puts JSON.pretty_generate(subject.body)
|
@@ -191,10 +248,10 @@ describe 'the yodlee api client integration tests', integration: true do
|
|
191
248
|
|
192
249
|
context 'When a valid username and password for an account is added' do
|
193
250
|
before {
|
194
|
-
dag_login_form['componentList'][0]['
|
195
|
-
dag_login_form['componentList'][1]['
|
251
|
+
dag_login_form['componentList'][0]['fieldValue'] = 'yodlicious.site16441.1'
|
252
|
+
dag_login_form['componentList'][1]['fieldValue'] = 'site16441.1'
|
196
253
|
}
|
197
|
-
subject { api.add_site_account_and_wait(16441, dag_login_form, seconds_between_retry,
|
254
|
+
subject { api.add_site_account_and_wait(16441, dag_login_form, seconds_between_retry, max_retrys) }
|
198
255
|
|
199
256
|
it 'is expected to respond with siteRefreshStatus=LOGIN_SUCCESS and refreshMode=NORMAL a siteAccountId' do
|
200
257
|
is_expected.to be_success
|
@@ -207,6 +264,239 @@ describe 'the yodlee api client integration tests', integration: true do
|
|
207
264
|
end
|
208
265
|
end
|
209
266
|
|
267
|
+
describe '#get_mfa_response_for_site' do
|
268
|
+
context 'Given a valid cobranded credentials and base_url' do
|
269
|
+
context 'Given a user who it logged into the api' do
|
270
|
+
context 'When #get_mfa_response_for_site is called the response' do
|
271
|
+
subject {
|
272
|
+
api.cobranded_login
|
273
|
+
response = api.login_or_register_user "testuser#{rand(100...200)}", 'testpassword143', 'test@test.com'
|
274
|
+
|
275
|
+
dag_fmfa_login_form['componentList'][0]['fieldValue'] = 'yodlicious1.site16445.1'
|
276
|
+
dag_fmfa_login_form['componentList'][1]['fieldValue'] = 'site16445.1'
|
277
|
+
|
278
|
+
response = api.add_site_account_and_wait(16445, dag_fmfa_login_form)
|
279
|
+
expect(response).to be_success
|
280
|
+
# puts "refreshMode= #{response.body['siteRefreshInfo']['siteRefreshMode']['refreshMode']}"
|
281
|
+
expect(response.body['siteRefreshInfo']['siteRefreshMode']['refreshMode']).to eq('MFA')
|
282
|
+
api.get_mfa_response_for_site response.body['siteAccountId']
|
283
|
+
}
|
284
|
+
|
285
|
+
it 'is expected be a valid response' do
|
286
|
+
is_expected.to be_kind_of(Yodlicious::Response)
|
287
|
+
is_expected.to be_success
|
288
|
+
expect(subject.body['isMessageAvailable']).not_to be_nil
|
289
|
+
end
|
290
|
+
|
291
|
+
after { api.unregister_user }
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
describe '#get_mfa_response_for_site_and_wait' do
|
298
|
+
context 'Given a valid cobranded credentials and base_url' do
|
299
|
+
context 'Given a user who it logged into the api' do
|
300
|
+
context 'When #get_mfa_response_for_site_and_wait is called the response' do
|
301
|
+
subject {
|
302
|
+
api.cobranded_login
|
303
|
+
response = api.login_or_register_user "testuser#{rand(100...200)}", 'testpassword143', 'test@test.com'
|
304
|
+
|
305
|
+
dag_fmfa_login_form['componentList'][0]['fieldValue'] = 'yodlicious1.site16445.1'
|
306
|
+
dag_fmfa_login_form['componentList'][1]['fieldValue'] = 'site16445.1'
|
307
|
+
|
308
|
+
response = api.add_site_account_and_wait(16445, dag_fmfa_login_form)
|
309
|
+
expect(response).to be_success
|
310
|
+
|
311
|
+
expect(response.body['siteRefreshInfo']['siteRefreshMode']['refreshMode']).to eq('MFA')
|
312
|
+
api.get_mfa_response_for_site_and_wait response.body['siteAccountId'], 1
|
313
|
+
}
|
314
|
+
|
315
|
+
it 'is expected be a valid response' do
|
316
|
+
is_expected.to be_kind_of(Yodlicious::Response)
|
317
|
+
is_expected.to be_success
|
318
|
+
expect(subject.body['isMessageAvailable']).to be_truthy
|
319
|
+
expect(subject.body['fieldInfo']).not_to be_nil
|
320
|
+
end
|
321
|
+
|
322
|
+
after { api.unregister_user }
|
323
|
+
end
|
324
|
+
end
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
describe '#put_mfa_request_for_site' do
|
329
|
+
context 'Given a valid cobranded credentials and base_url' do
|
330
|
+
context 'Given a user who is logged into the api' do
|
331
|
+
context 'Given a user attempting to add a site with Token Based MFA' do
|
332
|
+
context 'When #put_mfa_request_for_site is called the response' do
|
333
|
+
subject {
|
334
|
+
api.cobranded_login
|
335
|
+
response = api.login_or_register_user "testuser#{rand(100...200)}", 'testpassword143', 'test@test.com'
|
336
|
+
|
337
|
+
dag_fmfa_login_form['componentList'][0]['fieldValue'] = 'yodlicious1.site16445.1'
|
338
|
+
dag_fmfa_login_form['componentList'][1]['fieldValue'] = 'site16445.1'
|
339
|
+
|
340
|
+
response = api.add_site_account_and_wait(16445, dag_fmfa_login_form)
|
341
|
+
expect(response).to be_success
|
342
|
+
|
343
|
+
expect(response.body['siteRefreshInfo']['siteRefreshMode']['refreshMode']).to eq('MFA')
|
344
|
+
site_account_id = response.body['siteAccountId']
|
345
|
+
response = api.get_mfa_response_for_site_and_wait site_account_id, 2
|
346
|
+
#{
|
347
|
+
# "isMessageAvailable":true,
|
348
|
+
# "fieldInfo":{
|
349
|
+
# "responseFieldType":"text",
|
350
|
+
# "minimumLength":-1,
|
351
|
+
# "maximumLength":6,
|
352
|
+
# "displayString":"Security Key"
|
353
|
+
# },
|
354
|
+
# "timeOutTime":116420,
|
355
|
+
# "itemId":0,
|
356
|
+
# "memSiteAccId":10992295,
|
357
|
+
# "retry":false
|
358
|
+
#}
|
359
|
+
expect(response.body['isMessageAvailable']).to be_truthy
|
360
|
+
|
361
|
+
field_info = response.body['fieldInfo']
|
362
|
+
field_info['fieldValue'] = "monkeys"
|
363
|
+
api.put_mfa_request_for_site site_account_id, :MFATokenResponse, field_info
|
364
|
+
}
|
365
|
+
|
366
|
+
it 'is expected be a valid response' do
|
367
|
+
is_expected.to be_kind_of(Yodlicious::Response)
|
368
|
+
is_expected.to be_success
|
369
|
+
expect(subject.body['primitiveObj']).to be_truthy
|
370
|
+
end
|
371
|
+
|
372
|
+
after { api.unregister_user }
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
context 'Given a user attempting to add a site with Security Question and Answer MFA' do
|
377
|
+
context 'When #put_mfa_request_for_site is called the response' do
|
378
|
+
subject {
|
379
|
+
api.cobranded_login
|
380
|
+
response = api.login_or_register_user "testuser#{rand(100...200)}", 'testpassword143', 'test@test.com'
|
381
|
+
|
382
|
+
dag_sqa_login_form['componentList'][0]['fieldValue'] = 'yodlicious1.site16486.1'
|
383
|
+
dag_sqa_login_form['componentList'][1]['fieldValue'] = 'site16486.1'
|
384
|
+
|
385
|
+
response = api.add_site_account(16486, dag_sqa_login_form)
|
386
|
+
expect(response).to be_success
|
387
|
+
|
388
|
+
expect(response.body['siteRefreshInfo']['siteRefreshMode']['refreshMode']).to eq('MFA')
|
389
|
+
site_account_id = response.body['siteAccountId']
|
390
|
+
response = api.get_mfa_response_for_site_and_wait site_account_id, 2
|
391
|
+
# {
|
392
|
+
# "isMessageAvailable":true,
|
393
|
+
# "fieldInfo":{
|
394
|
+
# "questionAndAnswerValues":[
|
395
|
+
# {
|
396
|
+
# "question":"What is the name of your state?",
|
397
|
+
# "questionFieldType":"label",
|
398
|
+
# "responseFieldType":"text",
|
399
|
+
# "isRequired":"true",
|
400
|
+
# "sequence":1,
|
401
|
+
# "metaData":"QUESTION_1"
|
402
|
+
# },
|
403
|
+
# {
|
404
|
+
# "question":"What is the name of your first school",
|
405
|
+
# "questionFieldType":"label",
|
406
|
+
# "responseFieldType":"text",
|
407
|
+
# "isRequired":"true",
|
408
|
+
# "sequence":2,
|
409
|
+
# "metaData":"QUESTION_2"
|
410
|
+
# }
|
411
|
+
# ],
|
412
|
+
# "numOfMandatoryQuestions":-1
|
413
|
+
# },
|
414
|
+
# "timeOutTime":96180,
|
415
|
+
# "itemId":0,
|
416
|
+
# "memSiteAccId":11025687,
|
417
|
+
# "retry":false
|
418
|
+
# }
|
419
|
+
expect(response.body['isMessageAvailable']).to be_truthy
|
420
|
+
|
421
|
+
field_info = response.body['fieldInfo']
|
422
|
+
field_info['questionAndAnswerValues'][0]['fieldValue'] = 'Texas'
|
423
|
+
field_info['questionAndAnswerValues'][1]['fieldValue'] = 'w3schools'
|
424
|
+
api.put_mfa_request_for_site site_account_id, :MFAQuesAnsResponse, field_info
|
425
|
+
}
|
426
|
+
|
427
|
+
it 'is expected be a valid response' do
|
428
|
+
is_expected.to be_kind_of(Yodlicious::Response)
|
429
|
+
is_expected.to be_success
|
430
|
+
expect(subject.body['primitiveObj']).to be_truthy
|
431
|
+
end
|
432
|
+
|
433
|
+
after { api.unregister_user }
|
434
|
+
end
|
435
|
+
end
|
436
|
+
|
437
|
+
context 'Given a user attempting to add a site with Captcha MFA' do
|
438
|
+
context 'When #put_mfa_request_for_site is called the response' do
|
439
|
+
subject {
|
440
|
+
api.cobranded_login
|
441
|
+
response = api.login_or_register_user "testuser#{rand(100...200)}", 'testpassword143', 'test@test.com'
|
442
|
+
|
443
|
+
dag_sqa_login_form['componentList'][0]['fieldValue'] = 'yodlicious1.site18769.1'
|
444
|
+
dag_sqa_login_form['componentList'][1]['fieldValue'] = 'site18769.1'
|
445
|
+
|
446
|
+
response = api.add_site_account(18769, dag_sqa_login_form)
|
447
|
+
expect(response).to be_success
|
448
|
+
|
449
|
+
expect(response.body['siteRefreshInfo']['siteRefreshMode']['refreshMode']).to eq('MFA')
|
450
|
+
site_account_id = response.body['siteAccountId']
|
451
|
+
response = api.get_mfa_response_for_site_and_wait site_account_id, 2
|
452
|
+
# {
|
453
|
+
# "isMessageAvailable":true,
|
454
|
+
# "fieldInfo":{
|
455
|
+
# "questionAndAnswerValues":[
|
456
|
+
# {
|
457
|
+
# "question":"What is the name of your state?",
|
458
|
+
# "questionFieldType":"label",
|
459
|
+
# "responseFieldType":"text",
|
460
|
+
# "isRequired":"true",
|
461
|
+
# "sequence":1,
|
462
|
+
# "metaData":"QUESTION_1"
|
463
|
+
# },
|
464
|
+
# {
|
465
|
+
# "question":"What is the name of your first school",
|
466
|
+
# "questionFieldType":"label",
|
467
|
+
# "responseFieldType":"text",
|
468
|
+
# "isRequired":"true",
|
469
|
+
# "sequence":2,
|
470
|
+
# "metaData":"QUESTION_2"
|
471
|
+
# }
|
472
|
+
# ],
|
473
|
+
# "numOfMandatoryQuestions":-1
|
474
|
+
# },
|
475
|
+
# "timeOutTime":96180,
|
476
|
+
# "itemId":0,
|
477
|
+
# "memSiteAccId":11025687,
|
478
|
+
# "retry":false
|
479
|
+
# }
|
480
|
+
expect(response.body['isMessageAvailable']).to be_truthy
|
481
|
+
|
482
|
+
field_info = response.body['fieldInfo']
|
483
|
+
field_info['fieldValue'] = "monkeys"
|
484
|
+
api.put_mfa_request_for_site site_account_id, :MFAImageResponse, field_info
|
485
|
+
}
|
486
|
+
|
487
|
+
it 'is expected be a valid response' do
|
488
|
+
is_expected.to be_kind_of(Yodlicious::Response)
|
489
|
+
is_expected.to be_success
|
490
|
+
expect(subject.body['primitiveObj']).to be_truthy
|
491
|
+
end
|
492
|
+
|
493
|
+
after { api.unregister_user }
|
494
|
+
end
|
495
|
+
end
|
496
|
+
end
|
497
|
+
end
|
498
|
+
end
|
499
|
+
|
210
500
|
describe 'the yodlee apis fetching summary data about registered site accounts endpoints' do
|
211
501
|
context 'Given a registered user with registered accounts' do
|
212
502
|
before {
|
@@ -276,8 +566,8 @@ describe 'the yodlee api client integration tests', integration: true do
|
|
276
566
|
before {
|
277
567
|
api.cobranded_login
|
278
568
|
api.login_or_register_user 'testuser_with_transactions@liftforward.com', 'testpassword143', 'testuser_with_transactions@liftforward.com'
|
279
|
-
dag_login_form['componentList'][0]['
|
280
|
-
dag_login_form['componentList'][1]['
|
569
|
+
dag_login_form['componentList'][0]['fieldValue'] = 'yodlicious.site16441.1'
|
570
|
+
dag_login_form['componentList'][1]['fieldValue'] = 'site16441.1'
|
281
571
|
api.add_site_account_and_wait(16441, dag_login_form)
|
282
572
|
}
|
283
573
|
|
@@ -466,4 +756,140 @@ describe 'the yodlee api client integration tests', integration: true do
|
|
466
756
|
"defaultHelpText": "16103"
|
467
757
|
}')
|
468
758
|
}
|
759
|
+
|
760
|
+
let(:dag_fmfa_login_form) {
|
761
|
+
{
|
762
|
+
"conjunctionOp"=> {
|
763
|
+
"conjuctionOp"=>1
|
764
|
+
},
|
765
|
+
"componentList"=> [
|
766
|
+
{
|
767
|
+
"valueIdentifier"=>"LOGIN1",
|
768
|
+
"valueMask"=>"LOGIN_FIELD",
|
769
|
+
"fieldType"=>{"typeName"=>"IF_LOGIN"},
|
770
|
+
"size"=>20,
|
771
|
+
"maxlength"=>40,
|
772
|
+
"name"=>"LOGIN1",
|
773
|
+
"displayName"=>"Catalog",
|
774
|
+
"isEditable"=>true,
|
775
|
+
"isOptional"=>false,
|
776
|
+
"isEscaped"=>false,
|
777
|
+
"helpText"=>"150876",
|
778
|
+
"isOptionalMFA"=>false,
|
779
|
+
"isMFA"=>false
|
780
|
+
},
|
781
|
+
{
|
782
|
+
"valueIdentifier"=>"PASSWORD1",
|
783
|
+
"valueMask"=>"LOGIN_FIELD",
|
784
|
+
"fieldType"=>{"typeName"=>"IF_PASSWORD"},
|
785
|
+
"size"=>20,
|
786
|
+
"maxlength"=>40,
|
787
|
+
"name"=>"PASSWORD1",
|
788
|
+
"displayName"=>"Password",
|
789
|
+
"isEditable"=>true,
|
790
|
+
"isOptional"=>false,
|
791
|
+
"isEscaped"=>false,
|
792
|
+
"helpText"=>"150877",
|
793
|
+
"isOptionalMFA"=>false,
|
794
|
+
"isMFA"=>false
|
795
|
+
}
|
796
|
+
],
|
797
|
+
"defaultHelpText"=>"16126"
|
798
|
+
}
|
799
|
+
}
|
800
|
+
|
801
|
+
let(:dag_sqa_login_form) {
|
802
|
+
JSON.parse('{
|
803
|
+
"conjunctionOp":{
|
804
|
+
"conjuctionOp":1
|
805
|
+
},
|
806
|
+
"componentList":[
|
807
|
+
{
|
808
|
+
"valueIdentifier":"LOGIN",
|
809
|
+
"valueMask":"LOGIN_FIELD",
|
810
|
+
"fieldType":{
|
811
|
+
"typeName":"IF_LOGIN"
|
812
|
+
},
|
813
|
+
"size":20,
|
814
|
+
"maxlength":40,
|
815
|
+
"name":"LOGIN",
|
816
|
+
"displayName":"Catalog",
|
817
|
+
"isEditable":true,
|
818
|
+
"isOptional":false,
|
819
|
+
"isEscaped":false,
|
820
|
+
"helpText":"150978",
|
821
|
+
"isOptionalMFA":false,
|
822
|
+
"isMFA":false
|
823
|
+
},
|
824
|
+
{
|
825
|
+
"valueIdentifier":"PASSWORD",
|
826
|
+
"valueMask":"LOGIN_FIELD",
|
827
|
+
"fieldType":{
|
828
|
+
"typeName":"IF_PASSWORD"
|
829
|
+
},
|
830
|
+
"size":20,
|
831
|
+
"maxlength":40,
|
832
|
+
"name":"PASSWORD",
|
833
|
+
"displayName":"Password",
|
834
|
+
"isEditable":true,
|
835
|
+
"isOptional":false,
|
836
|
+
"isEscaped":false,
|
837
|
+
"helpText":"150979",
|
838
|
+
"isOptionalMFA":false,
|
839
|
+
"isMFA":false
|
840
|
+
}
|
841
|
+
],
|
842
|
+
"defaultHelpText":"16176"
|
843
|
+
}')
|
844
|
+
}
|
469
845
|
end
|
846
|
+
|
847
|
+
|
848
|
+
|
849
|
+
# {"popularity"=>0,
|
850
|
+
# "siteId"=>16477,
|
851
|
+
# "orgId"=>1148,
|
852
|
+
# "defaultDisplayName"=>"DagSIteMFAAndNonMFA (US)",
|
853
|
+
# "defaultOrgDisplayName"=>"Demo Bank",
|
854
|
+
# "contentServiceInfos"=>
|
855
|
+
# [{"contentServiceId"=>20631, "siteId"=>16477, "containerInfo"=>{"containerName"=>"bank", "assetType"=>1}},
|
856
|
+
# {"contentServiceId"=>20632, "siteId"=>16477, "containerInfo"=>{"containerName"=>"miles", "assetType"=>0}}],
|
857
|
+
# "enabledContainers"=>[{"containerName"=>"bank", "assetType"=>1}, {"containerName"=>"miles", "assetType"=>0}],
|
858
|
+
# "baseUrl"=>"http://192.168.210.152:9090/dag/dhaction.do",
|
859
|
+
# "loginForms"=>
|
860
|
+
# [{"conjunctionOp"=>{"conjuctionOp"=>1},
|
861
|
+
# "componentList"=>
|
862
|
+
# [{"valueIdentifier"=>"LOGIN",
|
863
|
+
# "valueMask"=>"LOGIN_FIELD",
|
864
|
+
# "fieldType"=>{"typeName"=>"IF_LOGIN"},
|
865
|
+
# "size"=>20,
|
866
|
+
# "maxlength"=>40,
|
867
|
+
# "name"=>"LOGIN",
|
868
|
+
# "displayName"=>"Catalog",
|
869
|
+
# "isEditable"=>true,
|
870
|
+
# "isOptional"=>false,
|
871
|
+
# "isEscaped"=>false,
|
872
|
+
# "helpText"=>"150970",
|
873
|
+
# "isOptionalMFA"=>false,
|
874
|
+
# "isMFA"=>false},
|
875
|
+
# {"valueIdentifier"=>"PASSWORD",
|
876
|
+
# "valueMask"=>"LOGIN_FIELD",
|
877
|
+
# "fieldType"=>{"typeName"=>"IF_PASSWORD"},
|
878
|
+
# "size"=>20,
|
879
|
+
# "maxlength"=>40,
|
880
|
+
# "name"=>"PASSWORD",
|
881
|
+
# "displayName"=>"Password",
|
882
|
+
# "isEditable"=>true,
|
883
|
+
# "isOptional"=>false,
|
884
|
+
# "isEscaped"=>false,
|
885
|
+
# "helpText"=>"150971",
|
886
|
+
# "isOptionalMFA"=>false,
|
887
|
+
# "isMFA"=>false}],
|
888
|
+
# "defaultHelpText"=>"16167"}],
|
889
|
+
# "isHeld"=>false,
|
890
|
+
# "isCustom"=>false,
|
891
|
+
# "mfaType"=>{"typeId"=>4, "typeName"=>"SECURITY_QUESTION"},
|
892
|
+
# "mfaCoverage"=>"FMPA",
|
893
|
+
# "siteSearchVisibility"=>true,
|
894
|
+
# "isAlreadyAddedByUser"=>false,
|
895
|
+
# "isOauthEnabled"=>false}
|
data/spec/spec_helper.rb
CHANGED
@@ -22,7 +22,7 @@ describe 'parameter translator' do
|
|
22
22
|
'helpText' => 4710,
|
23
23
|
'isOptionalMFA' => false,
|
24
24
|
'isMFA' => false,
|
25
|
-
'
|
25
|
+
'fieldValue' => 'kanyewest'
|
26
26
|
},
|
27
27
|
{
|
28
28
|
'valueIdentifier' => 'PASSWORD',
|
@@ -40,7 +40,7 @@ describe 'parameter translator' do
|
|
40
40
|
'helpText' => 11976,
|
41
41
|
'isOptionalMFA' => false,
|
42
42
|
'isMFA' => false,
|
43
|
-
'
|
43
|
+
'fieldValue' => 'iLoveTheGrammys'
|
44
44
|
}
|
45
45
|
]
|
46
46
|
}
|
@@ -3,7 +3,7 @@ require "yodlicious/config"
|
|
3
3
|
|
4
4
|
describe Yodlicious::YodleeApi do
|
5
5
|
|
6
|
-
context 'Given a new uninitialized YodleeApi
|
6
|
+
context 'Given a new uninitialized YodleeApi object' do
|
7
7
|
before {
|
8
8
|
Yodlicious::Config.base_url=nil
|
9
9
|
Yodlicious::Config.cobranded_username=nil
|
@@ -234,4 +234,107 @@ describe Yodlicious::YodleeApi do
|
|
234
234
|
end
|
235
235
|
end
|
236
236
|
end
|
237
|
+
|
238
|
+
describe '#should_retry_get_mfa_response?' do
|
239
|
+
let (:api) { Yodlicious::YodleeApi.new }
|
240
|
+
let (:response) { double("response") }
|
241
|
+
|
242
|
+
context 'Given get mfa response has failed' do
|
243
|
+
before { allow(response).to receive(:success?).and_return(false) }
|
244
|
+
subject { api.should_retry_get_mfa_response?(response,0,1) }
|
245
|
+
it { is_expected.to be_falsy }
|
246
|
+
end
|
247
|
+
|
248
|
+
context 'Given get mfa response is success' do
|
249
|
+
before { allow(response).to receive(:success?).and_return(true) }
|
250
|
+
|
251
|
+
context 'Given an error code is returned' do
|
252
|
+
before { allow(response).to receive(:body).and_return({ 'errorCode' => 100 }) }
|
253
|
+
subject { api.should_retry_get_mfa_response?(response,0,1) }
|
254
|
+
it { is_expected.to be_falsy }
|
255
|
+
end
|
256
|
+
|
257
|
+
context 'Given no error code is returned' do
|
258
|
+
context 'Given the MFA message is available' do
|
259
|
+
before { allow(response).to receive(:body).and_return({ 'isMessageAvailable' => true }) }
|
260
|
+
subject { api.should_retry_get_mfa_response?(response,0,1) }
|
261
|
+
it { is_expected.to be_falsy }
|
262
|
+
end
|
263
|
+
|
264
|
+
context 'Given the MFA message is not available' do
|
265
|
+
before { allow(response).to receive(:body).and_return({ 'isMessageAvailable' => false }) }
|
266
|
+
context 'Given all the trys have been used up' do
|
267
|
+
subject { api.should_retry_get_mfa_response?(response,1,1) }
|
268
|
+
it { is_expected.to be_falsy }
|
269
|
+
end
|
270
|
+
|
271
|
+
context 'Given the trys have not been used up' do
|
272
|
+
subject { api.should_retry_get_mfa_response?(response,0,2) }
|
273
|
+
it { is_expected.to be_truthy }
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
describe '#should_retry_get_site_refresh_info' do
|
281
|
+
let (:api) { Yodlicious::YodleeApi.new }
|
282
|
+
let (:response) { double("response") }
|
283
|
+
|
284
|
+
context 'Given get mfa response has failed' do
|
285
|
+
before { allow(response).to receive(:success?).and_return(false) }
|
286
|
+
subject { api.should_retry_get_site_refresh_info?(response,0,1) }
|
287
|
+
it { is_expected.to be_falsy }
|
288
|
+
end
|
289
|
+
|
290
|
+
context 'Given get mfa response is success' do
|
291
|
+
before { allow(response).to receive(:success?).and_return(true) }
|
292
|
+
|
293
|
+
context 'Given an code 801 is returned' do
|
294
|
+
before { allow(response).to receive(:body).and_return({ 'code' => 801 }) }
|
295
|
+
subject { api.should_retry_get_site_refresh_info?(response,0,1) }
|
296
|
+
it { is_expected.to be_truthy }
|
297
|
+
end
|
298
|
+
|
299
|
+
context 'Given not 801 and not 0 code is returned' do
|
300
|
+
before { allow(response).to receive(:body).and_return({ 'code' => 5 }) }
|
301
|
+
subject { api.should_retry_get_site_refresh_info?(response,0,1) }
|
302
|
+
it { is_expected.to be_falsy }
|
303
|
+
end
|
304
|
+
|
305
|
+
context 'Given a code 0 is returned' do
|
306
|
+
context 'Given a siteRefreshStatus of REFRESH_COMPLETED' do
|
307
|
+
before { allow(response).to receive(:body).and_return({ 'code' => 0, "siteRefreshStatus" => { "siteRefreshStatus" => "REFRESH_COMPLETED" }}) }
|
308
|
+
subject { api.should_retry_get_site_refresh_info?(response,0,1) }
|
309
|
+
it { is_expected.to be_falsy }
|
310
|
+
end
|
311
|
+
|
312
|
+
context 'Given a siteRefreshStatus of REFRESH_TIMED_OUT' do
|
313
|
+
before { allow(response).to receive(:body).and_return({ 'code' => 0, "siteRefreshStatus" => { "siteRefreshStatus" => "REFRESH_TIMED_OUT" }}) }
|
314
|
+
subject { api.should_retry_get_site_refresh_info?(response,0,1) }
|
315
|
+
it { is_expected.to be_falsy }
|
316
|
+
end
|
317
|
+
|
318
|
+
context 'Given a siteRefreshStatus of LOGIN_SUCCESS' do
|
319
|
+
before { allow(response).to receive(:body).and_return({ 'code' => 0, "siteRefreshStatus" => { "siteRefreshStatus" => "LOGIN_SUCCESS" }}) }
|
320
|
+
subject { api.should_retry_get_site_refresh_info?(response,0,1) }
|
321
|
+
it { is_expected.to be_falsy }
|
322
|
+
end
|
323
|
+
|
324
|
+
context 'Given a siteRefreshStatus of REFRESH_TRIGGERED' do
|
325
|
+
before { allow(response).to receive(:body).and_return({ 'code' => 0, "siteRefreshStatus" => { "siteRefreshStatus" => "REFRESH_TRIGGERED" }}) }
|
326
|
+
subject { api.should_retry_get_site_refresh_info?(response,0,1) }
|
327
|
+
it { is_expected.to be_truthy }
|
328
|
+
end
|
329
|
+
|
330
|
+
context 'Given a siteRefreshStatus of REFRESH_TRIGGERED' do
|
331
|
+
before { allow(response).to receive(:body).and_return({ 'code' => 0, "siteRefreshStatus" => { "siteRefreshStatus" => "REFRESH_TRIGGERED" }}) }
|
332
|
+
context 'Given trys have been used up' do
|
333
|
+
subject { api.should_retry_get_site_refresh_info?(response,1,1) }
|
334
|
+
it { is_expected.to be_falsy }
|
335
|
+
end
|
336
|
+
end
|
337
|
+
end
|
338
|
+
end
|
339
|
+
end
|
237
340
|
end
|
data/yodlicious.png
ADDED
Binary file
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: yodlicious
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Drew Nichols
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-03-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -110,14 +110,15 @@ files:
|
|
110
110
|
- lib/yodlicious/parameter_translator.rb
|
111
111
|
- lib/yodlicious/response.rb
|
112
112
|
- lib/yodlicious/version.rb
|
113
|
-
- lib/yodlicious/
|
113
|
+
- lib/yodlicious/yodlee_api.rb
|
114
114
|
- spec/integration_spec.rb
|
115
115
|
- spec/spec_helper.rb
|
116
116
|
- spec/unit/config_spec.rb
|
117
117
|
- spec/unit/parameter_translator_spec.rb
|
118
118
|
- spec/unit/response_spec.rb
|
119
|
-
- spec/unit/
|
119
|
+
- spec/unit/yodlee_api_spec.rb
|
120
120
|
- yodlicious.gemspec
|
121
|
+
- yodlicious.png
|
121
122
|
homepage: https://github.com/liftforward/yodlicious
|
122
123
|
licenses:
|
123
124
|
- MIT
|
@@ -148,4 +149,4 @@ test_files:
|
|
148
149
|
- spec/unit/config_spec.rb
|
149
150
|
- spec/unit/parameter_translator_spec.rb
|
150
151
|
- spec/unit/response_spec.rb
|
151
|
-
- spec/unit/
|
152
|
+
- spec/unit/yodlee_api_spec.rb
|