plaid 1.4.3 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/plaid.rb CHANGED
@@ -1,54 +1,96 @@
1
1
  require 'plaid/version'
2
2
  require 'plaid/config'
3
- require 'plaid/util'
4
3
 
5
- require 'plaid/add_user'
6
- require 'plaid/user/user'
7
- require 'plaid/institution/institution'
8
- require 'plaid/category/category'
4
+ require 'plaid/models/user'
5
+ require 'plaid/models/institution'
6
+ require 'plaid/models/category'
7
+ require 'plaid/models/exchange_token_response'
8
+
9
+ require 'json'
9
10
 
10
11
  module Plaid
12
+ autoload :Connection, 'plaid/connection'
13
+
11
14
  class << self
12
15
  # Configures the gem with the public, private, and environment vars
13
- include Plaid::Configure
16
+ include Configure
17
+
18
+ # API: public
19
+ # Use this to create a new Plaid user
20
+ # Required parameters:
21
+ # api_level, username, password, type
22
+ # TODO: Rename this to something more descriptive for 2.0, such as 'create_user`
23
+ def add_user(api_level, username, password, type, pin = nil, options = nil)
24
+ payload = { username: username, password: password, type: type }
14
25
 
15
- # Include the utility classes used throughout the gem
16
- include Plaid::Util
26
+ payload[:pin] = pin if pin
27
+ payload[:options] = options.is_a?(Hash) ? JSON.generate(options) : options if options
17
28
 
18
- # Includes the method to authenticate the user. Defined in auth.rb
19
- include Plaid::AddUser
29
+ res = Connection.post(api_level, payload)
30
+ User.build(res, api_level)
31
+ end
32
+
33
+ # API: public
34
+ # Exchange a Plaid Link public_token for a Plaid access_token
35
+ # Required parameters:
36
+ # public_token
37
+ def exchange_token(public_token)
38
+ payload = { public_token: public_token }
20
39
 
21
- # Builds the user object and returns on successful authentication
22
- def user(res,api_level=nil)
23
- @user = Plaid::User.new
24
- @user.new(res,api_level)
40
+ res = Connection.post('exchange_token', payload)
41
+ ExchangeTokenResponse.new(res)
25
42
  end
26
43
 
27
- def existing_user(token,api_level=[],type=nil)
28
- @user = Plaid::User.new
29
- @user.access_token = token
30
- api_level.each { |i|
31
- @user.permissions << i
32
- @user.get_auth if i == 'auth'
33
- @user.get_connect if i == 'connect'
34
- @user.get_info if i == 'info'
35
- } unless api_level.empty?
36
- @user
44
+ # API: public
45
+ # Use this to restore a user from Plaid based upon the access token
46
+ # TODO: Rename this to something more descriptive for 2.0, such as 'get_user'
47
+ def set_user(token, api_levels=[], institution_type=nil)
48
+ _user = User.new
49
+ _user.access_token = fully_qualified_token(token, institution_type)
50
+ _user.permissions = api_levels
51
+ api_levels.each { |l| _user.get(l) }
52
+ return _user
37
53
  end
38
54
 
39
- # Builds an institution object and returns when the institution details exist
40
- def institution(id=nil)
41
- @institution = Plaid::Institution.new
42
- res = self.get('institutions',id)
43
- id.nil? ? @institution.instantiate_all_institutions(res) : @institution.instantiate_one_institution(res)
55
+ # API: public
56
+ # Given an access code and query options, use this to get a dataset of
57
+ # transactions and accounts for # a given user. See /connect/get endpoint
58
+ #
59
+ # Returns a User object with accounts and transactions within
60
+ # the date range given
61
+ # Examples:
62
+ # Plaid.transactions 'test_wells', account: 'QPO8Jo8vdDHMepg41PBwckXm4KdK1yUdmXOwK'
63
+ def transactions(token, options = {})
64
+ _user = User.new
65
+ _user.access_token = token
66
+ _user.permit! 'connect'
67
+
68
+ # TODO: For 2.0, submit all data as JSON
69
+ options = JSON.generate(options) if options.kind_of?(Hash)
70
+
71
+ _user.get_connect(options: options)
72
+ return _user
73
+ end
74
+
75
+ # API: public
76
+ # Returns the fully-qualified token based upon type
77
+ # Note: Don't see this documented in the Plaid API docs, need to investigate this
78
+ def fully_qualified_token(token, institution_type)
79
+ institution_type.nil? ? token : token + '_' + institution_type
44
80
  end
