* This change abstracts the DatadogStatsClient into a ForemStatsClient. The purpose of this abstraction is to set the foundation for a subsequent PR that will allow one to use New Relic for recording Forem stats, instead of Datadog, if there is a New Relic configuration found. This specific change creates an abstraction layer that can be built upon, without changing any actual default behavior. All specs still pass. * Use delegate instead of explicit methods. * Delegate instead of explicit methods. * Fix the error. * Refactor according to the suggestions in the comments. * Ooops. Stats work better when all of the code is committed. * Removing the alias of count to increment since that was done in error.
232 lines
8.7 KiB
Ruby
232 lines
8.7 KiB
Ruby
require "rails_helper"
|
|
|
|
RSpec.describe "StripeActiveCards", type: :request do
|
|
let(:user) { create(:user) }
|
|
let(:stripe_helper) { StripeMock.create_test_helper }
|
|
let(:card_token) { stripe_helper.generate_card_token }
|
|
|
|
before do
|
|
StripeMock.start
|
|
|
|
sign_in user
|
|
end
|
|
|
|
after { StripeMock.stop }
|
|
|
|
def create_user_with_card(user, source)
|
|
customer = Payments::Customer.create(
|
|
email: "stripe_tester@dev.to",
|
|
source: source,
|
|
)
|
|
user.update(stripe_id_code: customer.id)
|
|
|
|
[customer, customer.sources.list.first]
|
|
end
|
|
|
|
describe "POST /stripe_active_cards" do
|
|
it "successfully adds a card to the correct user" do
|
|
post stripe_active_cards_path(stripe_token: stripe_helper.generate_card_token)
|
|
expect(response).to redirect_to(user_settings_path(:billing))
|
|
expect(flash[:settings_notice]).to eq("Your billing information has been updated")
|
|
|
|
card = Payments::Customer.get(user.stripe_id_code).sources.first
|
|
expect(card.is_a?(Stripe::Card)).to eq(true)
|
|
end
|
|
|
|
it "creates an AuditLog entry for successful creates" do
|
|
expect do
|
|
post stripe_active_cards_path(stripe_token: stripe_helper.generate_card_token)
|
|
end.to change(AuditLog, :count).by(1)
|
|
end
|
|
|
|
it "does not add a card if there is a card error" do
|
|
StripeMock.prepare_card_error(:incorrect_number, :create_source)
|
|
|
|
post stripe_active_cards_path(stripe_token: stripe_helper.generate_card_token)
|
|
|
|
expect(response).to redirect_to(user_settings_path(:billing))
|
|
expect(flash[:error]).to be_present
|
|
expect(Payments::Customer.get(user.stripe_id_code).sources.count).to eq(0)
|
|
end
|
|
|
|
it "increments sidekiq.errors in Datadog on failure" do
|
|
allow(ForemStatsClient).to receive(:increment)
|
|
invalid_error = Stripe::InvalidRequestError.new("message", "param")
|
|
allow(Stripe::Customer).to receive(:create).and_raise(invalid_error)
|
|
|
|
post stripe_active_cards_path(stripe_token: stripe_helper.generate_card_token)
|
|
expect(response).to redirect_to(user_settings_path(:billing))
|
|
expect(flash[:error]).to eq(invalid_error.message)
|
|
|
|
tags = hash_including(tags: array_including("error:InvalidRequestError"))
|
|
expect(ForemStatsClient).to have_received(:increment).with("stripe.errors", tags)
|
|
end
|
|
|
|
it "updates the user's updated_at" do
|
|
old_updated_at = user.updated_at
|
|
|
|
Timecop.freeze(1.minute.from_now) do
|
|
post stripe_active_cards_path(stripe_token: stripe_helper.generate_card_token)
|
|
end
|
|
|
|
expect(user.reload.updated_at.to_i > old_updated_at.to_i).to be(true)
|
|
end
|
|
|
|
it "increments sidekiq.errors.new_subscription in Datadog on failure" do
|
|
allow(ForemStatsClient).to receive(:increment)
|
|
invalid_error = Stripe::InvalidRequestError.new(nil, nil)
|
|
allow(Stripe::Customer).to receive(:create).and_raise(invalid_error)
|
|
post "/stripe_active_cards", params: { stripe_token: stripe_helper.generate_card_token }
|
|
|
|
tags = hash_including(tags: array_including("action:create_card", "user_id:#{user.id}"))
|
|
expect(ForemStatsClient).to have_received(:increment).with("stripe.errors", tags)
|
|
end
|
|
end
|
|
|
|
describe "PUT /stripe_active_cards/:card_id" do
|
|
it "updates the customer default source" do
|
|
customer, source = create_user_with_card(user, card_token)
|
|
expect(customer.default_source).to eq(source.id)
|
|
|
|
# add a second source
|
|
new_card_token = stripe_helper.generate_card_token
|
|
new_card = Payments::Customer.create_source(customer.id, new_card_token)
|
|
|
|
put stripe_active_card_path(id: new_card.id)
|
|
expect(response).to redirect_to(user_settings_path(:billing))
|
|
expect(flash[:settings_notice]).to eq("Your billing information has been updated")
|
|
|
|
expect(Payments::Customer.get(customer.id).default_source).to eq(new_card.id)
|
|
end
|
|
|
|
it "creates an AuditLog entry for successful updates" do
|
|
customer, = create_user_with_card(user, card_token)
|
|
# add a second source
|
|
new_card_token = stripe_helper.generate_card_token
|
|
new_card = Payments::Customer.create_source(customer.id, new_card_token)
|
|
|
|
expect do
|
|
put stripe_active_card_path(id: new_card.id)
|
|
end.to change(AuditLog, :count).by(1)
|
|
end
|
|
|
|
it "does not update the customer default souce if the source ID is unknown" do
|
|
customer, source = create_user_with_card(user, card_token)
|
|
|
|
put stripe_active_card_path(id: "unknown")
|
|
expect(response).to redirect_to(user_settings_path(:billing))
|
|
expect(flash[:error]).to eq("There is no source with ID unknown")
|
|
|
|
expect(Payments::Customer.get(customer.id).default_source).to eq(source.id)
|
|
end
|
|
|
|
it "increments sidekiq.errors in Datadog on failure" do
|
|
_, source = create_user_with_card(user, card_token)
|
|
original_card_id = source.id
|
|
|
|
allow(ForemStatsClient).to receive(:increment)
|
|
card_error = Stripe::CardError.new("message", "param")
|
|
allow(Stripe::Customer).to receive(:retrieve).and_raise(card_error)
|
|
|
|
put stripe_active_card_path(id: original_card_id)
|
|
expect(response).to redirect_to(user_settings_path(:billing))
|
|
expect(flash[:error]).to eq(card_error.message)
|
|
|
|
tags = hash_including(tags: array_including("error:CardError"))
|
|
expect(ForemStatsClient).to have_received(:increment).with("stripe.errors", tags)
|
|
end
|
|
|
|
it "updates the user's updated_at" do
|
|
_, source = create_user_with_card(user, card_token)
|
|
old_updated_at = user.updated_at
|
|
|
|
Timecop.freeze(1.minute.from_now) do
|
|
put stripe_active_card_path(id: source.id)
|
|
end
|
|
|
|
expect(user.reload.updated_at.to_i > old_updated_at.to_i).to be(true)
|
|
end
|
|
|
|
it "increments sidekiq.errors.update_subscription in Datadog on failure" do
|
|
_, source = create_user_with_card(user, card_token)
|
|
original_card_id = source.id
|
|
|
|
allow(ForemStatsClient).to receive(:increment)
|
|
card_error = Stripe::CardError.new("message", "param")
|
|
allow(Stripe::Customer).to receive(:retrieve).and_raise(card_error)
|
|
|
|
put stripe_active_card_path(id: original_card_id)
|
|
expect(response).to redirect_to(user_settings_path(:billing))
|
|
expect(flash[:error]).to eq(card_error.message)
|
|
tags = hash_including(tags: array_including("action:update_card", "user_id:#{user.id}"))
|
|
expect(ForemStatsClient).to have_received(:increment).with("stripe.errors", tags)
|
|
end
|
|
end
|
|
|
|
describe "DELETE /stripe_active_cards/:card_id" do
|
|
context "when a valid request is made" do
|
|
before do
|
|
_, source = create_user_with_card(user, card_token)
|
|
original_card_id = source.id
|
|
delete stripe_active_card_path(id: original_card_id)
|
|
end
|
|
|
|
it "redirects to billing page" do
|
|
expect(response).to redirect_to(user_settings_path(:billing))
|
|
end
|
|
|
|
it "provides the proper flash notice" do
|
|
expect(flash[:settings_notice]).to eq("Your card has been successfully removed.")
|
|
end
|
|
|
|
it "successfully deletes the card from sources" do
|
|
customer = Payments::Customer.get(user.stripe_id_code)
|
|
expect(Payments::Customer.get_sources(customer).count).to eq(0)
|
|
end
|
|
|
|
it "creates an AuditLog entry for successful deletes" do
|
|
_, source = create_user_with_card(user, card_token)
|
|
|
|
expect do
|
|
delete stripe_active_card_path(id: source.id)
|
|
end.to change(AuditLog, :count).by(1)
|
|
end
|
|
end
|
|
|
|
context "when an invalid request is made" do
|
|
it "redirects with an error if the card ID is unknown" do
|
|
create_user_with_card(user, card_token)
|
|
|
|
delete stripe_active_card_path(id: "unknown")
|
|
expect(response).to redirect_to(user_settings_path(:billing))
|
|
expect(flash[:error]).to eq("There is no source with ID unknown")
|
|
end
|
|
|
|
it "redirects with an error if the customer has a subscription" do
|
|
customer, = create_user_with_card(user, card_token)
|
|
|
|
product = stripe_helper.create_product
|
|
plan = stripe_helper.create_plan(product: product.id)
|
|
Stripe::Subscription.create(customer: customer.id, items: [{ plan: plan.id }])
|
|
|
|
delete stripe_active_card_path(id: "unknown")
|
|
expect(response).to redirect_to(user_settings_path(:billing))
|
|
error = "Can't remove card if you have an active membership. Please cancel your membership first."
|
|
expect(flash[:error]).to eq(error)
|
|
end
|
|
end
|
|
|
|
it "updates the user's updated_at" do
|
|
_, source = create_user_with_card(user, card_token)
|
|
original_card_id = source.id
|
|
|
|
old_updated_at = user.updated_at
|
|
|
|
Timecop.freeze(1.minute.from_now) do
|
|
delete stripe_active_card_path(id: original_card_id)
|
|
end
|
|
|
|
expect(user.reload.updated_at.to_i > old_updated_at.to_i).to be(true)
|
|
end
|
|
end
|
|
end
|