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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +3 -0
  3. data/CONTRIBUTING.md +15 -0
  4. data/LICENSE +20 -0
  5. data/README.md +215 -63
  6. data/Rakefile +50 -4
  7. data/UPGRADING.md +45 -0
  8. data/bin/console +13 -0
  9. data/bin/setup +8 -0
  10. data/lib/plaid.rb +51 -88
  11. data/lib/plaid/account.rb +144 -0
  12. data/lib/plaid/category.rb +62 -0
  13. data/lib/plaid/client.rb +67 -0
  14. data/lib/plaid/connector.rb +168 -0
  15. data/lib/plaid/errors.rb +24 -14
  16. data/lib/plaid/income.rb +106 -0
  17. data/lib/plaid/info.rb +65 -0
  18. data/lib/plaid/institution.rb +240 -0
  19. data/lib/plaid/risk.rb +34 -0
  20. data/lib/plaid/transaction.rb +123 -0
  21. data/lib/plaid/user.rb +430 -0
  22. data/lib/plaid/version.rb +1 -1
  23. data/plaid.gemspec +20 -12
  24. metadata +58 -62
  25. data/.gitignore +0 -15
  26. data/.rspec +0 -2
  27. data/.travis.yml +0 -5
  28. data/LICENSE.txt +0 -22
  29. data/PUBLISHING.md +0 -21
  30. data/lib/plaid/config.rb +0 -19
  31. data/lib/plaid/connection.rb +0 -109
  32. data/lib/plaid/models/account.rb +0 -24
  33. data/lib/plaid/models/category.rb +0 -17
  34. data/lib/plaid/models/exchange_token_response.rb +0 -11
  35. data/lib/plaid/models/info.rb +0 -12
  36. data/lib/plaid/models/institution.rb +0 -22
  37. data/lib/plaid/models/transaction.rb +0 -24
  38. data/lib/plaid/models/user.rb +0 -189
  39. data/spec/plaid/config_spec.rb +0 -67
  40. data/spec/plaid/connection_spec.rb +0 -191
  41. data/spec/plaid/error_spec.rb +0 -10
  42. data/spec/plaid/models/account_spec.rb +0 -37
  43. data/spec/plaid/models/category_spec.rb +0 -16
  44. data/spec/plaid/models/institution_spec.rb +0 -19
  45. data/spec/plaid/models/transaction_spec.rb +0 -28
  46. data/spec/plaid/models/user_spec.rb +0 -172
  47. data/spec/plaid_spec.rb +0 -263
  48. data/spec/spec_helper.rb +0 -14
@@ -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