plaid 1.7.1 → 2.0.0.alpha
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/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
|