45
81
 
46
- # Builds an institution object and returns when the category details exist
47
- def category(id=nil)
48
- @category = Plaid::Category.new
49
- res = self.get('categories',id)
50
- id.nil? ? @category.instantiate_all_categories(res) : @category.instantiate_one_category(res)
82
+ # API: public
83
+ # Builds an institution object and returns when the institution details exist
84
+ def institution(id = nil)
85
+ res = Connection.get('institutions', id)
86
+ id.nil? ? Institution.all(res) : Institution.new(res)
51
87
  end
52
88
 
89
+ # API: public
90
+ # Builds an category object and returns when the category details exist
91
+ def category(id = nil)
92
+ res = Connection.get('categories', id)
93
+ id.nil? ? Category.all(res) : Category.new(res)
94
+ end
53
95
  end
54
- end
96
+ end
data/plaid.gemspec CHANGED
@@ -21,4 +21,6 @@ Gem::Specification.new do |spec|
21
21
  spec.add_development_dependency 'bundler', '~> 1.7'
22
22
  spec.add_development_dependency 'rake', '~> 10.0'
23
23
  spec.add_development_dependency 'rspec', '~>3.1'
24
- end
24
+ spec.add_development_dependency 'pry'
25
+ spec.add_development_dependency 'pry-stack_explorer'
26
+ end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper.rb'
2
+
3
+ RSpec.describe Plaid::Account do
4
+ # API: semi-private
5
+ describe '.new' do
6
+ subject { Plaid::Account.new(results) }
7
+
8
+ def self.with_results(_results, &examples)
9
+ context "with results #{_results}" do
10
+ let(:results) { _results }
11
+ instance_eval(&examples)
12
+ end
13
+ end
14
+
15
+ with_results('name' => 'Name') do it { expect(subject.name).to eql('Name') } end
16
+ with_results('_id' => 'ID') do it { expect(subject.id).to eql('ID') } end
17
+ with_results('type' => 'Type') do it { expect(subject.type).to eql('Type') } end
18
+ with_results('type' => 'STyp') do it { expect(subject.type).to eql('STyp') } end
19
+ with_results('meta' => nil) do it { expect(subject.meta).to be_nil } end
20
+ with_results('meta' => {}) do it { expect(subject.meta).to eql({}) } end
21
+
22
+ with_results('balance' => { 'available' => 100.00 } ) do it { expect(subject.available_balance).to eql(100.00) } end
23
+ with_results('balance' => { 'current' => 200.00 } ) do it { expect(subject.current_balance).to eql(200.00) } end
24
+
25
+ with_results('institution_type' => 'Type') do it { expect(subject.institution_type).to eql('Type') } end
26
+
27
+ with_results('numbers' => nil) do
28
+ it { expect(subject.numbers).to eql('Upgrade user to access routing information for this account') }
29
+ end
30
+
31
+ with_results('numbers' => {}) do
32
+ it { expect(subject.numbers).to eql({}) }
33
+ end
34
+ end
35
+ end
@@ -1,22 +1,13 @@
1
1
  require 'spec_helper.rb'
2
- # Category specs
3
- describe '#Category' do
4
-
5
- before :all do
6
- Plaid.config do |p|
7
- p.customer_id = 'test_id'
8
- p.secret = 'test_secret'
9
- p.environment_location = 'https://tartan.plaid.com/'
10
- end
11
- end
12
2
 
3
+ RSpec.describe Plaid::Category do
13
4
  context 'when a single category is found' do
14
- category = Plaid.category('17001013')
15
- it { expect(category.class).to eq (Plaid::Category) }
5
+ let(:category) { Plaid.category('17001013') }
6
+ it { expect(category).to be_kind_of(Plaid::Category) }
16
7
  end
