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.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.rspec +1 -0
- data/.simplecov +4 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +83 -0
- data/Rakefile +1 -0
- data/lib/nmi_direct_post.rb +7 -0
- data/lib/nmi_direct_post/base.rb +102 -0
- data/lib/nmi_direct_post/customer_vault.rb +245 -0
- data/lib/nmi_direct_post/logger.rb +17 -0
- data/lib/nmi_direct_post/transaction.rb +168 -0
- data/lib/nmi_direct_post/version.rb +3 -0
- data/nmi_direct_post.gemspec +30 -0
- data/spec/base_spec.rb +37 -0
- data/spec/customer_vault_spec.rb +243 -0
- data/spec/logger_spec.rb +77 -0
- data/spec/spec_helper.rb +17 -0
- data/spec/support/credentials.rb.example +13 -0
- data/spec/support/test_credentials.rb +11 -0
- data/spec/transaction_spec.rb +303 -0
- metadata +217 -0
@@ -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,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
|