nmi_direct_post 0.2.0

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.
@@ -0,0 +1,17 @@
1
+ require "logger"
2
+
3
+ module NmiDirectPost
4
+ class << self
5
+ def logger
6
+ @logger ||= defined?(::Rails.logger) ? Rails.logger : ::Logger.new(STDOUT)
7
+ end
8
+ def logger=(_)
9
+ raise ArgumentError, "NmiDirectPost logger must respond to :info and :debug" unless logger_responds(_)
10
+ @logger = _
11
+ end
12
+ private
13
+ def logger_responds(logger)
14
+ logger.respond_to?(:info) && logger.respond_to?(:debug)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,168 @@
1
+ require_relative 'base'
2
+ require_relative 'customer_vault'
3
+
4
+ module NmiDirectPost
5
+ class TransactionNotFoundError < StandardError; end
6
+
7
+ class TransactionNotSavedError < StandardError; end
8
+
9
+ class Transaction < Base
10
+ SAFE_PARAMS = [:customer_vault_id, :type, :amount]
11
+
12
+ attr_reader *SAFE_PARAMS
13
+ attr_reader :auth_code, :avs_response, :cvv_response, :order_id, :type, :dup_seconds, :condition
14
+ attr_reader :transaction_id
15
+
16
+ validates_presence_of :customer_vault_id, :amount, :unless => :'finding_by_transaction_id?', :message => "%{attribute} cannot be blank"
17
+ validates_presence_of :customer_vault, :unless => 'customer_vault_id.blank?', :message => "%{attribute} with the given customer_vault could not be found"
18
+ validates_inclusion_of :type, :in => ["sale", "auth", "capture", "void", "refund", "credit", "validate", "update", ""]
19
+ validates_exclusion_of :type, :in => ["validate", "auth", "capture", "void"], :if => :'customer_vault_is_checking?', :message => "%{value} is not a valid action for a customer vault that uses a checking account"
20
+ validates_numericality_of :amount, :equal_to => 0, :if => :'is_validate?', :message => "%{attribute} must be 0 when validating a credit card"
21
+ validates_numericality_of :amount, :greater_than => 0, :if => :'is_sale?', :message => "%{attribute} cannot be 0 for a sale"
22
+ validates_numericality_of :amount, :greater_than => 0, :if => :'is_auth?', :message => "%{attribute} cannot be 0 for an authorization"
23
+ validate :voidable_transaction?, :if => :is_void?
24
+ validate :persisted?, :if => :is_void?
25
+ validate :save_successful?, :unless => 'response_text.blank?'
26
+
27
+ def initialize(attributes)
28
+ super()
29
+ @type, @amount = attributes[:type].to_s, attributes[:amount].to_f
30
+ @transaction_id = attributes[:transaction_id].to_i if attributes[:transaction_id]
31
+ @customer_vault_id = attributes[:customer_vault_id].to_i if attributes[:customer_vault_id]
32
+ reload if (finding_by_transaction_id? && self.valid?)
33
+ @type, @amount = attributes[:type].to_s, attributes[:amount].to_f if ['void', 'capture'].include?(attributes[:type].to_s)
34
+ end
35
+
36
+ def save
37
+ void! if ('void' == type && condition.blank?)
38
+ return false if self.invalid?
39
+ _safe_params = safe_params
40
+ logger.info { "Sending Direct Post Transaction to NMI: #{_safe_params}" }
41
+ post([_safe_params, transaction_params].join('&'))
42
+ valid?.tap { |_| reload if _ }
43
+ end
44
+
45
+ def save!
46
+ save || raise(TransactionNotSavedError)
47
+ end
48
+
49
+ def self.find_by_transaction_id(transaction_id)
50
+ raise StandardError, "TransactionID cannot be blank" if transaction_id.blank?
51
+ NmiDirectPost.logger.debug { "Looking up NMI transaction by transaction_id(#{transaction_id})" }
52
+ begin
53
+ new(:transaction_id => transaction_id)
54
+ rescue TransactionNotFoundError
55
+ return nil
56
+ end
57
+ end
58
+
59
+ def pending?
60
+ 'pendingsettlement' == condition
61
+ end
62
+
63
+ def cleared?
64
+ "complete" == condition
65
+ end
66
+
67
+ def failed?
68
+ "failed" == condition
69
+ end
70
+
71
+ def declined?
72
+ 2 == response
73
+ end
74
+
75
+ def void!
76
+ @type='void'
77
+ if condition.blank?
78
+ return false if invalid?
79
+ reload
80
+ @type = 'void'
81
+ end
82
+ save
83
+ end
84
+
85
+ def customer_vault
86
+ @customer_vault ||= CustomerVault.find_by_customer_vault_id(@customer_vault_id) unless @customer_vault_id.blank?
87
+ end
88
+
89
+ def reload
90
+ get(transaction_params) if finding_by_transaction_id?
91
+ self
92
+ end
93
+
94
+ private
95
+ def safe_params
96
+ generate_query_string(SAFE_PARAMS)
97
+ end
98
+
99
+ def transaction_params
100
+ generate_query_string([AUTH_PARAMS, :transaction_id].flatten)
101
+ end
102
+
103
+ def get(query)
104
+ hash = self.class.get(query)["transaction"]
105
+ hash = hash.keep_if { |v| v['transaction_id'].to_s == self.transaction_id.to_s }.first if hash.is_a?(Array)
106
+ raise TransactionNotFoundError, "No transaction found for TransactionID #{@transaction_id}" if hash.nil?
107
+ @auth_code = hash["authorization_code"]
108
+ @customer_vault_id = hash["customerid"].to_i
109
+ @avs_response = hash["avs_response"]
110
+ @condition = hash["condition"]
111
+ action = hash["action"]
112
+ action = action.last unless action.is_a?(Hash)
113
+ @amount = action["amount"].to_f
114
+ @type = action["action_type"]
115
+ @response = action["success"].to_i if action.key?("success")
116
+ @response_code = action["response_code"].to_i if action.key?("response_code")
117
+ @response_text = action["response_text"]
118
+ end
119
+
120
+ def post(query)
121
+ response = self.class.post(query)
122
+ @response = response["response"].to_i if response.key?("response")
123
+ @response_code = response["response_code"].to_i if response.key?("response_code")
124
+ @response_text, @avs_response, @cvv_response = response["responsetext"], response["avsresponse"], response["cvvresponse"]
125
+ @dup_seconds, @order_id, @auth_code = response["dup_seconds"], response["orderid"], response["authcode"]
126
+ @transaction_id = response["transactionid"]
127
+ end
128
+
129
+ def customer_vault_is_checking?
130
+ !customer_vault.blank? && customer_vault.checking?
131
+ end
132
+
133
+ def finding_by_transaction_id?
134
+ !transaction_id.blank?
135
+ end
136
+
137
+ def is_validate?
138
+ !finding_by_transaction_id? && ('validate' == type.to_s)
139
+ end
140
+
141
+ def is_sale?
142
+ !finding_by_transaction_id? && (['sale', ''].include?(type.to_s))
143
+ end
144
+
145
+ def is_auth?
146
+ !finding_by_transaction_id? && ('auth' == type.to_s)
147
+ end
148
+
149
+ def is_void?
150
+ !customer_vault_is_checking? && ('void' == type.to_s)
151
+ end
152
+
153
+ def save_successful?
154
+ return if (success? || declined?)
155
+ self.errors.add(:response, response.to_s)
156
+ self.errors.add(:response_code, response_code.to_s)
157
+ self.errors.add(:response_text, response_text)
158
+ end
159
+
160
+ def voidable_transaction?
161
+ self.errors.add(:type, "Void is only a valid action for a pending or unsettled authorization, or an unsettled sale") if (finding_by_transaction_id? && !['pending', 'pendingsettlement'].include?(condition)) unless condition.blank?
162
+ end
163
+
164
+ def persisted?
165
+ self.errors.add(:type, "Void is only a valid action for a transaction that has already been sent to NMI") unless finding_by_transaction_id?
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,3 @@
1
+ module NmiDirectPost
2
+ VERSION = "0.2.0"
3
+ end
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'nmi_direct_post/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "nmi_direct_post"
8
+ spec.version = NmiDirectPost::VERSION
9
+ spec.authors = ["Isaac Betesh"]
10
+ spec.email = ["iybetesh@gmail.com"]
11
+ spec.description = %q{Gem that encapsulates the NMI Direct Post API in an ActiveRecord-like syntax}
12
+ spec.summary = `cat README.md`
13
+ spec.homepage = "https://github.com/betesh/nmi_direct_post"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", ">= 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec"
24
+ spec.add_development_dependency "rspec-rails"
25
+ spec.add_development_dependency "simplecov"
26
+
27
+ spec.add_dependency 'addressable'
28
+ spec.add_dependency 'activemodel'
29
+ spec.add_dependency 'activesupport', ' >= 3.0'
30
+ end
data/spec/base_spec.rb ADDED
@@ -0,0 +1,37 @@
1
+ require_relative 'spec_helper'
2
+
3
+ describe NmiDirectPost::Base do
4
+ def a_query
5
+ NmiDirectPost::CustomerVault.find_by_customer_vault_id(a_cc_customer_vault_id)
6
+ end
7
+ before(:each) do
8
+ NmiDirectPost::Base.establish_connection(nil, nil)
9
+ NmiDirectPost::CustomerVault.establish_connection(nil, nil)
10
+ end
11
+ let(:credentials) { TestCredentials::INSTANCE }
12
+ let(:a_cc_customer_vault_id) { credentials.cc_customer }
13
+ it "should raise exception when username is an empty string" do
14
+ NmiDirectPost::Base.establish_connection('', credentials.nmi_password)
15
+ expect{a_query}.to raise_error(StandardError, "Please set a username by calling NmiDirectPost::Base.establish_connection(ENV['NMI_USERNAME'], ENV['NMI_PASSWORD'])")
16
+ end
17
+ it "should raise exception when password is an empty string" do
18
+ NmiDirectPost::Base.establish_connection(credentials.nmi_username, nil)
19
+ expect{a_query}.to raise_error(StandardError, "Please set a username by calling NmiDirectPost::Base.establish_connection(ENV['NMI_USERNAME'], ENV['NMI_PASSWORD'])")
20
+ end
21
+ it "should raise exception when username is nil" do
22
+ NmiDirectPost::Base.establish_connection('', credentials.nmi_password)
23
+ expect{a_query}.to raise_error(StandardError, "Please set a username by calling NmiDirectPost::Base.establish_connection(ENV['NMI_USERNAME'], ENV['NMI_PASSWORD'])")
24
+ end
25
+ it "should raise exception when password is nil" do
26
+ NmiDirectPost::Base.establish_connection(credentials.nmi_username, nil)
27
+ expect{a_query}.to raise_error(StandardError, "Please set a username by calling NmiDirectPost::Base.establish_connection(ENV['NMI_USERNAME'], ENV['NMI_PASSWORD'])")
28
+ end
29
+ it "should find parent connection" do
30
+ NmiDirectPost::Base.establish_connection(credentials.nmi_username, credentials.nmi_password)
31
+ expect{a_query}.to_not raise_error
32
+ end
33
+ it "should find parent connection" do
34
+ NmiDirectPost::CustomerVault.establish_connection(credentials.nmi_username, credentials.nmi_password)
35
+ expect{a_query}.to_not raise_error
36
+ end
37
+ end
@@ -0,0 +1,243 @@
1
+ require_relative 'spec_helper'
2
+
3
+ describe NmiDirectPost::CustomerVault do
4
+ def get_new_email
5
+ "someone#{Random.rand(1..1000)}@example.com"
6
+ end
7
+
8
+ CV = NmiDirectPost::CustomerVault
9
+ let(:a_cc_customer_vault_id) { TestCredentials::INSTANCE.cc_customer }
10
+ let(:a_cc_customer) { CV.find_by_customer_vault_id(a_cc_customer_vault_id) }
11
+ let(:a_checking_account_customer_vault_id) { TestCredentials::INSTANCE.ach_customer }
12
+ let(:a_checking_account_customer) { CV.find_by_customer_vault_id(a_checking_account_customer_vault_id) }
13
+
14
+ before :all do
15
+ credentials = TestCredentials::INSTANCE
16
+ NmiDirectPost::Base.establish_connection(credentials.nmi_username, credentials.nmi_password)
17
+ end
18
+
19
+ describe "find_by_customer_vault_id" do
20
+ it "should find a customer vault" do
21
+ expect(a_cc_customer.customer_vault_id).to eq(a_cc_customer_vault_id)
22
+ expect(a_cc_customer.first_name).not_to be_nil
23
+ expect(a_cc_customer.last_name).not_to be_nil
24
+ expect(a_cc_customer.email).not_to be_nil
25
+ end
26
+
27
+ it "should raise exception when customer_vault_id is blank" do
28
+ expect{CV.find_by_customer_vault_id("")}.to raise_error(StandardError, "CustomerVaultID cannot be blank")
29
+ end
30
+
31
+ it "should return exception when no customer is found" do
32
+ expect(CV.find_by_customer_vault_id("123456")).to be_nil
33
+ end
34
+ end
35
+
36
+ describe "create" do
37
+ it "should not create a customer vault when no payment info is specified" do
38
+ new_email = get_new_email
39
+ @customer = CV.new(:first_name => "George", :last_name => "Washington")
40
+ expect(@customer.create).to eq(false)
41
+ expect(@customer.errors.full_messages).to eq(["Billing information Either :cc_number (a credit card number) and :cc_exp (the credit card expiration date), or :check_account, :check_aba (the routing number of the checking account) and :check_name (a nickname for the account), must be present"])
42
+ end
43
+
44
+ it "should not create a customer vault when a customer valut id is already present" do
45
+ new_email = get_new_email
46
+ @customer = CV.new(:first_name => "George", :last_name => "Washington", :cc_number => "4111111111111111", :cc_exp => "06/16", :customer_vault_id => a_cc_customer_vault_id)
47
+ expect(@customer.create).to eq(false)
48
+ expect(@customer.errors.full_messages).to eq(["Customer vault You cannot specify a Customer vault ID when creating a new customer vault. NMI will assign one upon creating the record"])
49
+ end
50
+
51
+ it "should create a customer vault with an automatically assigned customer_vault_id when a credit card number and expiration date are specified" do
52
+ new_email = get_new_email
53
+ @customer = CV.new(:first_name => "George", :last_name => "Washington", :cc_number => "4111111111111111", :cc_exp => "06/16")
54
+ expect(@customer.create).to eq(true)
55
+ expect(@customer.destroy).to be_success
56
+ expect(@customer.cc_exp).to eq("06/16")
57
+ end
58
+
59
+ it "should create a customer vault with an automatically assigned customer_vault_id when a checking account number and routing number are specified" do
60
+ new_email = get_new_email
61
+ @customer = CV.new(:first_name => "George", :last_name => "Washington", :check_aba => "123123123", :check_account => "123123123", :check_name => "my checking account")
62
+ expect(@customer.create).to eq(true)
63
+ expect(@customer.destroy).to be_success
64
+ end
65
+
66
+ [[:cc_number, :check_name], [:cc_number, :check_account], [:cc_number, :check_aba], [:cc_exp, :check_name], [:cc_exp, :check_account], [:cc_exp, :check_aba]].each do |attrs|
67
+ attributes = {:first_name => "George", :last_name => "Washington", :cc_number => "4111111111111111", :cc_exp => "06/16", :check_aba => "123123123", :check_account => "123123123", :check_name => "my checking account"}
68
+ attributes.delete(attrs.first)
69
+ attributes.delete(attrs.last)
70
+ it "should not create a customer vault when missing #{attrs.first} and #{attrs.last}" do
71
+ new_email = get_new_email
72
+ @customer = CV.new(attributes)
73
+ expect(@customer.create).to eq(false)
74
+ expect(@customer.errors.full_messages).to eq(["Billing information Either :cc_number (a credit card number) and :cc_exp (the credit card expiration date), or :check_account, :check_aba (the routing number of the checking account) and :check_name (a nickname for the account), must be present"])
75
+ end
76
+ end
77
+ end
78
+
79
+ describe "save" do
80
+ it "should update the customer vault with new shipping_email when shipping_email is set before calling save!" do
81
+ new_email = get_new_email
82
+ a_cc_customer.shipping_email = new_email
83
+ a_cc_customer.save!
84
+ expect(a_cc_customer.response_text).to eq("Customer Update Successful")
85
+ expect(a_cc_customer).to be_success
86
+ expect(a_cc_customer.shipping_email).to eq(new_email)
87
+ expect(a_cc_customer.reload.shipping_email).to eq(new_email)
88
+ end
89
+ end
90
+
91
+ describe "update" do
92
+ it "should update the customer vault with new merchant_defined_fields" do
93
+ new_field_1 = Random.rand(1..1000)
94
+ new_field_2 = Random.rand(1..1000)
95
+ a_cc_customer.update!(:merchant_defined_field_1 => new_field_1, :merchant_defined_field_2 => new_field_2)
96
+ expect(a_cc_customer.response_text).to eq("Customer Update Successful")
97
+ expect(a_cc_customer).to be_success
98
+ a_cc_customer.reload
99
+ expect(a_cc_customer.merchant_defined_field_1).to eq(new_field_1.to_s)
100
+ expect(a_cc_customer.merchant_defined_field_2).to eq(new_field_2.to_s)
101
+ end
102
+
103
+ it "should update the customer vault with new shipping_email when shipping_email is passed to update!" do
104
+ new_email = get_new_email
105
+ a_cc_customer.update!(:shipping_email => new_email)
106
+ expect(a_cc_customer.response_text).to eq("Customer Update Successful")
107
+ expect(a_cc_customer).to be_success
108
+ expect(a_cc_customer.shipping_email).to eq(new_email)
109
+ expect(a_cc_customer.reload.shipping_email).to eq(new_email)
110
+ end
111
+
112
+ it "should not update the customer vault with new shipping_email when shipping_email is set before calling update!" do
113
+ new_email = get_new_email
114
+ new_address = "#{Random.rand(1..1000)} Sesame Street"
115
+ old_email = a_cc_customer.shipping_email
116
+ a_cc_customer.shipping_email = new_email
117
+ a_cc_customer.update!(:shipping_address_1 => new_address)
118
+ expect(a_cc_customer.response_text).to eq("Customer Update Successful")
119
+ expect(a_cc_customer).to be_success
120
+ expect(a_cc_customer.shipping_email).to eq(new_email)
121
+ expect(a_cc_customer.reload.shipping_email).to eq(old_email)
122
+ end
123
+
124
+ it "should not allow updating the customer_vault_id" do
125
+ new_email = get_new_email
126
+ expect{a_cc_customer.update!(:customer_vault_id => '')}.to raise_error(NmiDirectPost::MassAssignmentSecurity::Error, "Cannot mass-assign the following attributes: customer_vault_id")
127
+ end
128
+
129
+ it "should not interfere with other set variables" do
130
+ new_email = get_new_email
131
+ new_address = "#{Random.rand(1..1000)} Sesame Street"
132
+ old_email = a_cc_customer.shipping_email
133
+ a_cc_customer.shipping_email = new_email
134
+ a_cc_customer.update!(:shipping_address_1 => new_address)
135
+ expect(a_cc_customer.response_text).to eq("Customer Update Successful")
136
+ expect(a_cc_customer).to be_success
137
+ expect(a_cc_customer.shipping_email).to eq(new_email)
138
+ a_cc_customer.save!
139
+ expect(a_cc_customer.reload.shipping_email).to eq(new_email)
140
+ end
141
+ end
142
+
143
+ describe "reload" do
144
+ it "should not reload if customer vault id is missing" do
145
+ @customer = CV.new({})
146
+ expect(@customer.customer_vault_id).to be_nil
147
+ @customer.reload
148
+ expect(@customer).not_to be_success
149
+ expect(@customer.response).to be_nil
150
+ expect(@customer.errors.full_messages).to eq(["Customer vault You must specify a Customer vault ID when looking up an individual customer vault"])
151
+ end
152
+ end
153
+
154
+ describe "first/last/all" do
155
+ before(:all) do
156
+ @all_ids = CV.all_ids
157
+ end
158
+ it "should get all ids" do
159
+ expect(@all_ids).to be_a(Array)
160
+ expect(@all_ids).to eq(@all_ids.uniq)
161
+ @all_ids.each do |id|
162
+ expect(id).to be_a(Fixnum)
163
+ end
164
+ end
165
+
166
+ it "should get the first customer vault" do
167
+ expected = CV.find_by_customer_vault_id(@all_ids.first)
168
+ first = CV.first
169
+ expect(first).to be_a(CV)
170
+ expect(first).to have_same_attributes_as(expected)
171
+ end
172
+
173
+ it "should get the last customer vault" do
174
+ expected = CV.find_by_customer_vault_id(@all_ids.last)
175
+ last = CV.last
176
+ expect(last).to be_a(CV)
177
+ expect(last).to have_same_attributes_as(expected)
178
+ end
179
+
180
+ it "should get all customer vaults" do
181
+ customers = CV.all
182
+ expect(customers.count).to eq(@all_ids.count)
183
+ customers.each do |customer|
184
+ expect(customer).to be_a(CV)
185
+ expect(customer.customer_vault_id).not_to be_nil
186
+ end
187
+ end
188
+ end
189
+
190
+ describe "cc_hash" do
191
+ it "should not be settable" do
192
+ expect(a_cc_customer.respond_to?('cc_hash=')).to eq(false)
193
+ end
194
+ it "should be a string on a CC customer" do
195
+ expect(a_cc_customer.cc_hash).to be_a(String)
196
+ end
197
+ it "should be nil on a checking customer" do
198
+ expect(a_checking_account_customer.cc_hash).to be_nil
199
+ end
200
+ it "should not be allowed in a mass assignment update" do
201
+ expect{a_cc_customer.update!(:cc_hash => 'abcdefg')}.to raise_error(NmiDirectPost::MassAssignmentSecurity::Error, 'Cannot mass-assign the following attributes: cc_hash')
202
+ end
203
+ it "should not be allowed when initialized" do
204
+ expect{CV.new(:first_name => "George", :last_name => "Washington", :cc_number => "4111111111111111", :cc_exp => "06/16", :cc_hash => 'abcdefg')}.to raise_error(NmiDirectPost::MassAssignmentSecurity::Error, 'Cannot mass-assign the following attributes: cc_hash')
205
+ end
206
+ end
207
+
208
+ describe "check_hash" do
209
+ it "should not be settable" do
210
+ expect(a_cc_customer.respond_to?('check_hash=')).to eq(false)
211
+ end
212
+ it "should be a string on a CC customer" do
213
+ expect(a_checking_account_customer.check_hash).to be_a(String)
214
+ end
215
+ it "should be nil on a checking customer" do
216
+ expect(a_cc_customer.check_hash).to be_nil
217
+ end
218
+ it "should not be allowed in a mass assignment update" do
219
+ expect{a_cc_customer.update!(:check_hash => 'abcdefg')}.to raise_error(NmiDirectPost::MassAssignmentSecurity::Error, 'Cannot mass-assign the following attributes: check_hash')
220
+ end
221
+ it "should not be allowed when initialized" do
222
+ expect{CV.new(:first_name => "George", :last_name => "Washington", :cc_number => "4111111111111111", :cc_exp => "06/16", :check_hash => 'abcdefg')}.to raise_error(NmiDirectPost::MassAssignmentSecurity::Error, 'Cannot mass-assign the following attributes: check_hash')
223
+ end
224
+ end
225
+
226
+ describe "checking?" do
227
+ it "should be true for a checking account customer" do
228
+ expect(a_checking_account_customer).to be_checking
229
+ end
230
+ it "should be false for a CC customer" do
231
+ expect(a_cc_customer).not_to be_checking
232
+ end
233
+ end
234
+
235
+ describe "credit_card?" do
236
+ it "should be true for a CC customer" do
237
+ expect(a_cc_customer).to be_credit_card
238
+ end
239
+ it "should be false for a checking account customer" do
240
+ expect(a_checking_account_customer).not_to be_credit_card
241
+ end
242
+ end
243
+ end