17
8
 
18
9
  context 'when all categories are found' do
19
- category = Plaid.category
10
+ let(:category) { Plaid.category }
20
11
  it { expect(category).to be_kind_of(Array)}
21
12
  end
22
13
 
@@ -24,4 +15,4 @@ describe '#Category' do
24
15
  it { expect { Plaid.category('dumb_cat') }.to raise_error }
25
16
  end
26
17
 
27
- end
18
+ end
data/spec/config_spec.rb CHANGED
@@ -1,40 +1,69 @@
1
- # Configuration specs - used in gem configuration
2
- describe '.config' do
3
- context 'has valid dev keys' do
1
+ require 'spec_helper.rb'
2
+
3
+ RSpec.describe 'Plaid.config' do
4
+ around(:each) do |example|
5
+ old_customer_id = Plaid.customer_id
6
+ old_secret = Plaid.secret
7
+ old_environment_location = Plaid.environment_location
8
+
4
9
  Plaid.config do |p|
5
- p.customer_id = 'test_id'
6
- p.secret = 'test_secret'
7
- p.environment_location = 'https://tartan.plaid.com/'
10
+ p.customer_id = customer_id
11
+ p.secret = secret
12
+ p.environment_location = environment_location
8
13
  end
9
- res = Plaid.add_user('connect','plaid_test','plaid_good','wells')
10
- it { expect(res).to be_instance_of Plaid::User }
11
- end
12
14
 
13
- context 'has valid production keys' do
15
+ example.run
16
+
14
17
  Plaid.config do |p|
15
- p.customer_id = 'test_id'
16
- p.secret = 'test_secret'
17
- p.environment_location = 'https://api.plaid.com/'
18
+ p.customer_id = old_customer_id
19
+ p.secret = old_secret
20
+ p.environment_location = old_environment_location
18
21
  end
19
- res = Plaid.add_user('connect','plaid_test','plaid_good','wells')
20
- it { expect(res).to be_instance_of Plaid::User }
21
22
  end
22
23
 
23
- context 'has invalid dev keys' do
24
- Plaid.config do |p|
25
- p.customer_id = 'test_id'
26
- p.secret = 'test_bad'
27
- p.environment_location = 'https://tartan.plaid.com/'
24
+ let(:customer_id) { 'test_id' }
25
+ let(:secret) { 'test_secret' }
26
+ let(:dev_url) { 'https://tartan.plaid.com/' }
27
+ let(:prod_url) { 'https://api.plaid.com/' }
28
+
29
+
30
+ let(:user) { Plaid.add_user('connect','plaid_test','plaid_good','wells') }
31
+
32
+ context ':environment_location' do
33
+ context 'with trailing slash' do
34
+ let(:environment_location) { 'http://example.org/' }
35
+ it 'should leave it as-is' do
36
+ expect(Plaid.environment_location).to eql(environment_location)
37
+ end
38
+ end
39
+
40
+ context 'without trailing slash' do
41
+ let(:environment_location) { 'http://example.org' }
42
+ it 'should add a trailing slash' do
43
+ expect(Plaid.environment_location).to eql(environment_location + '/')
44
+ end
28
45
  end
29
- it { expect{Plaid.add_user('connect','plaid_bad','plaid_bad','wells')}.to raise_error }
46
+ end
47
+
48
+ context 'has valid dev keys' do
49
+ let(:environment_location) { dev_url }
50
+ it { expect(user).to be_instance_of Plaid::User }
51
+ end
52
+
53
+ context 'has valid production keys' do
54
+ let(:environment_location) { prod_url }
55
+ it { expect(user).to be_instance_of Plaid::User }
56
+ end
57
+
58
+ context 'has invalid dev keys' do
59
+ let(:secret) { 'test_bad' }
60
+ let(:environment_location) { dev_url }
61
+ it { expect { user }.to raise_error }
30
62
  end
31
63
 
32
64
  context 'has invalid production keys' do
