require "rails_helper" RSpec.describe "Credits", type: :request do describe "GET /credits" do let(:user) { create(:user) } let(:org_member) { create(:user, :org_member) } let(:org_admin) { create(:user, :org_admin) } it "shows credits page" do sign_in user get "/credits" expect(response.body).to include("You have") end it "shows credits page if user belongs to an org" do org = org_member.organizations.first sign_in org_member get "/credits" expect(response.body).to include("You have") expect(response.body).not_to include(CGI.escapeHTML(org.name)) end it "shows credits page if user belongs to an org and is org admin" do org = org_admin.organizations.first sign_in org_admin get "/credits" expect(response.body).to include(CGI.escapeHTML(org.name)) end context "when the user has made purchases that will appear in the ledger" do let(:params) { { spent: true, spent_at: Time.current } } it "shows listing purchases" do listing = create(:classified_listing, user: user, title: "Awesome opportunity") purchase_params = { user: user, purchase_type: listing.class.name, purchase_id: listing.id } create(:credit, params.merge(purchase_params)) sign_in user get credits_path expect(response.body).to include("Purchase history") expect(response.body).to include("Listing") expect(response.body).to include(listing.title) end it "does not show sponsorship purchases to org members" do org = org_member.organizations.first sponsorship = create(:sponsorship, organization: org, user: org_admin) purchase_params = { organization: org, purchase_type: sponsorship.class.name, purchase_id: sponsorship.id } create(:credit, params.merge(purchase_params)) sign_in org_member get credits_path expect(response.body).to include("Purchase history") expect(response.body).not_to include("Sponsorship") expect(response.body).not_to include(sponsorship.level) end it "shows sponsorship purchases to org admins" do org = org_admin.organizations.first sponsorship = create(:sponsorship, organization: org, user: org_admin) purchase_params = { organization: org, purchase_type: sponsorship.class.name, purchase_id: sponsorship.id } create(:credit, params.merge(purchase_params)) sign_in org_admin get credits_path expect(response.body).to include("Purchase history") expect(response.body).to include("Sponsorship") expect(response.body).to include(sponsorship.level.titleize) end it "shows tag sponsorship purchases to org admins" do org = org_admin.organizations.first tag = create(:tag) sponsorship = create(:sponsorship, organization: org, user: org_admin, level: :tag, sponsorable: tag) purchase_params = { organization: org, purchase_type: sponsorship.class.name, purchase_id: sponsorship.id } create(:credit, params.merge(purchase_params)) sign_in org_admin get credits_path expect(response.body).to include("Purchase history") expect(response.body).to include("Sponsorship") expect(response.body).to include(tag.name) end it "shows unattributed purchases" do purchase_params = { user: user } create(:credit, params.merge(purchase_params)) sign_in user get credits_path expect(response.body).to include("Purchase history") expect(response.body).to include("Miscellaneous items") end it "shows a pro membership purchase" do pro_membership = create(:pro_membership, user: user) purchase_params = { user: user, purchase_type: pro_membership.class.name, purchase_id: pro_membership.id } create(:credit, params.merge(purchase_params)) sign_in user get credits_path expect(response.body).to include("Purchase history") expect(response.body).to include("Pro Membership") expect(response.body).to include(pro_membership_path) end end end describe "POST credits" do let(:user) { create(:user) } let(:org_admin) { create(:user, :org_admin) } let(:admin_org_id) { org_admin.organizations.first.id } let(:stripe_helper) { StripeMock.create_test_helper } def charges(customer) Stripe::Charge.list(customer: customer.id) end before do StripeMock.start sign_in user end after do StripeMock.stop end it "creates unspent credits" do post "/credits", params: { credit: { number_to_purchase: 25 }, stripe_token: stripe_helper.generate_card_token } expect(user.credits.where(spent: false).size).to eq(25) end it "makes a valid Stripe charge" do post "/credits", params: { credit: { number_to_purchase: 20 }, stripe_token: stripe_helper.generate_card_token } customer = Payments::Customer.get(user.stripe_id_code) expect(charges(customer).first.amount).to eq 8000 end context "when a user already has a card" do before do customer = Payments::Customer.create(email: user.email) user.update_column(:stripe_id_code, customer.id) customer.sources.create(source: stripe_helper.generate_card_token) end it "makes a valid Stripe charge" do customer = Payments::Customer.get(user.stripe_id_code) post "/credits", params: { credit: { number_to_purchase: 20 }, selected_card: customer.sources.first.id } expect(charges(customer).first.amount).to eq 8000 end it "creates unspent credits" do customer = Payments::Customer.get(user.stripe_id_code) post "/credits", params: { credit: { number_to_purchase: 20 }, selected_card: customer.sources.first.id } expect(user.credits.where(spent: false).size).to eq(20) end it "charges a new card if given one" do post "/credits", params: { credit: { number_to_purchase: 20 }, stripe_token: stripe_helper.generate_card_token } customer = Payments::Customer.get(user.stripe_id_code) card_id = customer.sources.data.last.id expect(charges(customer).first.source.id).to eq card_id end end context "when purchasing as an organization" do before { sign_in org_admin } it "creates unspent credits for the organization" do post "/credits", params: { organization_id: admin_org_id, credit: { number_to_purchase: 20 }, stripe_token: stripe_helper.generate_card_token } expect(Credit.where(organization_id: admin_org_id, spent: false).size).to eq 20 end it "makes a valid Stripe charge" do post "/credits", params: { organization_id: admin_org_id, credit: { number_to_purchase: 20 }, stripe_token: stripe_helper.generate_card_token } customer = Payments::Customer.get(org_admin.stripe_id_code) expect(charges(customer).first.amount).to eq 8000 end it "does not create unspent credits for the current_user" do post "/credits", params: { organization_id: admin_org_id, credit: { number_to_purchase: 20 }, stripe_token: stripe_helper.generate_card_token } expect(org_admin.credits.where(spent: false).size).to eq 0 end end context "when payment fails" do it "does not reward credits" do StripeMock.prepare_card_error(:card_declined, :new_charge) post "/credits", params: { credit: { number_to_purchase: 25 }, stripe_token: stripe_helper.generate_card_token } expect(user.credits.where(spent: false).size).to eq(0) end it "does not reward credits for orgs" do sign_in org_admin StripeMock.prepare_card_error(:card_declined, :new_charge) post "/credits", params: { organization_id: admin_org_id, credit: { number_to_purchase: 25 }, stripe_token: stripe_helper.generate_card_token } expect(Credit.where(organization_id: admin_org_id, spent: false).size).to eq(0) end end end end