* Add ProMembership model * Implement ProMembershipsController#create * Implement basic ProMembershipsController#show * Add ProMembership to ledger * Populate user history after pro subscription is created * Add fields for expiration notifications * Add ProMemberships::ExpirationNotifier to notify users of expiring memberships * Add tasks for recurring jobs to notify users of expiration * Add auto_recharge column to ProMembership * Add ProMemberships::Biller (incomplete) * Fix specs * Add ProMembership to Administrate * Fix spec * Add has_enough_credits? to User and Organization * Add Payments::Customer class * Finish ProMembership::Biller functionality * Fix ProMemberships::Creator check for credits * Disable destroy actions for ProMembershipsController * Correctly authenticate ProMembershipsController actions * Make sure only pro user's history can be indexed * Add ProMembershipsController#update action for auto recharge * Use regular AR to save new credits and add touch to the purchaser * Clarify Pro membership create policy * Display information about an existing pro membership * Add UI to show page * Add system test for Pro membership creation * Implement edit membership * Make sure users with pro memberships can access history and dashboard pro * Fix padding issue * Show a different text for a user that has credits but not enough for Pro * Move Pro Membership functionality inside settings * Update Pro Membership link in email notifications * Bust all relevant caches * Add the Pro checkmark around the website * Use Users::ResaveArticlesJob instead of delay * Add/remove user from pro-members chat channel * Use the appropriate Pro checkmark * Remove unfinished pro elements * Remove checkmark JS
257 lines
8.4 KiB
Ruby
257 lines
8.4 KiB
Ruby
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 }
|
|
|
|
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 = Stripe::Customer.retrieve(user.stripe_id_code)
|
|
expect(customer.charges.first.amount).to eq 8000
|
|
end
|
|
|
|
context "when a user already has a card" do
|
|
before do
|
|
customer = Stripe::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 = Stripe::Customer.retrieve(user.stripe_id_code)
|
|
post "/credits", params: {
|
|
credit: {
|
|
number_to_purchase: 20
|
|
},
|
|
selected_card: customer.sources.first.id
|
|
}
|
|
expect(customer.charges.first.amount).to eq 8000
|
|
end
|
|
|
|
it "creates unspent credits" do
|
|
customer = Stripe::Customer.retrieve(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 = Stripe::Customer.retrieve(user.stripe_id_code)
|
|
card_id = customer.sources.data.last.id
|
|
expect(customer.charges.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 = Stripe::Customer.retrieve(org_admin.stripe_id_code)
|
|
expect(customer.charges.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_error(Stripe::CardError.new(2, 3, 4), :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_error(Stripe::CardError.new(2, 3, 4), :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
|