33
- Plaid.config do |p|
34
- p.customer_id = 'test_id'
35
- p.secret = 'test_bad'
36
- p.environment_location = 'https://api.plaid.com/'
37
- end
38
- it { expect{Plaid.add_user('connect','plaid_bad','plaid_bad','wells')}.to raise_error }
65
+ let(:secret) { 'test_bad' }
66
+ let(:environment_location) { prod_url }
67
+ it { expect { user }.to raise_error }
39
68
  end
40
- end
69
+ end
@@ -1,25 +1,17 @@
1
- # Institution specs
2
- describe '#Institution' do
3
-
4
- before :all do
5
- Plaid.config do |p|
6
- p.customer_id = 'test_id'
7
- p.secret = 'test_secret'
8
- p.environment_location = 'https://tartan.plaid.com/'
9
- end
10
- end
1
+ require 'spec_helper.rb'
11
2
 
3
+ RSpec.describe Plaid::Institution do
12
4
  context 'when a single institution is found' do
13
- institution = Plaid.institution('5301a93ac140de84910000e0')
14
- it { expect(institution.class).to eq(Plaid::Institution) }
5
+ let(:institution) { Plaid.institution('5301a93ac140de84910000e0') }
6
+ it { expect(institution).to be_kind_of(Plaid::Institution) }
15
7
  end
16
8
 
17
9
  context 'when all institutions are found' do
18
- institution = Plaid.institution
10
+ let(:institution) { Plaid.institution }
19
11
  it { expect(institution).to be_kind_of(Array) }
20
12
  end
21
13
 
22
14
  context 'when institution is not found' do
23
15
  it { expect { Plaid.institution('dumb_bank') }.to raise_error }
24
16
  end
