* 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
187 lines
5.7 KiB
Ruby
187 lines
5.7 KiB
Ruby
require "rails_helper"
|
|
|
|
RSpec.describe "Pro Memberships", type: :request do
|
|
describe "GET /pro" do
|
|
it "returns Pro landing page" do
|
|
get pro_membership_path
|
|
expect(response.body).to include("Like a Pro")
|
|
end
|
|
end
|
|
|
|
describe "POST /pro" do
|
|
let(:user) { create(:user) }
|
|
|
|
context "when the user is not logged in" do
|
|
it "redirects to the sign up page" do
|
|
post pro_membership_path
|
|
expect(response).to redirect_to(sign_up_path)
|
|
end
|
|
end
|
|
|
|
context "when the user is logged in and already has a pro memberships" do
|
|
before do
|
|
sign_in user
|
|
end
|
|
|
|
it "does not authorize creation if it has an active membership" do
|
|
create(:pro_membership, user: user)
|
|
expect do
|
|
post pro_membership_path
|
|
end.to raise_error(Pundit::NotAuthorizedError)
|
|
end
|
|
|
|
it "does not authorize creation if it has an expired membership" do
|
|
Timecop.freeze(Time.current) do
|
|
membership = create(:pro_membership, user: user)
|
|
membership.expire!
|
|
|
|
expect do
|
|
post pro_membership_path
|
|
end.to raise_error(Pundit::NotAuthorizedError)
|
|
end
|
|
end
|
|
|
|
it "does not authorize creation if the user as a pro role" do
|
|
user.add_role(:pro)
|
|
expect do
|
|
post pro_membership_path
|
|
end.to raise_error(Pundit::NotAuthorizedError)
|
|
end
|
|
end
|
|
|
|
context "when the user is logged in without a pro membership and enough credits" do
|
|
before do
|
|
sign_in user
|
|
create_list(:credit, ProMembership::MONTHLY_COST, user: user)
|
|
end
|
|
|
|
it "creates an active pro membership" do
|
|
expect do
|
|
post pro_membership_path
|
|
end.to change(ProMembership, :count).by(1)
|
|
expect(user.reload.pro_membership.active?).to be(true)
|
|
end
|
|
|
|
it "buys the pro membership with the correct amount of credits" do
|
|
expect do
|
|
post pro_membership_path
|
|
end.to change(user.credits.spent, :count).by(ProMembership::MONTHLY_COST)
|
|
end
|
|
|
|
it "enqueues a job to populate the history" do
|
|
assert_enqueued_with(
|
|
job: ProMemberships::PopulateHistoryJob,
|
|
args: [user.id],
|
|
queue: "pro_memberships_populate_history",
|
|
) do
|
|
post pro_membership_path
|
|
end
|
|
end
|
|
|
|
it "enqueues a job to bust the user's cache" do
|
|
ActiveJob::Base.queue_adapter.enqueued_jobs.clear # make sure it hasn't been previously queued
|
|
assert_enqueued_with(
|
|
job: Users::BustCacheJob,
|
|
args: [user.id],
|
|
queue: "users_bust_cache",
|
|
) do
|
|
post pro_membership_path
|
|
end
|
|
end
|
|
|
|
it "enqueues a job to bust the user's articles caches" do
|
|
assert_enqueued_with(
|
|
job: Users::ResaveArticlesJob,
|
|
args: [user.id],
|
|
queue: "users_resave_articles",
|
|
) do
|
|
post pro_membership_path
|
|
end
|
|
end
|
|
|
|
it "adds the user to the pro members channel" do
|
|
create(:chat_channel, channel_type: "invite_only", slug: "pro-members")
|
|
post pro_membership_path
|
|
expect(user.reload.chat_channels.exists?(slug: "pro-members")).to be(true)
|
|
end
|
|
|
|
it "redirects to the pro membership settings page with a notice" do
|
|
post pro_membership_path
|
|
expect(response).to redirect_to(user_settings_path("pro-membership"))
|
|
expect(flash[:settings_notice]).to eq("You are now a Pro!")
|
|
end
|
|
end
|
|
|
|
context "when the user is logged in without a pro membership and not enough credits" do
|
|
before do
|
|
sign_in user
|
|
end
|
|
|
|
it "does not create an active pro membership" do
|
|
expect do
|
|
post pro_membership_path
|
|
end.to change(ProMembership, :count).by(0)
|
|
end
|
|
|
|
it "does not subtract credits" do
|
|
expect do
|
|
post pro_membership_path
|
|
end.to change(user.credits.spent, :count).by(0)
|
|
end
|
|
|
|
it "redirects to the pro membership settings page with an error message" do
|
|
post pro_membership_path
|
|
expect(response).to redirect_to(user_settings_path("pro-membership"))
|
|
expect(flash[:error]).to eq("You don't have enough credits!")
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "PUT /pro" do
|
|
let(:user) { create(:user) }
|
|
|
|
context "when the user is not logged in" do
|
|
it "redirects to the sign up page" do
|
|
put pro_membership_path
|
|
expect(response).to redirect_to(sign_up_path)
|
|
end
|
|
end
|
|
|
|
context "when the user is logged in without a pro membership" do
|
|
before do
|
|
sign_in user
|
|
end
|
|
|
|
it "does not authorize the operation" do
|
|
expect do
|
|
put pro_membership_path
|
|
end.to raise_error(Pundit::NotAuthorizedError)
|
|
end
|
|
end
|
|
|
|
context "when the user is logged in with a pro membership" do
|
|
before do
|
|
sign_in user
|
|
end
|
|
|
|
it "works correctly" do
|
|
create(:pro_membership, user: user)
|
|
put pro_membership_path, params: { pro_membership: { auto_recharge: true } }
|
|
expect(flash[:settings_notice]).to eq("Your membership has been updated!")
|
|
expect(response).to redirect_to(user_settings_path("pro-membership"))
|
|
end
|
|
|
|
it "activates auto recharge" do
|
|
pro_membership = create(:pro_membership, user: user)
|
|
put pro_membership_path, params: { pro_membership: { auto_recharge: true } }
|
|
expect(pro_membership.reload.auto_recharge).to be(true)
|
|
end
|
|
|
|
it "deactivates auto recharge" do
|
|
pro_membership = create(:pro_membership, user: user, auto_recharge: true)
|
|
put pro_membership_path, params: { pro_membership: { auto_recharge: false } }
|
|
expect(pro_membership.reload.auto_recharge).to be(false)
|
|
end
|
|
end
|
|
end
|
|
end
|