# frozen_string_literal: true require 'spec_helper' RSpec.describe Spree::CreditCardsController do describe "using VCR", :vcr, :stripe_version do let(:user) { create(:user) } before do allow(controller).to receive(:spree_current_user) { user } end describe "#new_from_token" do let!(:token) do Stripe::Token.create({ card: { number: '4242424242424242', exp_month: 9, exp_year: 1.year.from_now.year, cvc: '314', }, }) end context "when the request to store the customer/card with Stripe is successful" do let(:params) do { format: :json, exp_month: 9, exp_year: 1.year.from_now.year, last4: 4242, token: token['id'], cc_type: "visa" } end it "saves the card locally" do expect { spree_post :new_from_token, params }.to change { Spree::CreditCard.count }.from(0).to(1) card = Spree::CreditCard.last # retrieves the created card from Stripe stripe_card = Stripe::Customer.list_sources( card.gateway_customer_profile_id, { object: 'card', limit: 1 }, ) payment_profile = stripe_card['data'][0]['id'] customer_profile = stripe_card['data'][0]['customer'] expect(card.gateway_payment_profile_id).to eq payment_profile expect(card.gateway_customer_profile_id).to eq customer_profile expect(card.user_id).to eq user.id expect(card.last_digits).to eq "4242" end end end end describe "not using VCR" do let(:user) { create(:user) } let(:token) { "tok_234bd2c22" } before do Stripe.api_key = "sk_test_12345" allow(controller).to receive(:spree_current_user) { user } end describe "#new_from_token" do let(:params) do { format: :json, exp_month: 12, exp_year: Time.zone.now.year.next, last4: 4242, token:, cc_type: "visa" } end before do stub_request(:post, "https://api.stripe.com/v1/customers") .with(body: { email: user.email, source: token }) .to_return(response_mock) end context "when the request to store the customer/card with Stripe fails" do let(:response_mock) { { status: 402, body: JSON.generate(error: { message: "Bup-bow..." }) } } it "doesn't save the card locally, and renders a flash error" do expect{ spree_post :new_from_token, params }.not_to change { Spree::CreditCard.count } json_response = response.parsed_body flash_message = "There was a problem with your payment information: %s" % 'Bup-bow...' expect(json_response["flash"]["error"]).to eq flash_message end end end describe "#update card to be the default card" do let(:params) { { format: :json, credit_card: { is_default: true } } } context "when the specified credit card is not found" do before { params[:id] = 123 } it "renders a flash error" do spree_put :update, params json_response = response.parsed_body expect(json_response['flash']['error']).to eq 'Card could not be updated' end end context "when the specified credit card is found" do let!(:card) { create(:credit_card, gateway_customer_profile_id: 'cus_AZNMJ') } before { params[:id] = card.id } context "but the card is not owned by the user" do it "redirects to unauthorized" do spree_put :update, params expect(response).to redirect_to unauthorized_path end end context "and the card is owned by the user" do before { card.update_attribute(:user_id, user.id) } context "when the update completes successfully" do it "renders a serialized copy of the updated card" do expect{ spree_put :update, params }.to change { card.reload.is_default }.to(true) json_response = response.parsed_body expect(json_response['id']).to eq card.id expect(json_response['is_default']).to eq true end end context "when the update fails" do before { params[:credit_card][:month] = 'some illegal month' } it "renders an error" do spree_put :update, params json_response = response.parsed_body expect(json_response['flash']['error']).to eq 'Card could not be updated' end end context "and there are existing authorizations for the user" do let!(:customer1) { create(:customer, allow_charges: true) } let!(:customer2) { create(:customer, allow_charges: true) } it "removes the authorizations" do customer1.user = card.user customer2.user = card.user customer1.save customer2.save expect(customer1.reload.allow_charges).to be true expect(customer2.reload.allow_charges).to be true spree_put :update, params expect(customer1.reload.allow_charges).to be false expect(customer2.reload.allow_charges).to be false end end end end end describe "#destroy" do context "when the specified credit card is not found" do let(:params) { { id: 123 } } it "redirects to /account with a flash error, does not request deletion with Stripe" do expect(controller).not_to receive(:destroy_at_stripe) spree_delete :destroy, params expect(flash[:error]).to eq 'Sorry, the card could not be removed' expect(response).to have_http_status :ok end end context "when the specified credit card is found" do let!(:card) { create(:credit_card, gateway_customer_profile_id: 'cus_AZNMJ') } let(:params) { { id: card.id } } context "but the card is not owned by the user" do it "redirects to unauthorized" do spree_delete :destroy, params expect(response).to redirect_to unauthorized_path end end context "and the card is owned by the user" do before do card.update_attribute(:user_id, user.id) stub_request(:get, "https://api.stripe.com/v1/customers/cus_AZNMJ"). to_return(status: 200, body: JSON.generate(id: "cus_AZNMJ")) end context "where the request to destroy the Stripe customer fails" do before do stub_request(:delete, "https://api.stripe.com/v1/customers/cus_AZNMJ"). to_return(status: 402, body: JSON.generate(error: { message: 'Bup-bow!' })) end it "doesn't delete the card" do expect{ spree_delete :destroy, params }.not_to change { Spree::CreditCard.count } expect(flash[:error]).to eq 'Sorry, the card could not be removed' expect(response).to have_http_status :unprocessable_entity end end context "where the request to destroy the Stripe customer succeeds" do before do stub_request(:delete, "https://api.stripe.com/v1/customers/cus_AZNMJ"). to_return(status: 200, body: JSON.generate(deleted: true, id: "cus_AZNMJ")) end it "deletes the card and redirects to account_path" do expect{ spree_delete :destroy, params }.to change { Spree::CreditCard.count }.by(-1) expect(flash[:success]) .to eq "Your card has been removed (number: %s)" % "x-#{card.last_digits}" expect(response).to have_http_status :ok end context "card is the default card and there are existing authorizations for the user" do before do card.update_attribute(:is_default, true) end let!(:customer1) { create(:customer, allow_charges: true) } let!(:customer2) { create(:customer, allow_charges: true) } it "removes the authorizations" do customer1.user = card.user customer2.user = card.user customer1.save customer2.save expect(customer1.reload.allow_charges).to be true expect(customer2.reload.allow_charges).to be true spree_delete :destroy, params expect(customer1.reload.allow_charges).to be false expect(customer2.reload.allow_charges).to be false end context "when has any other saved cards" do let!(:second_card) { create(:stored_credit_card, user_id: user.id, gateway_customer_profile_id: 'cus_AZNMJ') } it "should assign the second one as the default one" do spree_delete :destroy, params expect(Spree::CreditCard.find_by(id: second_card.id).is_default).to eq true end end end end end end end end end