25
- end
17
+ end
@@ -0,0 +1,258 @@
1
+ require 'spec_helper.rb'
2
+ # Authentication flow specs - returns Plaid::User
3
+ RSpec.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
+ it { expect(user.api_res).to eq 'User account is locked' }
32
+ end
33
+
34
+ context 'with connection options' do
35
+ context 'when requests pending transactions from an institution' do
36
+ let(:options) { { pending: true } }
37
+ it { expect(user.accounts).not_to be_empty }
38
+ end
39
+
40
+ context 'when login only is true' do
41
+ let(:options) { { login_only: true } }
42
+ it { expect(user.accounts).not_to be_empty }
43
+ end
44
+
45
+ context 'sets a start date for transactions' do
46
+ let(:options) { { login_only: true, start_date: '10 days ago'} }
47
+ it { expect(user.accounts).not_to be_empty }
48
+ end
49
+
50
+ context 'sets an end date for transactions' do
51
+ let(:options) { { login_only: true, end_date: '10 days ago'} }
52
+ it { expect(user.accounts).not_to be_empty }
53
+ end
54
+
55
+ context 'sets start and end dates for transactions' do
56
+ let(:options) { { gte: "05/10/2014" , lte: "06/10/2014" } }
57
+ it { expect(user.transactions).not_to be_nil }
58
+ end
59
+
60
+ pending 'with JSON-encoded string for options'
61
+ end
62
+ end
63
+
64
+ context 'and "auth" level of api access' do
65
+ let(:api_level) { 'auth' }
66
+ it { expect(user.accounts.first.numbers).not_to be_empty }
67
+ end
68
+
69
+ context 'and "info" level of api access' do
70
+ let(:api_level) { 'info' }
71
+ it { expect(user.info).not_to be_empty }
72
+ end
73
+ end
74
+
75
+ context 'with incorrect credentials for single factor auth' do
76
+ # Set up correct credentials. Override with bad element
77
+ # within each context block
78
+ let(:username) { 'plaid_test' }
79
+ let(:password) { 'plaid_good' }
80
+ let(:type) { 'wells' }
81
+
82
+ context 'at "auth" level api access' do
83
+ let(:api_level) { 'auth' }
84
+
85
+ context 'using incorrect password' do
86
+ let(:password) { 'plaid_bad' }
87
+ it { expect { user }.to raise_error }
88
+ end
89
+
90
+ context 'using incorrect username' do
91
+ let(:username) { 'plaid_bad' }
92
+ it { expect { user }.to raise_error }
93
+ end
94
+ end
95
+
96
+ context 'at "connect" level api access' do
97
+ let(:api_level) { 'connect' }
98
+
99
+ context 'using incorrect password' do
100
+ let(:password) { 'plaid_bad' }
101
+ it { expect { user }.to raise_error }
102
+ end
103
+
104
+ context 'using incorrect username' do
105
+ let(:username) { 'plaid_bad' }
106
+ it { expect { user }.to raise_error }
107
+ end
108
+ end
109
+
110
+ context 'at "info" level api access' do
111
+ let(:api_level) { 'info' }
112
+
113
+ context 'using incorrect password' do
114
+ let(:password) { 'plaid_bad' }
115
+ it { expect { user }.to raise_error }
116
+ end
117
+
118
+ context 'using incorrect username' do
119
+ let(:username) { 'plaid_bad' }
120
+ it { expect { user }.to raise_error }
121
+ end
122
+ end
123
+ end
124
+
125
+ context 'when institution requires PIN' do
126
+ let(:api_level) { 'connect' }
127
+ let(:username) { 'plaid_test' }
128
+ let(:password) { 'plaid_good' }
129
+ let(:type) { 'usaa' }
130
+
131
+ context 'using correct PIN' do
132
+ let(:pin) { '1234' }
133
+ it { expect(user.api_res).to eq 'Requires further authentication' }
134
+ end
135
+
136
+ context 'using incorrect PIN' do
137
+ let(:pin) { '0000' }
138
+ it { expect { user }.to raise_error }
139
+ end
140
+ end
141
+
142
+ context 'when institution requires MFA' do
143
+ let(:api_level) { 'connect' }
144
+ let(:username) { 'plaid_test' }
145
+ let(:password) { 'plaid_good' }
146
+ let(:type) { 'bofa' }
147
+
148
+ context 'with only standard credentials' do
149
+ it { expect(user.api_res).to eq 'Requires further authentication' }
150
+ end
151
+
152
+ context 'with options' do
153
+ context 'with webhook' do
154
+ let(:options) { { login_only: true, webhook: 'test.com/test.endpoint.aspx' } }
155
+ it { expect(user.api_res).to eq 'Requires further authentication' }
156
+ end
157
+
158
+ context 'requests a list of options for code based MFA' do
159
+ let(:type) { 'citi' }
160
+ let(:options) { { list: true } }
161
+
162
+ it { expect(user.pending_mfa_questions).not_to be_nil }
163
+ end
164
+ end
165
+ end
166
+ end
167
+
168
+ describe '.set_user' do
169
+ subject { Plaid.set_user(access_token) }
170
+ let(:access_token) { 'test' }
171
+
172
+ it { expect(subject.access_token).to eq(access_token)}
173
+
174
+ context 'gets a valid user with accounts and transactions' do
175
+ let(:user) { Plaid.set_user('test_wells',['connect']) }
176
+ it { expect(user.transactions).not_to be_empty }
177
+ end
178
+
179
+ context 'gets a valid user with accounts' do
180
+ let(:user) { Plaid.set_user('test_wells',['auth']) }
181
+ it { expect(user.accounts).not_to be_empty }
182
+ end
183
+
184
+ #TODO: Fully vet the info api endpoint for the beta functions before adding this as a supported function.
185
+ pending 'need to vet the info api endpoint' do
186
+ context 'gets a valid user with info' do
187
+ let(:user) { Plaid.set_user('test_wells',['info']) }
188
+ it { expect(user.accounts).to be_truthy}
189
+ end
190
+
191
+ context 'gets a fully validated user with all access granted' do
192
+ let(:user) { Plaid.set_user('test_wells',['connect','info','auth']) }
193
+ it { expect(user.transactions).to be_truthy}
194
+ end
195
+ end
196
+ end
197
+
198
+ describe '.exchange_token' do
199
+ subject { Plaid.exchange_token('test,chase,connected') }
200
+
201
+ it { expect(subject.access_token).to eql('test_chase') }
202
+ end
203
+
204
+ describe '.transactions' do
205
+ subject { Plaid.transactions(access_token, options) }
206
+ let(:access_token) { 'test_wells' }
207
+ let(:options) { nil }
208
+
209
+ context 'without options' do
210
+ it 'should return all accounts' do
211
+ expect(subject.accounts).not_to be_empty
212
+ end
213
+
214
+ it 'should return all transactions' do
215
+ expect(subject.transactions).not_to be_empty
216
+ end
217
+ end
218
+
219
+ context 'when filering by account' do
220
+ let(:options) { { account: account } }
221
+ let(:account) { 'QPO8Jo8vdDHMepg41PBwckXm4KdK1yUdmXOwK' }
222
+
223
+ it 'should return a subset of transactions' do
224
+ expect(subject.transactions.size).to eql(2)
225
+ end
226
+
227
+ it 'should only return transactions from the requested account' do
228
+ expect(subject.transactions.map(&:account).uniq).to eql([account])
229
+ end
230
+ end
231
+
232
+ context 'when filtering by date' do
233
+ let(:options) { { gte: "2014-07-24", lte: "2014-07-25" } }
234
+
235
+ it 'should return a subset of transactions' do
236
+ expect(subject.transactions.size).to eql(1)
237
+ end
238
+
239
+ it 'should only return transactions from the requested date range' do
240
+ expect(subject.transactions.map(&:date).uniq).to eql(['2014-07-24'])
241
+ end
242
+ end
243
+
244
+ context 'when filtering by account and date' do
245
+ let(:options) { { account: account , gte: "2014-07-24", lte: "2014-07-25" } }
246
+ let(:account) { 'XARE85EJqKsjxLp6XR8ocg8VakrkXpTXmRdOo' }
247
+
248
+ it 'should return a subset of transactions' do
249
+ expect(subject.transactions.size).to eql(1)
250
+ end
251
+
252
+ it 'should only return transactions from the requested account and date range' do
253
+ expect(subject.transactions.map(&:date).uniq).to eql(['2014-07-24'])
254
+ expect(subject.transactions.map(&:account).uniq).to eql([account])
255
+ end
256
+ end
257
+ end
258
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,4 +1,11 @@
1
1
  require 'bundler/setup'
