518 lines
17 KiB
Elixir
518 lines
17 KiB
Elixir
defmodule Plausible.Billing.QuotaTest do
|
|
use Plausible.DataCase, async: true
|
|
alias Plausible.Billing.Quota
|
|
alias Plausible.Billing.Feature.{Goals, RevenueGoals, Funnels, Props, StatsAPI}
|
|
|
|
@v1_plan_id "558018"
|
|
@v2_plan_id "654177"
|
|
@v3_plan_id "749342"
|
|
@v3_business_plan_id "857481"
|
|
|
|
describe "site_limit/1" do
|
|
test "returns 50 when user is on an old plan" do
|
|
user_on_v1 = insert(:user, subscription: build(:subscription, paddle_plan_id: @v1_plan_id))
|
|
user_on_v2 = insert(:user, subscription: build(:subscription, paddle_plan_id: @v2_plan_id))
|
|
user_on_v3 = insert(:user, subscription: build(:subscription, paddle_plan_id: @v3_plan_id))
|
|
|
|
assert 50 == Quota.site_limit(user_on_v1)
|
|
assert 50 == Quota.site_limit(user_on_v2)
|
|
assert 50 == Quota.site_limit(user_on_v3)
|
|
end
|
|
|
|
test "returns 50 when user is on free_10k plan" do
|
|
user = insert(:user, subscription: build(:subscription, paddle_plan_id: "free_10k"))
|
|
assert 50 == Quota.site_limit(user)
|
|
end
|
|
|
|
test "returns unlimited when user is on an enterprise plan" do
|
|
user = insert(:user)
|
|
|
|
enterprise_plan =
|
|
insert(:enterprise_plan,
|
|
user_id: user.id,
|
|
monthly_pageview_limit: 100_000,
|
|
site_limit: 500
|
|
)
|
|
|
|
_subscription =
|
|
insert(:subscription, user_id: user.id, paddle_plan_id: enterprise_plan.paddle_plan_id)
|
|
|
|
assert :unlimited == Quota.site_limit(user)
|
|
end
|
|
|
|
test "returns 50 when user in on trial" do
|
|
user = insert(:user, trial_expiry_date: Timex.shift(Timex.now(), days: 7))
|
|
assert 50 == Quota.site_limit(user)
|
|
end
|
|
|
|
test "returns the subscription limit for enterprise users who have not paid yet" do
|
|
user =
|
|
insert(:user,
|
|
enterprise_plan: build(:enterprise_plan, paddle_plan_id: "123321"),
|
|
subscription: build(:subscription, paddle_plan_id: @v1_plan_id)
|
|
)
|
|
|
|
assert 50 == Quota.site_limit(user)
|
|
end
|
|
|
|
test "returns 50 for enterprise users who have not upgraded yet and are on trial" do
|
|
user =
|
|
insert(:user,
|
|
enterprise_plan: build(:enterprise_plan, paddle_plan_id: "123321"),
|
|
subscription: nil
|
|
)
|
|
|
|
assert 50 == Quota.site_limit(user)
|
|
end
|
|
|
|
test "is unlimited for enterprise customers" do
|
|
user =
|
|
insert(:user,
|
|
enterprise_plan: build(:enterprise_plan, paddle_plan_id: "123321"),
|
|
subscription: build(:subscription, paddle_plan_id: "123321")
|
|
)
|
|
|
|
assert :unlimited == Quota.site_limit(user)
|
|
end
|
|
|
|
test "is unlimited for enterprise customers who are due to change a plan" do
|
|
user =
|
|
insert(:user,
|
|
enterprise_plan: build(:enterprise_plan, paddle_plan_id: "old-paddle-plan-id"),
|
|
subscription: build(:subscription, paddle_plan_id: "old-paddle-plan-id")
|
|
)
|
|
|
|
insert(:enterprise_plan, user_id: user.id, paddle_plan_id: "new-paddle-plan-id")
|
|
assert :unlimited == Quota.site_limit(user)
|
|
end
|
|
end
|
|
|
|
test "site_usage/1 returns the amount of sites the user owns" do
|
|
user = insert(:user)
|
|
insert_list(3, :site, memberships: [build(:site_membership, user: user, role: :owner)])
|
|
insert(:site, memberships: [build(:site_membership, user: user, role: :admin)])
|
|
insert(:site, memberships: [build(:site_membership, user: user, role: :viewer)])
|
|
|
|
assert Quota.site_usage(user) == 3
|
|
end
|
|
|
|
describe "within_limit?/2" do
|
|
test "returns true when quota is not exceeded" do
|
|
assert Quota.within_limit?(3, 5)
|
|
end
|
|
|
|
test "returns true when limit is :unlimited" do
|
|
assert Quota.within_limit?(10_000, :unlimited)
|
|
end
|
|
|
|
test "returns false when usage is at limit" do
|
|
refute Quota.within_limit?(3, 3)
|
|
end
|
|
|
|
test "returns false when usage exceeds the limit" do
|
|
refute Quota.within_limit?(10, 3)
|
|
end
|
|
end
|
|
|
|
describe "monthly_pageview_limit/1" do
|
|
test "is based on the plan if user is on a standard plan" do
|
|
user = insert(:user, subscription: build(:subscription, paddle_plan_id: @v1_plan_id))
|
|
|
|
assert Quota.monthly_pageview_limit(user.subscription) == 10_000
|
|
end
|
|
|
|
test "free_10k has 10k monthly_pageview_limit" do
|
|
user = insert(:user, subscription: build(:subscription, paddle_plan_id: "free_10k"))
|
|
|
|
assert Quota.monthly_pageview_limit(user.subscription) == 10_000
|
|
end
|
|
|
|
test "is based on the enterprise plan if user is on an enterprise plan" do
|
|
user = insert(:user)
|
|
|
|
enterprise_plan =
|
|
insert(:enterprise_plan, user_id: user.id, monthly_pageview_limit: 100_000)
|
|
|
|
subscription =
|
|
insert(:subscription, user_id: user.id, paddle_plan_id: enterprise_plan.paddle_plan_id)
|
|
|
|
assert Quota.monthly_pageview_limit(subscription) == 100_000
|
|
end
|
|
|
|
test "does not limit pageviews when user has a pending enterprise plan" do
|
|
user = insert(:user)
|
|
subscription = insert(:subscription, user_id: user.id, paddle_plan_id: "pending-enterprise")
|
|
|
|
assert Quota.monthly_pageview_limit(subscription) == :unlimited
|
|
end
|
|
end
|
|
|
|
describe "monthly_pageview_usage/1" do
|
|
test "is 0 with no events" do
|
|
user = insert(:user)
|
|
|
|
assert Quota.monthly_pageview_usage(user) == 0
|
|
end
|
|
|
|
test "counts the total number of events from all sites the user owns" do
|
|
user = insert(:user)
|
|
site1 = insert(:site, members: [user])
|
|
site2 = insert(:site, members: [user])
|
|
|
|
populate_stats(site1, [
|
|
build(:pageview),
|
|
build(:pageview)
|
|
])
|
|
|
|
populate_stats(site2, [
|
|
build(:pageview),
|
|
build(:event, name: "custom events")
|
|
])
|
|
|
|
assert Quota.monthly_pageview_usage(user) == 4
|
|
end
|
|
|
|
test "only counts usage from sites where the user is the owner" do
|
|
user = insert(:user)
|
|
|
|
insert(:site,
|
|
domain: "site-with-no-views.com",
|
|
memberships: [
|
|
build(:site_membership, user: user, role: :owner)
|
|
]
|
|
)
|
|
|
|
insert(:site,
|
|
domain: "test-site.com",
|
|
memberships: [
|
|
build(:site_membership, user: user, role: :admin)
|
|
]
|
|
)
|
|
|
|
assert Quota.monthly_pageview_usage(user) == 0
|
|
end
|
|
end
|
|
|
|
describe "team_member_usage/1" do
|
|
test "returns the number of members in all of the sites the user owns" do
|
|
me = insert(:user)
|
|
|
|
_site_i_own_1 =
|
|
insert(:site,
|
|
memberships: [
|
|
build(:site_membership, user: me, role: :owner),
|
|
build(:site_membership, user: build(:user), role: :viewer)
|
|
]
|
|
)
|
|
|
|
_site_i_own_2 =
|
|
insert(:site,
|
|
memberships: [
|
|
build(:site_membership, user: me, role: :owner),
|
|
build(:site_membership, user: build(:user), role: :admin),
|
|
build(:site_membership, user: build(:user), role: :viewer)
|
|
]
|
|
)
|
|
|
|
_site_i_own_3 =
|
|
insert(:site,
|
|
memberships: [
|
|
build(:site_membership, user: me, role: :owner)
|
|
]
|
|
)
|
|
|
|
_site_i_have_access =
|
|
insert(:site,
|
|
memberships: [
|
|
build(:site_membership, user: me, role: :viewer),
|
|
build(:site_membership, user: build(:user), role: :viewer),
|
|
build(:site_membership, user: build(:user), role: :viewer),
|
|
build(:site_membership, user: build(:user), role: :viewer)
|
|
]
|
|
)
|
|
|
|
assert Quota.team_member_usage(me) == 3
|
|
end
|
|
|
|
test "counts the same email address as one team member" do
|
|
me = insert(:user)
|
|
joe = insert(:user, email: "joe@plausible.test")
|
|
|
|
_site_i_own_1 =
|
|
insert(:site,
|
|
memberships: [
|
|
build(:site_membership, user: me, role: :owner),
|
|
build(:site_membership, user: joe, role: :viewer)
|
|
]
|
|
)
|
|
|
|
_site_i_own_2 =
|
|
insert(:site,
|
|
memberships: [
|
|
build(:site_membership, user: me, role: :owner),
|
|
build(:site_membership, user: build(:user), role: :admin),
|
|
build(:site_membership, user: joe, role: :viewer)
|
|
]
|
|
)
|
|
|
|
site_i_own_3 = insert(:site, memberships: [build(:site_membership, user: me, role: :owner)])
|
|
|
|
insert(:invitation, site: site_i_own_3, inviter: me, email: "joe@plausible.test")
|
|
|
|
assert Quota.team_member_usage(me) == 2
|
|
end
|
|
|
|
test "counts pending invitations as team members" do
|
|
me = insert(:user)
|
|
member = insert(:user)
|
|
|
|
site_i_own =
|
|
insert(:site,
|
|
memberships: [
|
|
build(:site_membership, user: me, role: :owner),
|
|
build(:site_membership, user: member, role: :admin)
|
|
]
|
|
)
|
|
|
|
site_i_have_access =
|
|
insert(:site, memberships: [build(:site_membership, user: me, role: :admin)])
|
|
|
|
insert(:invitation, site: site_i_own, inviter: me)
|
|
insert(:invitation, site: site_i_own, inviter: member)
|
|
insert(:invitation, site: site_i_have_access, inviter: me)
|
|
|
|
assert Quota.team_member_usage(me) == 3
|
|
end
|
|
|
|
test "does not count ownership transfer as a team member" do
|
|
me = insert(:user)
|
|
site_i_own = insert(:site, memberships: [build(:site_membership, user: me, role: :owner)])
|
|
|
|
insert(:invitation, site: site_i_own, inviter: me, role: :owner)
|
|
|
|
assert Quota.team_member_usage(me) == 0
|
|
end
|
|
|
|
test "returns zero when user does not have any site" do
|
|
me = insert(:user)
|
|
assert Quota.team_member_usage(me) == 0
|
|
end
|
|
|
|
test "does not count email report recipients as team members" do
|
|
me = insert(:user)
|
|
site = insert(:site, memberships: [build(:site_membership, user: me, role: :owner)])
|
|
|
|
insert(:weekly_report,
|
|
site: site,
|
|
recipients: ["adam@plausible.test", "vini@plausible.test"]
|
|
)
|
|
|
|
assert Quota.team_member_usage(me) == 0
|
|
end
|
|
end
|
|
|
|
describe "team_member_limit/1" do
|
|
test "returns unlimited when user is on an old plan" do
|
|
user_on_v1 = insert(:user, subscription: build(:subscription, paddle_plan_id: @v1_plan_id))
|
|
user_on_v2 = insert(:user, subscription: build(:subscription, paddle_plan_id: @v2_plan_id))
|
|
user_on_v3 = insert(:user, subscription: build(:subscription, paddle_plan_id: @v3_plan_id))
|
|
|
|
assert :unlimited == Quota.team_member_limit(user_on_v1)
|
|
assert :unlimited == Quota.team_member_limit(user_on_v2)
|
|
assert :unlimited == Quota.team_member_limit(user_on_v3)
|
|
end
|
|
|
|
test "returns unlimited when user is on free_10k plan" do
|
|
user = insert(:user, subscription: build(:subscription, paddle_plan_id: "free_10k"))
|
|
assert :unlimited == Quota.team_member_limit(user)
|
|
end
|
|
|
|
test "returns unlimited when user is on an enterprise plan" do
|
|
user = insert(:user)
|
|
enterprise_plan = insert(:enterprise_plan, user_id: user.id)
|
|
|
|
_subscription =
|
|
insert(:subscription, user_id: user.id, paddle_plan_id: enterprise_plan.paddle_plan_id)
|
|
|
|
assert :unlimited == Quota.team_member_limit(user)
|
|
end
|
|
|
|
test "returns 5 when user in on trial" do
|
|
user = insert(:user, trial_expiry_date: Timex.shift(Timex.now(), days: 7))
|
|
assert 5 == Quota.team_member_limit(user)
|
|
end
|
|
|
|
test "is unlimited for enterprise customers" do
|
|
user =
|
|
insert(:user,
|
|
enterprise_plan: build(:enterprise_plan, paddle_plan_id: "123321"),
|
|
subscription: build(:subscription, paddle_plan_id: "123321")
|
|
)
|
|
|
|
assert :unlimited == Quota.team_member_limit(user)
|
|
end
|
|
|
|
test "reads from json file when the user is on a v4 plan" do
|
|
user_on_growth = insert(:user, subscription: build(:growth_subscription))
|
|
|
|
user_on_business = insert(:user, subscription: build(:business_subscription))
|
|
|
|
assert 3 == Quota.team_member_limit(user_on_growth)
|
|
assert 10 == Quota.team_member_limit(user_on_business)
|
|
end
|
|
|
|
test "returns unlimited when user is on a v3 business plan" do
|
|
user =
|
|
insert(:user, subscription: build(:subscription, paddle_plan_id: @v3_business_plan_id))
|
|
|
|
assert :unlimited == Quota.team_member_limit(user)
|
|
end
|
|
end
|
|
|
|
describe "features_usage/1" do
|
|
test "returns an empty list" do
|
|
user = insert(:user)
|
|
assert [] == Quota.features_usage(user)
|
|
end
|
|
|
|
test "returns [Props] when user uses custom props" do
|
|
user = insert(:user)
|
|
|
|
insert(:site,
|
|
allowed_event_props: ["dummy"],
|
|
memberships: [build(:site_membership, user: user, role: :owner)]
|
|
)
|
|
|
|
assert [Props] == Quota.features_usage(user)
|
|
end
|
|
|
|
test "returns [Funnels] when user uses funnels" do
|
|
user = insert(:user)
|
|
site = insert(:site, memberships: [build(:site_membership, user: user, role: :owner)])
|
|
|
|
goals = insert_list(3, :goal, site: site, event_name: fn -> Ecto.UUID.generate() end)
|
|
steps = Enum.map(goals, &%{"goal_id" => &1.id})
|
|
Plausible.Funnels.create(site, "dummy", steps)
|
|
|
|
assert [Funnels] == Quota.features_usage(user)
|
|
end
|
|
|
|
test "returns [RevenueGoals] when user uses revenue goals" do
|
|
user = insert(:user)
|
|
site = insert(:site, memberships: [build(:site_membership, user: user, role: :owner)])
|
|
insert(:goal, currency: :USD, site: site, event_name: "Purchase")
|
|
|
|
assert [RevenueGoals] == Quota.features_usage(user)
|
|
end
|
|
|
|
test "returns multiple features" do
|
|
user = insert(:user)
|
|
|
|
site =
|
|
insert(:site,
|
|
allowed_event_props: ["dummy"],
|
|
memberships: [build(:site_membership, user: user, role: :owner)]
|
|
)
|
|
|
|
insert(:goal, currency: :USD, site: site, event_name: "Purchase")
|
|
|
|
goals = insert_list(3, :goal, site: site, event_name: fn -> Ecto.UUID.generate() end)
|
|
steps = Enum.map(goals, &%{"goal_id" => &1.id})
|
|
Plausible.Funnels.create(site, "dummy", steps)
|
|
|
|
assert [RevenueGoals, Funnels, Props] == Quota.features_usage(user)
|
|
end
|
|
|
|
test "accounts only for sites the user owns" do
|
|
user = insert(:user)
|
|
|
|
insert(:site,
|
|
allowed_event_props: ["dummy"],
|
|
memberships: [build(:site_membership, user: user, role: :admin)]
|
|
)
|
|
|
|
assert [] == Quota.features_usage(user)
|
|
end
|
|
end
|
|
|
|
describe "allowed_features_for/1" do
|
|
test "returns all grandfathered features when user is on an old plan" do
|
|
user_on_v1 = insert(:user, subscription: build(:subscription, paddle_plan_id: @v1_plan_id))
|
|
user_on_v2 = insert(:user, subscription: build(:subscription, paddle_plan_id: @v2_plan_id))
|
|
user_on_v3 = insert(:user, subscription: build(:subscription, paddle_plan_id: @v3_plan_id))
|
|
|
|
assert [Goals, StatsAPI, Props] == Quota.allowed_features_for(user_on_v1)
|
|
assert [Goals, StatsAPI, Props] == Quota.allowed_features_for(user_on_v2)
|
|
assert [Goals, StatsAPI, Props] == Quota.allowed_features_for(user_on_v3)
|
|
end
|
|
|
|
test "returns [Goals] when user is on free_10k plan" do
|
|
user = insert(:user, subscription: build(:subscription, paddle_plan_id: "free_10k"))
|
|
assert [Goals] == Quota.allowed_features_for(user)
|
|
end
|
|
|
|
test "returns all features when user is on an enterprise plan" do
|
|
user = insert(:user)
|
|
|
|
enterprise_plan =
|
|
insert(:enterprise_plan,
|
|
user_id: user.id,
|
|
monthly_pageview_limit: 100_000,
|
|
site_limit: 500
|
|
)
|
|
|
|
_subscription =
|
|
insert(:subscription, user_id: user.id, paddle_plan_id: enterprise_plan.paddle_plan_id)
|
|
|
|
assert Plausible.Billing.Feature.list() == Quota.allowed_features_for(user)
|
|
end
|
|
|
|
test "returns all features when user in on trial" do
|
|
user = insert(:user, trial_expiry_date: Timex.shift(Timex.now(), days: 7))
|
|
|
|
assert Plausible.Billing.Feature.list() == Quota.allowed_features_for(user)
|
|
end
|
|
|
|
test "returns previous plan limits for enterprise users who have not paid yet" do
|
|
user =
|
|
insert(:user,
|
|
enterprise_plan: build(:enterprise_plan, paddle_plan_id: "123321"),
|
|
subscription: build(:subscription, paddle_plan_id: @v1_plan_id)
|
|
)
|
|
|
|
assert [Goals, StatsAPI, Props] == Quota.allowed_features_for(user)
|
|
end
|
|
|
|
test "returns all features for enterprise users who have not upgraded yet and are on trial" do
|
|
user =
|
|
insert(:user,
|
|
enterprise_plan: build(:enterprise_plan, paddle_plan_id: "123321"),
|
|
subscription: nil
|
|
)
|
|
|
|
assert Plausible.Billing.Feature.list() == Quota.allowed_features_for(user)
|
|
end
|
|
|
|
test "returns all features for enterprise customers" do
|
|
user =
|
|
insert(:user,
|
|
enterprise_plan: build(:enterprise_plan, paddle_plan_id: "123321"),
|
|
subscription: build(:subscription, paddle_plan_id: "123321")
|
|
)
|
|
|
|
assert Plausible.Billing.Feature.list() == Quota.allowed_features_for(user)
|
|
end
|
|
|
|
test "returns all features for enterprise customers who are due to change a plan" do
|
|
user =
|
|
insert(:user,
|
|
enterprise_plan: build(:enterprise_plan, paddle_plan_id: "old-paddle-plan-id"),
|
|
subscription: build(:subscription, paddle_plan_id: "old-paddle-plan-id")
|
|
)
|
|
|
|
insert(:enterprise_plan, user_id: user.id, paddle_plan_id: "new-paddle-plan-id")
|
|
assert Plausible.Billing.Feature.list() == Quota.allowed_features_for(user)
|
|
end
|
|
end
|
|
end
|