plaid 1.7.1 → 2.0.0.alpha
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -0
- data/CONTRIBUTING.md +15 -0
- data/LICENSE +20 -0
- data/README.md +215 -63
- data/Rakefile +50 -4
- data/UPGRADING.md +45 -0
- data/bin/console +13 -0
- data/bin/setup +8 -0
- data/lib/plaid.rb +51 -88
- data/lib/plaid/account.rb +144 -0
- data/lib/plaid/category.rb +62 -0
- data/lib/plaid/client.rb +67 -0
- data/lib/plaid/connector.rb +168 -0
- data/lib/plaid/errors.rb +24 -14
- data/lib/plaid/income.rb +106 -0
- data/lib/plaid/info.rb +65 -0
- data/lib/plaid/institution.rb +240 -0
- data/lib/plaid/risk.rb +34 -0
- data/lib/plaid/transaction.rb +123 -0
- data/lib/plaid/user.rb +430 -0
- data/lib/plaid/version.rb +1 -1
- data/plaid.gemspec +20 -12
- metadata +58 -62
- data/.gitignore +0 -15
- data/.rspec +0 -2
- data/.travis.yml +0 -5
- data/LICENSE.txt +0 -22
- data/PUBLISHING.md +0 -21
- data/lib/plaid/config.rb +0 -19
- data/lib/plaid/connection.rb +0 -109
- data/lib/plaid/models/account.rb +0 -24
- data/lib/plaid/models/category.rb +0 -17
- data/lib/plaid/models/exchange_token_response.rb +0 -11
- data/lib/plaid/models/info.rb +0 -12
- data/lib/plaid/models/institution.rb +0 -22
- data/lib/plaid/models/transaction.rb +0 -24
- data/lib/plaid/models/user.rb +0 -189
- data/spec/plaid/config_spec.rb +0 -67
- data/spec/plaid/connection_spec.rb +0 -191
- data/spec/plaid/error_spec.rb +0 -10
- data/spec/plaid/models/account_spec.rb +0 -37
- data/spec/plaid/models/category_spec.rb +0 -16
- data/spec/plaid/models/institution_spec.rb +0 -19
- data/spec/plaid/models/transaction_spec.rb +0 -28
- data/spec/plaid/models/user_spec.rb +0 -172
- data/spec/plaid_spec.rb +0 -263
- data/spec/spec_helper.rb +0 -14
data/spec/plaid/error_spec.rb
DELETED
@@ -1,10 +0,0 @@
|
|
1
|
-
describe Plaid::PlaidError do
|
2
|
-
describe "#new" do
|
3
|
-
it "allows code, message and resolution" do
|
4
|
-
error = Plaid::PlaidError.new 1, "testing", "fix it"
|
5
|
-
expect(error.code).to eq(1)
|
6
|
-
expect(error.message).to eq("testing")
|
7
|
-
expect(error.resolve).to eq("fix it")
|
8
|
-
end
|
9
|
-
end
|
10
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
describe Plaid::Account do
|
2
|
-
# API: semi-private
|
3
|
-
describe '.new' do
|
4
|
-
subject { Plaid::Account.new(results) }
|
5
|
-
|
6
|
-
def self.with_results(_results, &examples)
|
7
|
-
context "with results #{_results}" do
|
8
|
-
let(:results) { _results }
|
9
|
-
instance_eval(&examples)
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
with_results('meta' => {'name' => 'Name'}) do it { expect(subject.name).to eql('Name') } end
|
14
|
-
with_results('_id' => 'ID') do it { expect(subject.id).to eql('ID') } end
|
15
|
-
with_results('type' => 'Type') do it { expect(subject.type).to eql('Type') } end
|
16
|
-
with_results('type' => 'STyp') do it { expect(subject.type).to eql('STyp') } end
|
17
|
-
with_results('meta' => nil) do it { expect(subject.meta).to be_nil } end
|
18
|
-
with_results('meta' => {}) do it { expect(subject.meta).to eql({}) } end
|
19
|
-
|
20
|
-
with_results('balance' => { 'available' => 100.00 } ) do it { expect(subject.available_balance).to eql(100.00) } end
|
21
|
-
with_results('balance' => { 'current' => 200.00 } ) do it { expect(subject.current_balance).to eql(200.00) } end
|
22
|
-
|
23
|
-
with_results('institution_type' => 'Type') do it { expect(subject.institution_type).to eql('Type') } end
|
24
|
-
|
25
|
-
with_results('numbers' => nil) do
|
26
|
-
it { expect(subject.numbers).to eql('Upgrade user to access routing information for this account') }
|
27
|
-
end
|
28
|
-
|
29
|
-
with_results('numbers' => {}) do
|
30
|
-
it { expect(subject.numbers).to eql({}) }
|
31
|
-
end
|
32
|
-
|
33
|
-
with_results({}) do
|
34
|
-
it { expect(subject.name).to eq nil } # doesn't blow up if 'meta' is missing
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
@@ -1,16 +0,0 @@
|
|
1
|
-
describe Plaid::Category do
|
2
|
-
context 'when a single category is found' do
|
3
|
-
let(:category) { Plaid.category('17001013') }
|
4
|
-
it { expect(category).to be_kind_of(Plaid::Category) }
|
5
|
-
end
|
6
|
-
|
7
|
-
context 'when all categories are found' do
|
8
|
-
let(:category) { Plaid.category }
|
9
|
-
it { expect(category).to be_kind_of(Array)}
|
10
|
-
end
|
11
|
-
|
12
|
-
context 'when category is not found' do
|
13
|
-
it { expect { Plaid.category('dumb_cat') }.to raise_error(Plaid::NotFound, 'unable to find category') }
|
14
|
-
end
|
15
|
-
|
16
|
-
end
|
@@ -1,19 +0,0 @@
|
|
1
|
-
describe Plaid::Institution do
|
2
|
-
context 'when a single institution is found' do
|
3
|
-
let(:institution) { Plaid.institution('5301a93ac140de84910000e0') }
|
4
|
-
|
5
|
-
it { expect(institution).to be_kind_of(Plaid::Institution) }
|
6
|
-
it { expect(institution.mfa).to be_kind_of(Array) }
|
7
|
-
it { expect(institution.products).to be_kind_of(Array) }
|
8
|
-
it { expect(institution.credentials).to be_kind_of(Hash) }
|
9
|
-
end
|
10
|
-
|
11
|
-
context 'when all institutions are found' do
|
12
|
-
let(:institution) { Plaid.institution }
|
13
|
-
it { expect(institution).to be_kind_of(Array) }
|
14
|
-
end
|
15
|
-
|
16
|
-
context 'when institution is not found' do
|
17
|
-
it { expect { Plaid.institution('dumb_bank') }.to raise_error(Plaid::NotFound, 'unable to find institution') }
|
18
|
-
end
|
19
|
-
end
|
@@ -1,28 +0,0 @@
|
|
1
|
-
describe Plaid::Transaction do
|
2
|
-
# API: semi-private
|
3
|
-
describe '.new' do
|
4
|
-
# The reason this looks weird is because it is. This will be refactored for 2.0
|
5
|
-
subject { Plaid::Transaction.new(results) }
|
6
|
-
|
7
|
-
def self.with_results(_results, &examples)
|
8
|
-
context "with results #{_results}" do
|
9
|
-
let(:results) { _results }
|
10
|
-
instance_eval(&examples)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
with_results('_id' => 'ID') do it { expect(subject.id).to eql('ID') } end
|
15
|
-
with_results('_account' => 'acct') do it { expect(subject.account).to eql('acct') } end
|
16
|
-
with_results('date' => '00/00/00') do it { expect(subject.date).to eql('00/00/00') } end
|
17
|
-
with_results('amount' => 100.00) do it { expect(subject.amount).to eql(100.00) } end
|
18
|
-
with_results('name' => 'Name') do it { expect(subject.name).to eql('Name') } end
|
19
|
-
with_results('meta' => {} ) do it { expect(subject.meta).to eql({}) } end
|
20
|
-
with_results('meta' => {'location' => 'Location'}) do it { expect(subject.location).to eql('Location') } end
|
21
|
-
with_results('pending' => true) do it { expect(subject.pending).to eql(true) } end
|
22
|
-
with_results('score' => 200) do it { expect(subject.score).to eql(200) } end
|
23
|
-
with_results('type' => 'Type') do it { expect(subject.type).to eql('Type') } end
|
24
|
-
|
25
|
-
with_results('category' => 'Category') do it { expect(subject.category).to eql('Category') } end
|
26
|
-
with_results('category_id' => 100) do it { expect(subject.category_id).to eql(100) } end
|
27
|
-
end
|
28
|
-
end
|
@@ -1,172 +0,0 @@
|
|
1
|
-
describe Plaid::User do
|
2
|
-
let(:auth_user) { Plaid.add_user('auth', 'plaid_test', 'plaid_good', 'wells') }
|
3
|
-
let(:connect_user) { Plaid.add_user('connect', 'plaid_test', 'plaid_good', 'wells') }
|
4
|
-
let(:info_user) { Plaid.add_user('info', 'plaid_test', 'plaid_good', 'wells') }
|
5
|
-
|
6
|
-
context 'user vars' do
|
7
|
-
context 'valid user has accounts and accounts contain id attribute' do
|
8
|
-
let(:user) { Plaid.add_user('connect', 'plaid_test', 'plaid_good', 'wells') }
|
9
|
-
it { expect(user.accounts.first.id).not_to be_nil }
|
10
|
-
end
|
11
|
-
|
12
|
-
context 'valid user has accounts and accounts contain type attribute' do
|
13
|
-
let(:user) { Plaid.add_user('connect', 'plaid_test', 'plaid_good', 'wells') }
|
14
|
-
it { expect(user.accounts.first.type).to eq('depository') }
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
# MFA specs - after user is instantiated,
|
19
|
-
describe '#mfa_authentication' do
|
20
|
-
let(:user) { Plaid.add_user('connect', 'plaid_test', 'plaid_good', 'bofa') }
|
21
|
-
let(:new_mfa_user) { user.mfa_authentication('tomato') }
|
22
|
-
|
23
|
-
context 'enters correct credentials for MFA auth and authenticates' do
|
24
|
-
it { expect(new_mfa_user.accounts).not_to be_empty }
|
25
|
-
end
|
26
|
-
|
27
|
-
context 'enters old method of adding type strongly in each method and authenticates correctly using 2FA' do
|
28
|
-
let(:new_mfa_user) { user.mfa_authentication('tomato', 'bofa') }
|
29
|
-
it { expect(new_mfa_user.accounts).to be_truthy }
|
30
|
-
end
|
31
|
-
|
32
|
-
context 'has to enter another round of MFA credentials' do
|
33
|
-
let(:mfa_again) { user.mfa_authentication('again') }
|
34
|
-
it { expect(mfa_again.api_res).to eq 'Requires further authentication' }
|
35
|
-
end
|
36
|
-
|
37
|
-
context 'enters incorrect credentials for MFA auth' do
|
38
|
-
let(:mfa_user) { user.mfa_authentication('tomato') }
|
39
|
-
let(:mfa_bad) { mfa_user; Plaid.add_user('connect', 'plaid_test', 'plaid_good', 'bofa') }
|
40
|
-
it { expect { mfa_bad.mfa_authentication('bad') }.to raise_error(Plaid::RequestFailed, 'invalid mfa') }
|
41
|
-
end
|
42
|
-
|
43
|
-
context 'requests list of MFA credentials' do
|
44
|
-
let(:new_mfa_user) { Plaid.add_user('auth', 'plaid_test', 'plaid_good', 'chase', nil, '{"list":true}') }
|
45
|
-
let(:expected_questions) do
|
46
|
-
{
|
47
|
-
"type"=>"list",
|
48
|
-
"mfa"=> [
|
49
|
-
{"mask"=>"xxx-xxx-5309", "type"=>"phone"},
|
50
|
-
{"mask"=>"t..t@plaid.com", "type"=>"email"}
|
51
|
-
],
|
52
|
-
"access_token"=>"test_chase"
|
53
|
-
}
|
54
|
-
end
|
55
|
-
it { expect(new_mfa_user.pending_mfa_questions).to eql(expected_questions) }
|
56
|
-
end
|
57
|
-
|
58
|
-
context 'selects MFA method and returns successful response' do
|
59
|
-
let(:user) { Plaid.add_user('auth', 'plaid_test', 'plaid_good', 'chase', nil, '{"list":true}') }
|
60
|
-
let(:new_mfa_user) { user.select_mfa_method({mask: 'xxx-xxx-5309' }, 'chase') }
|
61
|
-
let(:expected_pending_questions) do
|
62
|
-
{
|
63
|
-
"type" => "device",
|
64
|
-
"mfa" => { "message" => "Code sent to xxx-xxx-5309" },
|
65
|
-
"access_token" => "test_chase"
|
66
|
-
}
|
67
|
-
end
|
68
|
-
it { expect(new_mfa_user.pending_mfa_questions).to eql(expected_pending_questions) }
|
69
|
-
end
|
70
|
-
|
71
|
-
context 'selects MFA method, and delivers correct payload to authenticate user' do
|
72
|
-
let(:user) { Plaid.add_user('auth', 'plaid_test', 'plaid_good', 'chase', nil, '{"list":true}') }
|
73
|
-
let(:user_select_method) { user.select_mfa_method({mask:'xxx-xxx-5309'}) }
|
74
|
-
let(:new_mfa_user) { user_select_method.mfa_authentication(1234) }
|
75
|
-
|
76
|
-
it { expect(new_mfa_user.accounts).not_to be_empty }
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
context 'when authenticating' do
|
81
|
-
# Auth specs
|
82
|
-
describe '#get_auth' do
|
83
|
-
|
84
|
-
context 'has access and returns accounts' do
|
85
|
-
it { expect(auth_user.permissions[0]).to eq('auth') }
|
86
|
-
end
|
87
|
-
|
88
|
-
context 'does not have access to auth' do
|
89
|
-
it { expect(connect_user.permissions.include? 'auth' ).to eql(false) }
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
# Connect specs
|
94
|
-
describe '#get_connect' do
|
95
|
-
context 'has access and returns accounts' do
|
96
|
-
it { expect(connect_user.permissions[0]).to eq('connect') }
|
97
|
-
end
|
98
|
-
|
99
|
-
context 'does not have access to auth' do
|
100
|
-
it { expect(auth_user.permissions.include? 'connect' ).to eql(false) }
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
# Get info specs
|
105
|
-
describe '#get_info' do
|
106
|
-
context 'has access and returns user info' do
|
107
|
-
it { expect(info_user.permissions[0]).to eq('info') }
|
108
|
-
end
|
109
|
-
|
110
|
-
context 'does not have access to info' do
|
111
|
-
it{ expect(auth_user.permissions.include? 'info' ).to eql(false) }
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
describe '#get_balance' do
|
117
|
-
subject { user.tap(&:update_balance) }
|
118
|
-
let(:user) { Plaid.add_user('info', 'plaid_test', 'plaid_good', 'wells') }
|
119
|
-
|
120
|
-
context 'updates user accounts' do
|
121
|
-
it { expect(subject.accounts).not_to be_empty }
|
122
|
-
end
|
123
|
-
|
124
|
-
# TODO: This test needs to be rewritten better, such as using #uniq instead of this
|
125
|
-
context 'does not double up accounts or transactions' do
|
126
|
-
let(:total_duplicates) { duplicate_accounts.length + duplicate_transactions.length }
|
127
|
-
let(:duplicate_accounts) { subject.accounts.select {|element| user.accounts.count(element) > 1} }
|
128
|
-
let(:duplicate_transactions) { subject.transactions.select {|element| user.transactions.count(element) > 1} }
|
129
|
-
it{ expect(total_duplicates).to eql(0) }
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
describe '#update_info' do
|
134
|
-
let(:info_user) { Plaid.add_user('info', 'plaid_test', 'plaid_good', 'wells') }
|
135
|
-
context 'updates information correctly' do
|
136
|
-
# TODO: This test needs to pass, currently test credentials are failing
|
137
|
-
pending { expect { info_user.update_info('plaid_test', 'plaid_good') }.to_not raise_error }
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
describe '#delete_user' do
|
142
|
-
subject { info_user.tap(&:delete_user) }
|
143
|
-
let(:info_user) { Plaid.add_user('info', 'plaid_test', 'plaid_good', 'wells') }
|
144
|
-
|
145
|
-
context 'updates information correctly' do
|
146
|
-
it { expect { subject.get_info }.to raise_error(Plaid::Unauthorized, 'client_id missing') }
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
describe '#upgrade' do
|
151
|
-
subject { user.tap(&upgrade!) }
|
152
|
-
let(:upgrade!) { ->(x) { x.upgrade(upgrade_level) } }
|
153
|
-
let(:upgrade_level) { raise 'Define upgrade level' }
|
154
|
-
|
155
|
-
context 'auth upgrade is successful' do
|
156
|
-
let(:user) { connect_user }
|
157
|
-
let(:upgrade_level) { 'auth' }
|
158
|
-
it { expect{ subject.get_auth }.to_not raise_error }
|
159
|
-
end
|
160
|
-
|
161
|
-
context 'connect upgrade is successful' do
|
162
|
-
let(:user) { auth_user }
|
163
|
-
let(:upgrade_level) { 'connect' }
|
164
|
-
it { expect{ subject.get_connect }.to_not raise_error }
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
# This stuff needs to be tested and rewritten. Have already
|
169
|
-
# surfaced up a bug in it
|
170
|
-
pending '#populate_user'
|
171
|
-
|
172
|
-
end
|
data/spec/plaid_spec.rb
DELETED
@@ -1,263 +0,0 @@
|
|
1
|
-
# Authentication flow specs - returns Plaid::User
|
2
|
-
|
3
|
-
describe Plaid do
|
4
|
-
let(:api_level) { raise "Define let(:api_level)" }
|
5
|
-
let(:username) { raise "Define let(:username)" }
|
6
|
-
let(:password) { raise "Define let(:password)" }
|
7
|
-
let(:type) { raise "Define let(:type)" }
|
8
|
-
let(:pin) { nil }
|
9
|
-
let(:options) { nil }
|
10
|
-
|
11
|
-
describe '.add_user' do
|
12
|
-
let(:user) { Plaid.add_user api_level, username, password, type, pin, options }
|
13
|
-
|
14
|
-
context 'with correct credentials for single user auth' do
|
15
|
-
let(:username) { 'plaid_test' }
|
16
|
-
let(:password) { 'plaid_good' }
|
17
|
-
let(:type) { 'wells' }
|
18
|
-
|
19
|
-
context 'and "connect" level of api access' do
|
20
|
-
let(:api_level) { 'connect' }
|
21
|
-
|
22
|
-
it { expect(user.accounts).not_to be_empty }
|
23
|
-
|
24
|
-
context 'with webhook' do
|
25
|
-
let(:options) { { login_only: true, webhook: 'test.com/test.endpoint.aspx' } }
|
26
|
-
it { expect(user.accounts).not_to be_empty }
|
27
|
-
end
|
28
|
-
|
29
|
-
context 'when account is locked' do
|
30
|
-
let(:password) { 'plaid_locked' }
|
31
|
-
|
32
|
-
it 'raises a locked error' do
|
33
|
-
expect { user }.to raise_error(Plaid::RequestFailed) { |error|
|
34
|
-
expect(error.code).to eq(1205)
|
35
|
-
}
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
context 'with connection options' do
|
40
|
-
context 'when requests pending transactions from an institution' do
|
41
|
-
let(:options) { { pending: true } }
|
42
|
-
it { expect(user.accounts).not_to be_empty }
|
43
|
-
end
|
44
|
-
|
45
|
-
context 'when login only is true' do
|
46
|
-
let(:options) { { login_only: true } }
|
47
|
-
it { expect(user.accounts).not_to be_empty }
|
48
|
-
end
|
49
|
-
|
50
|
-
context 'sets a start date for transactions' do
|
51
|
-
let(:options) { { login_only: true, start_date: '10 days ago'} }
|
52
|
-
it { expect(user.accounts).not_to be_empty }
|
53
|
-
end
|
54
|
-
|
55
|
-
context 'sets an end date for transactions' do
|
56
|
-
let(:options) { { login_only: true, end_date: '10 days ago'} }
|
57
|
-
it { expect(user.accounts).not_to be_empty }
|
58
|
-
end
|
59
|
-
|
60
|
-
context 'sets start and end dates for transactions' do
|
61
|
-
let(:options) { { gte: "05/10/2014" , lte: "06/10/2014" } }
|
62
|
-
it { expect(user.transactions).not_to be_nil }
|
63
|
-
end
|
64
|
-
|
65
|
-
pending 'with JSON-encoded string for options'
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
context 'and "auth" level of api access' do
|
70
|
-
let(:api_level) { 'auth' }
|
71
|
-
it { expect(user.accounts.first.numbers).not_to be_empty }
|
72
|
-
end
|
73
|
-
|
74
|
-
context 'and "info" level of api access' do
|
75
|
-
let(:api_level) { 'info' }
|
76
|
-
it { expect(user.info).not_to be_empty }
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
context 'with incorrect credentials for single factor auth' do
|
81
|
-
# Set up correct credentials. Override with bad element
|
82
|
-
# within each context block
|
83
|
-
let(:username) { 'plaid_test' }
|
84
|
-
let(:password) { 'plaid_good' }
|
85
|
-
let(:type) { 'wells' }
|
86
|
-
|
87
|
-
context 'at "auth" level api access' do
|
88
|
-
let(:api_level) { 'auth' }
|
89
|
-
|
90
|
-
context 'using incorrect password' do
|
91
|
-
let(:password) { 'plaid_bad' }
|
92
|
-
it { expect { user }.to raise_error(Plaid::RequestFailed, 'invalid credentials') }
|
93
|
-
end
|
94
|
-
|
95
|
-
context 'using incorrect username' do
|
96
|
-
let(:username) { 'plaid_bad' }
|
97
|
-
it { expect { user }.to raise_error(Plaid::RequestFailed, 'invalid credentials') }
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
context 'at "connect" level api access' do
|
102
|
-
let(:api_level) { 'connect' }
|
103
|
-
|
104
|
-
context 'using incorrect password' do
|
105
|
-
let(:password) { 'plaid_bad' }
|
106
|
-
it { expect { user }.to raise_error(Plaid::RequestFailed, 'invalid credentials') }
|
107
|
-
end
|
108
|
-
|
109
|
-
context 'using incorrect username' do
|
110
|
-
let(:username) { 'plaid_bad' }
|
111
|
-
it { expect { user }.to raise_error(Plaid::RequestFailed, 'invalid credentials') }
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
context 'at "info" level api access' do
|
116
|
-
let(:api_level) { 'info' }
|
117
|
-
|
118
|
-
context 'using incorrect password' do
|
119
|
-
let(:password) { 'plaid_bad' }
|
120
|
-
it { expect { user }.to raise_error(Plaid::RequestFailed, 'invalid credentials') }
|
121
|
-
end
|
122
|
-
|
123
|
-
context 'using incorrect username' do
|
124
|
-
let(:username) { 'plaid_bad' }
|
125
|
-
it { expect { user }.to raise_error(Plaid::RequestFailed, 'invalid credentials') }
|
126
|
-
end
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
context 'when institution requires PIN' do
|
131
|
-
let(:api_level) { 'connect' }
|
132
|
-
let(:username) { 'plaid_test' }
|
133
|
-
let(:password) { 'plaid_good' }
|
134
|
-
let(:type) { 'usaa' }
|
135
|
-
|
136
|
-
context 'using correct PIN' do
|
137
|
-
let(:pin) { '1234' }
|
138
|
-
it { expect(user.api_res).to eq 'Requires further authentication' }
|
139
|
-
end
|
140
|
-
|
141
|
-
context 'using incorrect PIN' do
|
142
|
-
let(:pin) { '0000' }
|
143
|
-
it { expect { user }.to raise_error(Plaid::RequestFailed, 'invalid pin') }
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
context 'when institution requires MFA' do
|
148
|
-
let(:api_level) { 'connect' }
|
149
|
-
let(:username) { 'plaid_test' }
|
150
|
-
let(:password) { 'plaid_good' }
|
151
|
-
let(:type) { 'bofa' }
|
152
|
-
|
153
|
-
context 'with only standard credentials' do
|
154
|
-
it { expect(user.api_res).to eq 'Requires further authentication' }
|
155
|
-
end
|
156
|
-
|
157
|
-
context 'with options' do
|
158
|
-
context 'with webhook' do
|
159
|
-
let(:options) { { login_only: true, webhook: 'test.com/test.endpoint.aspx' } }
|
160
|
-
it { expect(user.api_res).to eq 'Requires further authentication' }
|
161
|
-
end
|
162
|
-
|
163
|
-
context 'requests a list of options for code based MFA' do
|
164
|
-
let(:type) { 'citi' }
|
165
|
-
let(:options) { { list: true } }
|
166
|
-
|
167
|
-
it { expect(user.pending_mfa_questions).not_to be_nil }
|
168
|
-
end
|
169
|
-
end
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
describe '.set_user' do
|
174
|
-
subject { Plaid.set_user(access_token) }
|
175
|
-
let(:access_token) { 'test' }
|
176
|
-
|
177
|
-
it { expect(subject.access_token).to eq(access_token)}
|
178
|
-
|
179
|
-
context 'gets a valid user with accounts and transactions' do
|
180
|
-
let(:user) { Plaid.set_user('test_wells',['connect']) }
|
181
|
-
it { expect(user.transactions).not_to be_empty }
|
182
|
-
end
|
183
|
-
|
184
|
-
context 'gets a valid user with accounts' do
|
185
|
-
let(:user) { Plaid.set_user('test_wells',['auth']) }
|
186
|
-
it { expect(user.accounts).not_to be_empty }
|
187
|
-
end
|
188
|
-
|
189
|
-
#TODO: Fully vet the info api endpoint for the beta functions before adding this as a supported function.
|
190
|
-
pending 'need to vet the info api endpoint' do
|
191
|
-
context 'gets a valid user with info' do
|
192
|
-
let(:user) { Plaid.set_user('test_wells',['info']) }
|
193
|
-
it { expect(user.accounts).to be_truthy}
|
194
|
-
end
|
195
|
-
|
196
|
-
context 'gets a fully validated user with all access granted' do
|
197
|
-
let(:user) { Plaid.set_user('test_wells', ['connect', 'info', 'auth']) }
|
198
|
-
it { expect(user.transactions).to be_truthy}
|
199
|
-
end
|
200
|
-
end
|
201
|
-
end
|
202
|
-
|
203
|
-
describe '.exchange_token' do
|
204
|
-
subject { Plaid.exchange_token('test,chase,connected', 'QPO8Jo8vdDHMepg41PBwckXm4KdK1yUdmXOwK') }
|
205
|
-
|
206
|
-
it { expect(subject.access_token).to eql('test_chase') }
|
207
|
-
end
|
208
|
-
|
209
|
-
describe '.transactions' do
|
210
|
-
subject { Plaid.transactions(access_token, options) }
|
211
|
-
let(:access_token) { 'test_wells' }
|
212
|
-
let(:options) { nil }
|
213
|
-
|
214
|
-
context 'without options' do
|
215
|
-
it 'returns all accounts' do
|
216
|
-
expect(subject.accounts).not_to be_empty
|
217
|
-
end
|
218
|
-
|
219
|
-
it 'returns all transactions' do
|
220
|
-
expect(subject.transactions).not_to be_empty
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
|
-
context 'when filtering by account' do
|
225
|
-
let(:options) { { account: account } }
|
226
|
-
let(:account) { 'QPO8Jo8vdDHMepg41PBwckXm4KdK1yUdmXOwK' }
|
227
|
-
|
228
|
-
it 'returns a subset of transactions' do
|
229
|
-
expect(subject.transactions.size).to eql(2)
|
230
|
-
end
|
231
|
-
|
232
|
-
it 'return only transactions from the requested account' do
|
233
|
-
expect(subject.transactions.map(&:account).uniq).to eql([account])
|
234
|
-
end
|
235
|
-
end
|
236
|
-
|
237
|
-
context 'when filtering by date' do
|
238
|
-
let(:options) { { gte: "2014-07-24", lte: "2014-07-25" } }
|
239
|
-
|
240
|
-
it 'returns a subset of transactions' do
|
241
|
-
expect(subject.transactions.size).to eql(1)
|
242
|
-
end
|
243
|
-
|
244
|
-
it 'return only transactions from the requested date range' do
|
245
|
-
expect(subject.transactions.map(&:date).uniq).to eql(['2014-07-24'])
|
246
|
-
end
|
247
|
-
end
|
248
|
-
|
249
|
-
context 'when filtering by account and date' do
|
250
|
-
let(:options) { { account: account , gte: "2014-07-24", lte: "2014-07-25" } }
|
251
|
-
let(:account) { 'XARE85EJqKsjxLp6XR8ocg8VakrkXpTXmRdOo' }
|
252
|
-
|
253
|
-
it 'returns a subset of transactions' do
|
254
|
-
expect(subject.transactions.size).to eql(1)
|
255
|
-
end
|
256
|
-
|
257
|
-
it 'returns only transactions from the requested account and date range' do
|
258
|
-
expect(subject.transactions.map(&:date).uniq).to eql(['2014-07-24'])
|
259
|
-
expect(subject.transactions.map(&:account).uniq).to eql([account])
|
260
|
-
end
|
261
|
-
end
|
262
|
-
end
|
263
|
-
end
|