2
2
  Bundler.setup
3
3
 
4
- require 'plaid'
4
+ require 'plaid'
5
+ require 'pry' if ENV['DEBUG']
6
+
7
+ Plaid.config do |p|
8
+ p.customer_id = 'test_id'
9
+ p.secret = 'test_secret'
10
+ p.environment_location = 'https://tartan.plaid.com/'
11
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper.rb'
2
+
3
+ RSpec.describe Plaid::Transaction do
4
+ # API: semi-private
5
+ describe '.new' do
6
+ # The reason this looks weird is because it is. This will be refactored for 2.0
7
+ subject { Plaid::Transaction.new(results) }
8
+
9
+ def self.with_results(_results, &examples)
10
+ context "with results #{_results}" do
11
+ let(:results) { _results }
12
+ instance_eval(&examples)
13
+ end
14
+ end
15
+
16
+ with_results('_id' => 'ID') do it { expect(subject.id).to eql('ID') } end
17
+ with_results('_account' => 'acct') do it { expect(subject.account).to eql('acct') } end
18
+ with_results('date' => '00/00/00') do it { expect(subject.date).to eql('00/00/00') } end
19
+ with_results('amount' => 100.00) do it { expect(subject.amount).to eql(100.00) } end
20
+ with_results('name' => 'Name') do it { expect(subject.name).to eql('Name') } end
21
+ with_results('meta' => {} ) do it { expect(subject.meta).to eql({}) } end
22
+ with_results('meta' => {'location' => 'Location'}) do it { expect(subject.location).to eql('Location') } end
23
+ with_results('pending' => true) do it { expect(subject.pending).to eql(true) } end
24
+ with_results('score' => 200) do it { expect(subject.score).to eql(200) } end
25
+ with_results('type' => 'Type') do it { expect(subject.type).to eql('Type') } end
26
+
27
+ with_results('category' => 'Category') do it { expect(subject.category).to eql('Category') } end
28
+ with_results('category_id' => 100) do it { expect(subject.category_id).to eql(100) } end
29
+ end
30
+ end