spree_gateway 2.2.1 → 3.0.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 +4 -4
- data/.travis.yml +5 -17
- data/Gemfile +1 -1
- data/README.md +9 -3
- data/app/models/spree/billing_integration.rb +21 -0
- data/app/models/spree/gateway/authorize_net.rb +31 -1
- data/app/models/spree/gateway/authorize_net_cim.rb +128 -47
- data/app/models/spree/gateway/balanced_gateway.rb +3 -5
- data/app/models/spree/gateway/braintree_gateway.rb +55 -18
- data/app/models/spree/gateway/cyber_source.rb +10 -0
- data/app/models/spree/gateway/migs.rb +11 -0
- data/app/models/spree/gateway/payflow_pro.rb +1 -0
- data/app/models/spree/gateway/pin_gateway.rb +45 -0
- data/app/models/spree/gateway/spreedly_core_gateway.rb +10 -0
- data/app/models/spree/gateway/stripe_gateway.rb +29 -6
- data/app/models/spree/gateway/usa_epay_transaction.rb +9 -0
- data/config/routes.rb +1 -1
- data/db/migrate/20111118164631_create_skrill_transactions.rb +1 -2
- data/lib/assets/javascripts/spree/frontend/spree_gateway.js +1 -0
- data/{app → lib}/assets/stylesheets/spree/frontend/spree_gateway.css +0 -0
- data/{app/controllers → lib/controllers/frontend}/spree/checkout_controller_decorator.rb +1 -1
- data/{app/controllers → lib/controllers/frontend}/spree/skrill_status_controller.rb +0 -0
- data/lib/spree_gateway.rb +1 -1
- data/lib/spree_gateway/engine.rb +56 -25
- data/{app/views → lib/views/backend}/spree/admin/log_entries/_braintree.html.erb +0 -0
- data/{app/views → lib/views/backend}/spree/admin/log_entries/_stripe.html.erb +0 -0
- data/{app/views → lib/views/backend}/spree/admin/payments/source_forms/_quickcheckout.html.erb +0 -0
- data/lib/views/backend/spree/admin/payments/source_forms/_stripe.html.erb +1 -0
- data/{app/views → lib/views/backend}/spree/admin/payments/source_views/_quickcheckout.html.erb +0 -0
- data/{app/views → lib/views/backend}/spree/admin/payments/source_views/_stripe.html.erb +0 -0
- data/{app/views → lib/views/frontend}/spree/checkout/payment/_quickcheckout.html.erb +2 -2
- data/lib/views/frontend/spree/checkout/payment/_stripe.html.erb +90 -0
- data/spec/factories/payment_method_factory.rb +0 -1
- data/spec/features/stripe_checkout_spec.rb +15 -4
- data/spec/models/gateway/authorize_net_cim_spec.rb +6 -6
- data/spec/models/gateway/authorize_net_spec.rb +6 -6
- data/spec/models/gateway/balanced_gateway_spec.rb +1 -1
- data/spec/models/gateway/beanstream_spec.rb +1 -1
- data/spec/models/gateway/braintree_gateway_spec.rb +147 -31
- data/spec/models/gateway/cyber_source_spec.rb +11 -0
- data/spec/models/gateway/eway_spec.rb +3 -3
- data/spec/models/gateway/maxipago_spec.rb +1 -1
- data/spec/models/gateway/pay_junction_spec.rb +2 -2
- data/spec/models/gateway/payflow_pro_spec.rb +2 -2
- data/spec/models/gateway/pin_gateway_spec.rb +4 -6
- data/spec/models/gateway/stripe_gateway_spec.rb +90 -9
- data/spec/models/gateway/{usa_epay_spec.rb → usa_epay_transaction_spec.rb} +9 -9
- data/spec/spec_helper.rb +5 -2
- data/spree_gateway.gemspec +15 -16
- metadata +89 -98
- data/Versionfile +0 -7
- data/app/assets/javascripts/spree/frontend/spree_gateway.js +0 -3
- data/app/assets/javascripts/store/gateway/stripe.js.coffee +0 -58
- data/app/assets/javascripts/store/spree_gateway.js +0 -2
- data/app/models/spree/gateway/fatzebra.rb +0 -15
- data/app/models/spree/gateway/linkpoint.rb +0 -28
- data/app/models/spree/gateway/samurai.rb +0 -63
- data/app/models/spree/gateway/usa_epay.rb +0 -9
- data/app/views/spree/admin/payments/source_forms/_stripe.html.erb +0 -1
- data/app/views/spree/checkout/payment/_stripe.html.erb +0 -21
- data/config/initializers/savon.rb +0 -3
- data/spec/models/gateway/fatzebra_spec.rb +0 -51
- data/spec/models/gateway/linkpoint_spec.rb +0 -62
- data/spec/models/gateway/samurai_spec.rb +0 -17
- data/spec/models/savon_spec.rb +0 -9
@@ -6,10 +6,55 @@ module Spree
|
|
6
6
|
def provider_class
|
7
7
|
ActiveMerchant::Billing::PinGateway
|
8
8
|
end
|
9
|
+
|
10
|
+
def purchase(money, creditcard, options = {})
|
11
|
+
super(money, creditcard.try(:gateway_customer_profile_id) || creditcard.try(:gateway_payment_profile_id) || creditcard, options)
|
12
|
+
end
|
13
|
+
|
14
|
+
def create_profile(payment)
|
15
|
+
if payment.source.gateway_customer_profile_id.nil?
|
16
|
+
response = provider.store(payment.source, options_for_payment(payment))
|
17
|
+
|
18
|
+
if response.success?
|
19
|
+
payment.source.update_attributes!(:gateway_customer_profile_id => response.authorization)
|
20
|
+
|
21
|
+
cc = response.params['response']['card']
|
22
|
+
payment.source.update_attributes!(:gateway_payment_profile_id => cc['token']) if cc
|
23
|
+
else
|
24
|
+
payment.send(:gateway_error, response.message)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
9
28
|
|
10
29
|
# Pin does not appear to support authorizing transactions yet
|
11
30
|
def auto_capture?
|
12
31
|
true
|
13
32
|
end
|
33
|
+
|
34
|
+
def payment_profiles_supported?
|
35
|
+
true
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def options_for_payment(p)
|
41
|
+
o = Hash.new
|
42
|
+
o[:email] = p.order.email
|
43
|
+
|
44
|
+
if p.order.bill_address
|
45
|
+
bill_addr = p.order.bill_address
|
46
|
+
|
47
|
+
o[:billing_address] = {
|
48
|
+
address1: bill_addr.address1,
|
49
|
+
city: bill_addr.city,
|
50
|
+
state: bill_addr.state ? bill_addr.state.name : bill_addr.state_name,
|
51
|
+
country: bill_addr.country.iso3,
|
52
|
+
zip: bill_addr.zipcode
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
return o
|
57
|
+
end
|
58
|
+
|
14
59
|
end
|
15
60
|
end
|
@@ -3,6 +3,12 @@ module Spree
|
|
3
3
|
preference :secret_key, :string
|
4
4
|
preference :publishable_key, :string
|
5
5
|
|
6
|
+
CARD_TYPE_MAPPING = {
|
7
|
+
'American Express' => 'american_express',
|
8
|
+
'Diners Club' => 'diners_club',
|
9
|
+
'Visa' => 'visa'
|
10
|
+
}
|
11
|
+
|
6
12
|
def method_type
|
7
13
|
'stripe'
|
8
14
|
end
|
@@ -23,8 +29,8 @@ module Spree
|
|
23
29
|
provider.authorize(*options_for_purchase_or_auth(money, creditcard, gateway_options))
|
24
30
|
end
|
25
31
|
|
26
|
-
def capture(
|
27
|
-
provider.capture(
|
32
|
+
def capture(money, response_code, gateway_options)
|
33
|
+
provider.capture(money, response_code, gateway_options)
|
28
34
|
end
|
29
35
|
|
30
36
|
def credit(money, creditcard, response_code, gateway_options)
|
@@ -35,6 +41,10 @@ module Spree
|
|
35
41
|
provider.void(response_code, {})
|
36
42
|
end
|
37
43
|
|
44
|
+
def cancel(response_code)
|
45
|
+
provider.void(response_code, {})
|
46
|
+
end
|
47
|
+
|
38
48
|
def create_profile(payment)
|
39
49
|
return unless payment.source.gateway_customer_profile_id.nil?
|
40
50
|
options = {
|
@@ -42,12 +52,21 @@ module Spree
|
|
42
52
|
login: preferred_secret_key,
|
43
53
|
}.merge! address_for(payment)
|
44
54
|
|
45
|
-
|
55
|
+
source = update_source!(payment.source)
|
56
|
+
if source.number.blank? && source.gateway_payment_profile_id.present?
|
57
|
+
creditcard = source.gateway_payment_profile_id
|
58
|
+
else
|
59
|
+
creditcard = source
|
60
|
+
end
|
61
|
+
|
62
|
+
response = provider.store(creditcard, options)
|
46
63
|
if response.success?
|
47
64
|
payment.source.update_attributes!({
|
48
|
-
:
|
49
|
-
:
|
65
|
+
cc_type: payment.source.cc_type, # side-effect of update_source!
|
66
|
+
gateway_customer_profile_id: response.params['id'],
|
67
|
+
gateway_payment_profile_id: response.params['default_source'] || response.params['default_card']
|
50
68
|
})
|
69
|
+
|
51
70
|
else
|
52
71
|
payment.send(:gateway_error, response.message)
|
53
72
|
end
|
@@ -61,7 +80,6 @@ module Spree
|
|
61
80
|
options.merge(:login => preferred_secret_key)
|
62
81
|
end
|
63
82
|
|
64
|
-
|
65
83
|
def options_for_purchase_or_auth(money, creditcard, gateway_options)
|
66
84
|
options = {}
|
67
85
|
options[:description] = "Spree Order ID: #{gateway_options[:order_id]}"
|
@@ -99,5 +117,10 @@ module Spree
|
|
99
117
|
end
|
100
118
|
end
|
101
119
|
end
|
120
|
+
|
121
|
+
def update_source!(source)
|
122
|
+
source.cc_type = CARD_TYPE_MAPPING[source.cc_type] if CARD_TYPE_MAPPING.include?(source.cc_type)
|
123
|
+
source
|
124
|
+
end
|
102
125
|
end
|
103
126
|
end
|
data/config/routes.rb
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
//= require spree/frontend
|
File without changes
|
@@ -38,7 +38,7 @@ module Spree
|
|
38
38
|
|
39
39
|
private
|
40
40
|
def confirm_skrill
|
41
|
-
return unless (params[:state] == "payment") && params[:order][:payments_attributes]
|
41
|
+
return unless (params[:state] == "payment") && params[:order] && params[:order][:payments_attributes]
|
42
42
|
|
43
43
|
payment_method = PaymentMethod.find(params[:order][:payments_attributes].first[:payment_method_id])
|
44
44
|
if payment_method.kind_of?(BillingIntegration::Skrill::QuickCheckout)
|
File without changes
|
data/lib/spree_gateway.rb
CHANGED
data/lib/spree_gateway/engine.rb
CHANGED
@@ -5,31 +5,62 @@ module SpreeGateway
|
|
5
5
|
config.autoload_paths += %W(#{config.root}/lib)
|
6
6
|
|
7
7
|
initializer "spree.gateway.payment_methods", :after => "spree.register.payment_methods" do |app|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
8
|
+
app.config.spree.payment_methods << Spree::BillingIntegration::Skrill::QuickCheckout
|
9
|
+
app.config.spree.payment_methods << Spree::Gateway::AuthorizeNet
|
10
|
+
app.config.spree.payment_methods << Spree::Gateway::AuthorizeNetCim
|
11
|
+
app.config.spree.payment_methods << Spree::Gateway::BalancedGateway
|
12
|
+
app.config.spree.payment_methods << Spree::Gateway::Banwire
|
13
|
+
app.config.spree.payment_methods << Spree::Gateway::Beanstream
|
14
|
+
app.config.spree.payment_methods << Spree::Gateway::BraintreeGateway
|
15
|
+
app.config.spree.payment_methods << Spree::Gateway::CardSave
|
16
|
+
app.config.spree.payment_methods << Spree::Gateway::CyberSource
|
17
|
+
app.config.spree.payment_methods << Spree::Gateway::DataCash
|
18
|
+
app.config.spree.payment_methods << Spree::Gateway::Eway
|
19
|
+
app.config.spree.payment_methods << Spree::Gateway::Maxipago
|
20
|
+
app.config.spree.payment_methods << Spree::Gateway::Migs
|
21
|
+
app.config.spree.payment_methods << Spree::Gateway::Moneris
|
22
|
+
app.config.spree.payment_methods << Spree::Gateway::PayJunction
|
23
|
+
app.config.spree.payment_methods << Spree::Gateway::PayPalGateway
|
24
|
+
app.config.spree.payment_methods << Spree::Gateway::PayflowPro
|
25
|
+
app.config.spree.payment_methods << Spree::Gateway::Paymill
|
26
|
+
app.config.spree.payment_methods << Spree::Gateway::PinGateway
|
27
|
+
app.config.spree.payment_methods << Spree::Gateway::SagePay
|
28
|
+
app.config.spree.payment_methods << Spree::Gateway::SecurePayAU
|
29
|
+
app.config.spree.payment_methods << Spree::Gateway::SpreedlyCoreGateway
|
30
|
+
app.config.spree.payment_methods << Spree::Gateway::StripeGateway
|
31
|
+
app.config.spree.payment_methods << Spree::Gateway::UsaEpayTransaction
|
32
|
+
app.config.spree.payment_methods << Spree::Gateway::Worldpay
|
33
33
|
end
|
34
|
+
|
35
|
+
def self.activate
|
36
|
+
if SpreeGateway::Engine.frontend_available?
|
37
|
+
Rails.application.config.assets.precompile += [
|
38
|
+
'lib/assets/javascripts/spree/frontend/spree_gateway.js',
|
39
|
+
'lib/assets/javascripts/spree/frontend/spree_gateway.css',
|
40
|
+
]
|
41
|
+
Dir.glob(File.join(File.dirname(__FILE__), "../../controllers/frontend/*/*_decorator*.rb")) do |c|
|
42
|
+
Rails.configuration.cache_classes ? require(c) : load(c)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.backend_available?
|
48
|
+
@@backend_available ||= ::Rails::Engine.subclasses.map(&:instance).map{ |e| e.class.to_s }.include?('Spree::Backend::Engine')
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.frontend_available?
|
52
|
+
@@frontend_available ||= ::Rails::Engine.subclasses.map(&:instance).map{ |e| e.class.to_s }.include?('Spree::Frontend::Engine')
|
53
|
+
end
|
54
|
+
|
55
|
+
if self.backend_available?
|
56
|
+
paths["app/views"] << "lib/views/backend"
|
57
|
+
end
|
58
|
+
|
59
|
+
if self.frontend_available?
|
60
|
+
paths["app/controllers"] << "lib/controllers/frontend"
|
61
|
+
paths["app/views"] << "lib/views/frontend"
|
62
|
+
end
|
63
|
+
|
64
|
+
config.to_prepare &method(:activate).to_proc
|
34
65
|
end
|
35
66
|
end
|
File without changes
|
File without changes
|
data/{app/views → lib/views/backend}/spree/admin/payments/source_forms/_quickcheckout.html.erb
RENAMED
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render "spree/admin/payments/source_forms/gateway", payment_method: payment_method, previous_cards: payment_method.reusable_sources(@order) %>
|
data/{app/views → lib/views/backend}/spree/admin/payments/source_views/_quickcheckout.html.erb
RENAMED
File without changes
|
File without changes
|
@@ -4,9 +4,9 @@
|
|
4
4
|
opts = {}
|
5
5
|
opts[:transaction_id] = "#{@order.number}"
|
6
6
|
opts[:amount] = @order.total
|
7
|
-
opts[:return_url] = skrill_return_order_checkout_url(@order, :token => @order.
|
7
|
+
opts[:return_url] = skrill_return_order_checkout_url(@order, :token => @order.guest_token,
|
8
8
|
:payment_method_id => payment_method.id)
|
9
|
-
opts[:cancel_url] = skrill_cancel_order_checkout_url(@order, :token => @order.
|
9
|
+
opts[:cancel_url] = skrill_cancel_order_checkout_url(@order, :token => @order.guest_token)
|
10
10
|
opts[:status_url] = skrill_url
|
11
11
|
opts[:payment_method_id] = payment_method.id
|
12
12
|
%>
|
@@ -0,0 +1,90 @@
|
|
1
|
+
<%= render "spree/checkout/payment/gateway", payment_method: payment_method %>
|
2
|
+
|
3
|
+
<script type="text/javascript" src="https://js.stripe.com/v2/"></script>
|
4
|
+
<script type="text/javascript">
|
5
|
+
Stripe.setPublishableKey("<%= payment_method.preferred_publishable_key %>");
|
6
|
+
</script>
|
7
|
+
|
8
|
+
<script>
|
9
|
+
Spree.stripePaymentMethod = $('#payment_method_' + <%= payment_method.id %>);
|
10
|
+
|
11
|
+
var mapCC, stripeResponseHandler;
|
12
|
+
|
13
|
+
mapCC = function(ccType) {
|
14
|
+
if (ccType === 'MasterCard') {
|
15
|
+
return 'mastercard';
|
16
|
+
} else if (ccType === 'Visa') {
|
17
|
+
return 'visa';
|
18
|
+
} else if (ccType === 'American Express') {
|
19
|
+
return 'amex';
|
20
|
+
} else if (ccType === 'Discover') {
|
21
|
+
return 'discover';
|
22
|
+
} else if (ccType === 'Diners Club') {
|
23
|
+
return 'dinersclub';
|
24
|
+
} else if (ccType === 'JCB') {
|
25
|
+
return 'jcb';
|
26
|
+
}
|
27
|
+
};
|
28
|
+
|
29
|
+
stripeResponseHandler = function(status, response) {
|
30
|
+
var paymentMethodId, token;
|
31
|
+
if (response.error) {
|
32
|
+
$('#stripeError').html(response.error.message);
|
33
|
+
var param_map = {
|
34
|
+
number: '#card_number',
|
35
|
+
exp_month: '#card_expiry',
|
36
|
+
exp_year: '#card_expiry',
|
37
|
+
cvc: '#card_code'
|
38
|
+
}
|
39
|
+
if (response.error.param)
|
40
|
+
Spree.stripePaymentMethod.find(param_map[response.error.param]).addClass('error');
|
41
|
+
|
42
|
+
return $('#stripeError').show();
|
43
|
+
} else {
|
44
|
+
Spree.stripePaymentMethod.find('#card_number, #card_expiry, #card_code').prop("disabled", true);
|
45
|
+
Spree.stripePaymentMethod.find(".ccType").prop("disabled", false);
|
46
|
+
Spree.stripePaymentMethod.find(".ccType").val(mapCC(response.card.brand));
|
47
|
+
token = response['id'];
|
48
|
+
paymentMethodId = Spree.stripePaymentMethod.prop('id').split("_")[2];
|
49
|
+
Spree.stripePaymentMethod.append("<input type='hidden' class='stripeToken' name='payment_source[" + paymentMethodId + "][gateway_payment_profile_id]' value='" + token + "'/>");
|
50
|
+
Spree.stripePaymentMethod.append("<input type='hidden' class='stripeToken' name='payment_source[" + paymentMethodId + "][last_digits]' value='" + response.card.last4 + "'/>");
|
51
|
+
Spree.stripePaymentMethod.append("<input type='hidden' class='stripeToken' name='payment_source[" + paymentMethodId + "][month]' value='" + response.card.exp_month + "'/>");
|
52
|
+
Spree.stripePaymentMethod.append("<input type='hidden' class='stripeToken' name='payment_source[" + paymentMethodId + "][year]' value='" + response.card.exp_year + "'/>");
|
53
|
+
return Spree.stripePaymentMethod.parents("form").trigger('submit');
|
54
|
+
}
|
55
|
+
};
|
56
|
+
|
57
|
+
$(document).ready(function() {
|
58
|
+
Spree.stripePaymentMethod.prepend("<div id='stripeError' class='errorExplanation' style='display:none'></div>");
|
59
|
+
return $('#checkout_form_payment [data-hook=buttons]').click(function() {
|
60
|
+
var expiration, params;
|
61
|
+
$('#stripeError').hide();
|
62
|
+
Spree.stripePaymentMethod.find('#card_number, #card_expiry, #card_code').removeClass('error');
|
63
|
+
if (Spree.stripePaymentMethod.is(':visible')) {
|
64
|
+
expiration = $('.cardExpiry:visible').payment('cardExpiryVal');
|
65
|
+
params = $.extend({
|
66
|
+
number: $('.cardNumber:visible').val(),
|
67
|
+
cvc: $('.cardCode:visible').val(),
|
68
|
+
exp_month: expiration.month || 0,
|
69
|
+
exp_year: expiration.year || 0
|
70
|
+
}, Spree.stripeAdditionalInfo);
|
71
|
+
Stripe.card.createToken(params, stripeResponseHandler);
|
72
|
+
return false;
|
73
|
+
}
|
74
|
+
});
|
75
|
+
});
|
76
|
+
</script>
|
77
|
+
|
78
|
+
<%- if @order.has_checkout_step?('address') -%>
|
79
|
+
<script>
|
80
|
+
Spree.stripeAdditionalInfo = {
|
81
|
+
name: "<%= @order.bill_address.full_name %>",
|
82
|
+
address_line1: "<%= @order.bill_address.address1 %>",
|
83
|
+
address_line2: "<%= @order.bill_address.address2 %>",
|
84
|
+
address_city: "<%= @order.bill_address.city %>",
|
85
|
+
address_state: "<%= @order.bill_address.state_text %>",
|
86
|
+
address_zip: "<%= @order.bill_address.zipcode %>",
|
87
|
+
address_country: "<%= @order.bill_address.country %>"
|
88
|
+
}
|
89
|
+
</script>
|
90
|
+
<%- end -%>
|
@@ -10,8 +10,7 @@ describe "Stripe checkout" do
|
|
10
10
|
Spree::Gateway::StripeGateway.create!(
|
11
11
|
:name => "Stripe",
|
12
12
|
:preferred_secret_key => "sk_test_VCZnDv3GLU15TRvn8i2EsaAN",
|
13
|
-
:preferred_publishable_key => "pk_test_Cuf0PNtiAkkMpTVC2gwYDMIg"
|
14
|
-
:environment => "test"
|
13
|
+
:preferred_publishable_key => "pk_test_Cuf0PNtiAkkMpTVC2gwYDMIg"
|
15
14
|
)
|
16
15
|
end
|
17
16
|
|
@@ -63,6 +62,7 @@ describe "Stripe checkout" do
|
|
63
62
|
it "shows an error with an invalid credit card number", :js => true do
|
64
63
|
click_button "Save and Continue"
|
65
64
|
page.should have_content("This card number looks invalid")
|
65
|
+
page.should have_css('#card_number.error')
|
66
66
|
end
|
67
67
|
|
68
68
|
it "shows an error with invalid security fields", :js => true do
|
@@ -70,13 +70,24 @@ describe "Stripe checkout" do
|
|
70
70
|
fill_in "Expiration", :with => "01 / #{Time.now.year + 1}"
|
71
71
|
click_button "Save and Continue"
|
72
72
|
page.should have_content("Your card's security code is invalid.")
|
73
|
+
page.should have_css('#card_code.error')
|
73
74
|
end
|
74
75
|
|
75
|
-
it "shows an error with invalid expiry
|
76
|
+
it "shows an error with invalid expiry month field", :js => true do
|
76
77
|
fill_in "Card Number", :with => "4242 4242 4242 4242"
|
77
78
|
fill_in "Expiration", :with => "00 / #{Time.now.year + 1}"
|
78
79
|
fill_in "Card Code", :with => "123"
|
79
80
|
click_button "Save and Continue"
|
80
81
|
page.should have_content("Your card's expiration month is invalid.")
|
82
|
+
page.should have_css('#card_expiry.error')
|
81
83
|
end
|
82
|
-
|
84
|
+
|
85
|
+
it "shows an error with invalid expiry year field", :js => true do
|
86
|
+
fill_in "Card Number", :with => "4242 4242 4242 4242"
|
87
|
+
fill_in "Expiration", :with => "12 / "
|
88
|
+
fill_in "Card Code", :with => "123"
|
89
|
+
click_button "Save and Continue"
|
90
|
+
page.should have_content("Your card's expiration year is invalid.")
|
91
|
+
page.should have_css('#card_expiry.error')
|
92
|
+
end
|
93
|
+
end
|