mirror of
https://github.com/plausible/analytics.git
synced 2024-09-11 18:07:33 +03:00
Refactor: Add 'goals' feature to JSON plan files (#3435)
* fix text color in dark mode * rename a function * use aliases in quota.ex * rename a function * make Goals a similar feature to others but with a free option * rename a function * mix format
This commit is contained in:
parent
52d5fac362
commit
7674c94ace
@ -9,18 +9,25 @@ defmodule Plausible.Billing.Feature do
|
||||
When defining new features, the following options are expected by the
|
||||
`__using__` macro:
|
||||
|
||||
* `:name` - an atom representing the feature name in the plan JSON
|
||||
file (see also Plausible.Billing.Plan).
|
||||
|
||||
* `:display_name` - human-readable display name of the feature
|
||||
|
||||
* `:toggle_field` - the field in the %Plausible.Site{} schema that toggles
|
||||
the feature. If `nil` or not set, toggle/2 silently returns `:ok`
|
||||
|
||||
* `:extra_feature` - an atom representing the feature name in the plan JSON
|
||||
file (see also Plausible.Billing.Plan). If `nil` or not set,
|
||||
`check_availability/1` silently returns `:ok`
|
||||
* `:free` - if set to `true`, makes the `check_availability/1` function
|
||||
always return `:ok` (no matter the user's subscription status)
|
||||
|
||||
Functions defined by `__using__` can be overridden if needed.
|
||||
"""
|
||||
|
||||
@doc """
|
||||
Returns the atom representing the feature name in the plan JSON file.
|
||||
"""
|
||||
@callback name() :: atom()
|
||||
|
||||
@doc """
|
||||
Returns the human-readable display name of the feature.
|
||||
"""
|
||||
@ -32,7 +39,7 @@ defmodule Plausible.Billing.Feature do
|
||||
@callback toggle_field() :: atom()
|
||||
|
||||
@doc """
|
||||
Toggles the feature on and off for a site. Returns
|
||||
Toggles the feature on and off for a site. Returns
|
||||
`{:error, :upgrade_required}` when toggling a feature the site owner does not
|
||||
have access to.
|
||||
"""
|
||||
@ -51,9 +58,10 @@ defmodule Plausible.Billing.Feature do
|
||||
:ok | {:error, :upgrade_required} | {:error, :not_implemented}
|
||||
|
||||
@features [
|
||||
Plausible.Billing.Feature.Funnels,
|
||||
Plausible.Billing.Feature.Goals,
|
||||
Plausible.Billing.Feature.StatsAPI,
|
||||
Plausible.Billing.Feature.Props,
|
||||
Plausible.Billing.Feature.Funnels,
|
||||
Plausible.Billing.Feature.RevenueGoals
|
||||
]
|
||||
|
||||
@ -70,6 +78,9 @@ defmodule Plausible.Billing.Feature do
|
||||
@behaviour Plausible.Billing.Feature
|
||||
alias Plausible.Billing.Quota
|
||||
|
||||
@impl true
|
||||
def name, do: Keyword.get(unquote(opts), :name)
|
||||
|
||||
@impl true
|
||||
def display_name, do: Keyword.get(unquote(opts), :display_name)
|
||||
|
||||
@ -89,12 +100,10 @@ defmodule Plausible.Billing.Feature do
|
||||
|
||||
@impl true
|
||||
def check_availability(%Plausible.Auth.User{} = user) do
|
||||
extra_feature = Keyword.get(unquote(opts), :extra_feature)
|
||||
|
||||
cond do
|
||||
is_nil(extra_feature) -> :ok
|
||||
not FunWithFlags.enabled?(:business_tier, for: user) -> :ok
|
||||
extra_feature in Quota.extra_features_limit(user) -> :ok
|
||||
Keyword.get(unquote(opts), :free) -> :ok
|
||||
__MODULE__ in Quota.allowed_features_for(user) -> :ok
|
||||
true -> {:error, :upgrade_required}
|
||||
end
|
||||
end
|
||||
@ -122,36 +131,38 @@ end
|
||||
defmodule Plausible.Billing.Feature.Funnels do
|
||||
@moduledoc false
|
||||
use Plausible.Billing.Feature,
|
||||
name: :funnels,
|
||||
display_name: "Funnels",
|
||||
toggle_field: :funnels_enabled,
|
||||
extra_feature: :funnels
|
||||
toggle_field: :funnels_enabled
|
||||
end
|
||||
|
||||
defmodule Plausible.Billing.Feature.RevenueGoals do
|
||||
@moduledoc false
|
||||
use Plausible.Billing.Feature,
|
||||
display_name: "Revenue Goals",
|
||||
extra_feature: :revenue_goals
|
||||
name: :revenue_goals,
|
||||
display_name: "Revenue Goals"
|
||||
end
|
||||
|
||||
defmodule Plausible.Billing.Feature.Goals do
|
||||
@moduledoc false
|
||||
use Plausible.Billing.Feature,
|
||||
name: :goals,
|
||||
display_name: "Goals",
|
||||
toggle_field: :conversions_enabled
|
||||
toggle_field: :conversions_enabled,
|
||||
free: true
|
||||
end
|
||||
|
||||
defmodule Plausible.Billing.Feature.Props do
|
||||
@moduledoc false
|
||||
use Plausible.Billing.Feature,
|
||||
name: :props,
|
||||
display_name: "Custom Properties",
|
||||
toggle_field: :props_enabled,
|
||||
extra_feature: :props
|
||||
toggle_field: :props_enabled
|
||||
end
|
||||
|
||||
defmodule Plausible.Billing.Feature.StatsAPI do
|
||||
@moduledoc false
|
||||
use Plausible.Billing.Feature,
|
||||
display_name: "Stats API",
|
||||
extra_feature: :stats_api
|
||||
name: :stats_api,
|
||||
display_name: "Stats API"
|
||||
end
|
||||
|
@ -2,7 +2,7 @@ defmodule Plausible.Billing.Plan do
|
||||
@moduledoc false
|
||||
|
||||
@derive Jason.Encoder
|
||||
@enforce_keys ~w(kind site_limit monthly_pageview_limit team_member_limit extra_features volume monthly_product_id yearly_product_id)a
|
||||
@enforce_keys ~w(kind site_limit monthly_pageview_limit team_member_limit features volume monthly_product_id yearly_product_id)a
|
||||
defstruct @enforce_keys ++ [:monthly_cost, :yearly_cost]
|
||||
|
||||
@type t() ::
|
||||
@ -16,7 +16,7 @@ defmodule Plausible.Billing.Plan do
|
||||
yearly_cost: Money.t() | nil,
|
||||
monthly_product_id: String.t() | nil,
|
||||
yearly_product_id: String.t() | nil,
|
||||
extra_features: [atom()]
|
||||
features: [atom()]
|
||||
}
|
||||
| :enterprise
|
||||
|
||||
@ -31,8 +31,6 @@ defmodule Plausible.Billing.Plans do
|
||||
alias Plausible.Billing.{Subscription, Plan, EnterprisePlan}
|
||||
alias Plausible.Auth.User
|
||||
|
||||
@available_features ["props", "revenue_goals", "funnels", "stats_api"]
|
||||
|
||||
for f <- [
|
||||
:plans_v1,
|
||||
:plans_v2,
|
||||
@ -56,20 +54,26 @@ defmodule Plausible.Billing.Plans do
|
||||
_any -> raise ArgumentError, "Failed to parse team member limit from plan JSON files"
|
||||
end
|
||||
|
||||
extra_features =
|
||||
Enum.map(raw.extra_features, fn feature ->
|
||||
if feature in @available_features,
|
||||
do: String.to_atom(feature),
|
||||
else: raise(ArgumentError, "Failed to parse extra features from plan JSON files")
|
||||
features =
|
||||
Plausible.Billing.Feature.list()
|
||||
|> Enum.filter(fn module ->
|
||||
to_string(module.name()) in raw.features
|
||||
end)
|
||||
|
||||
if length(features) != length(raw.features),
|
||||
do:
|
||||
raise(
|
||||
ArgumentError,
|
||||
"Unrecognized feature(s) in #{inspect(raw.features)} (#{f}.json)"
|
||||
)
|
||||
|
||||
volume = PlausibleWeb.StatsView.large_number_format(raw.monthly_pageview_limit)
|
||||
|
||||
raw
|
||||
|> Map.put(:volume, volume)
|
||||
|> Map.put(:kind, String.to_atom(raw.kind))
|
||||
|> Map.put(:team_member_limit, team_member_limit)
|
||||
|> Map.put(:extra_features, extra_features)
|
||||
|> Map.put(:features, features)
|
||||
|> Plan.new()
|
||||
end)
|
||||
|
||||
|
@ -4,7 +4,9 @@ defmodule Plausible.Billing.Quota do
|
||||
"""
|
||||
|
||||
import Ecto.Query
|
||||
alias Plausible.Billing.Plans
|
||||
alias Plausible.Billing
|
||||
alias Plausible.Billing.{Plan, Plans, Subscription, EnterprisePlan, Feature}
|
||||
alias Plausible.Billing.Feature.{Goals, RevenueGoals, Funnels, Props}
|
||||
|
||||
@limit_sites_since ~D[2021-05-05]
|
||||
@spec site_limit(Plausible.Auth.User.t()) :: non_neg_integer() | :unlimited
|
||||
@ -28,8 +30,8 @@ defmodule Plausible.Billing.Quota do
|
||||
user = Plausible.Users.with_subscription(user)
|
||||
|
||||
case Plans.get_subscription_plan(user.subscription) do
|
||||
%Plausible.Billing.EnterprisePlan{} -> :unlimited
|
||||
%Plausible.Billing.Plan{site_limit: site_limit} -> site_limit
|
||||
%EnterprisePlan{} -> :unlimited
|
||||
%Plan{site_limit: site_limit} -> site_limit
|
||||
:free_10k -> @site_limit_for_free_10k
|
||||
nil -> @site_limit_for_trials
|
||||
end
|
||||
@ -46,17 +48,17 @@ defmodule Plausible.Billing.Quota do
|
||||
@monthly_pageview_limit_for_free_10k 10_000
|
||||
@monthly_pageview_limit_for_trials :unlimited
|
||||
|
||||
@spec monthly_pageview_limit(Plausible.Billing.Subscription.t()) ::
|
||||
@spec monthly_pageview_limit(Subscription.t()) ::
|
||||
non_neg_integer() | :unlimited
|
||||
@doc """
|
||||
Returns the limit of pageviews for a subscription.
|
||||
"""
|
||||
def monthly_pageview_limit(subscription) do
|
||||
case Plans.get_subscription_plan(subscription) do
|
||||
%Plausible.Billing.EnterprisePlan{monthly_pageview_limit: limit} ->
|
||||
%EnterprisePlan{monthly_pageview_limit: limit} ->
|
||||
limit
|
||||
|
||||
%Plausible.Billing.Plan{monthly_pageview_limit: limit} ->
|
||||
%Plan{monthly_pageview_limit: limit} ->
|
||||
limit
|
||||
|
||||
:free_10k ->
|
||||
@ -80,7 +82,7 @@ defmodule Plausible.Billing.Quota do
|
||||
"""
|
||||
def monthly_pageview_usage(user) do
|
||||
user
|
||||
|> Plausible.Billing.usage_breakdown()
|
||||
|> Billing.usage_breakdown()
|
||||
|> Tuple.sum()
|
||||
end
|
||||
|
||||
@ -93,8 +95,8 @@ defmodule Plausible.Billing.Quota do
|
||||
user = Plausible.Users.with_subscription(user)
|
||||
|
||||
case Plans.get_subscription_plan(user.subscription) do
|
||||
%Plausible.Billing.EnterprisePlan{} -> :unlimited
|
||||
%Plausible.Billing.Plan{team_member_limit: limit} -> limit
|
||||
%EnterprisePlan{} -> :unlimited
|
||||
%Plan{team_member_limit: limit} -> limit
|
||||
:free_10k -> :unlimited
|
||||
nil -> @team_member_limit_for_trials
|
||||
end
|
||||
@ -129,11 +131,13 @@ defmodule Plausible.Billing.Quota do
|
||||
Plausible.Repo.one(query)
|
||||
end
|
||||
|
||||
@spec extra_features_usage(Plausible.Auth.User.t()) :: [atom()]
|
||||
@spec features_usage(Plausible.Auth.User.t()) :: [atom()]
|
||||
@doc """
|
||||
Returns a list of extra features the given user's sites uses.
|
||||
Returns a list of features the given user is using. At the
|
||||
current stage, the only features that we need to know the
|
||||
usage for are `Props`, `Funnels`, and `RevenueGoals`
|
||||
"""
|
||||
def extra_features_usage(user) do
|
||||
def features_usage(user) do
|
||||
props_usage_query =
|
||||
from s in Plausible.Site,
|
||||
inner_join: os in subquery(owned_sites_query(user)),
|
||||
@ -152,9 +156,9 @@ defmodule Plausible.Billing.Quota do
|
||||
where: not is_nil(g.currency)
|
||||
|
||||
queries = [
|
||||
props: props_usage_query,
|
||||
funnels: funnels_usage_query,
|
||||
revenue_goals: revenue_goals_usage
|
||||
{Props, props_usage_query},
|
||||
{Funnels, funnels_usage_query},
|
||||
{RevenueGoals, revenue_goals_usage}
|
||||
]
|
||||
|
||||
Enum.reduce(queries, [], fn {feature, query}, acc ->
|
||||
@ -162,19 +166,18 @@ defmodule Plausible.Billing.Quota do
|
||||
end)
|
||||
end
|
||||
|
||||
@all_features [:props, :revenue_goals, :funnels, :stats_api]
|
||||
@doc """
|
||||
Returns a list of extra features the user can use. Trial users have the
|
||||
Returns a list of features the user can use. Trial users have the
|
||||
ability to use all features during their trial.
|
||||
"""
|
||||
def extra_features_limit(user) do
|
||||
def allowed_features_for(user) do
|
||||
user = Plausible.Users.with_subscription(user)
|
||||
|
||||
case Plans.get_subscription_plan(user.subscription) do
|
||||
%Plausible.Billing.EnterprisePlan{} -> @all_features
|
||||
%Plausible.Billing.Plan{extra_features: extra_features} -> extra_features
|
||||
:free_10k -> []
|
||||
nil -> @all_features
|
||||
%EnterprisePlan{} -> Feature.list()
|
||||
%Plan{features: features} -> features
|
||||
:free_10k -> [Goals]
|
||||
nil -> Feature.list()
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -15,7 +15,7 @@ defmodule PlausibleWeb.Components.Billing do
|
||||
attr(:rest, :global)
|
||||
|
||||
# credo:disable-for-next-line Credo.Check.Refactor.CyclomaticComplexity
|
||||
def extra_feature_notice(assigns) do
|
||||
def premium_feature_notice(assigns) do
|
||||
private_preview? = not FunWithFlags.enabled?(:business_tier, for: assigns.current_user)
|
||||
display_upgrade_link? = assigns.current_user.id == assigns.billable_user.id
|
||||
has_access? = assigns.feature_mod.check_availability(assigns.billable_user) == :ok
|
||||
|
@ -381,7 +381,10 @@ defmodule PlausibleWeb.Live.ChoosePlan do
|
||||
</p>
|
||||
<p class="h-4 mt-1"></p>
|
||||
<.contact_button class="" />
|
||||
<ul role="list" class="mt-8 space-y-3 text-sm leading-6 xl:mt-10 text-gray-300">
|
||||
<ul
|
||||
role="list"
|
||||
class="mt-8 space-y-3 text-sm leading-6 xl:mt-10 text-gray-300 dark:text-gray-100"
|
||||
>
|
||||
<li class="flex gap-x-3">
|
||||
<.check_icon class="text-white dark:text-green-600" /> Unlimited products
|
||||
</li>
|
||||
|
@ -192,7 +192,7 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
|
||||
</button>
|
||||
|
||||
<span x-show="active">
|
||||
<PlausibleWeb.Components.Billing.extra_feature_notice
|
||||
<PlausibleWeb.Components.Billing.premium_feature_notice
|
||||
billable_user={@site.owner}
|
||||
current_user={@current_user}
|
||||
feature_mod={Plausible.Billing.Feature.RevenueGoals}
|
||||
|
@ -319,7 +319,7 @@
|
||||
<h2 class="text-xl font-black dark:text-gray-100">API Keys</h2>
|
||||
<div class="my-4 border-b border-gray-300 dark:border-gray-500"></div>
|
||||
|
||||
<PlausibleWeb.Components.Billing.extra_feature_notice
|
||||
<PlausibleWeb.Components.Billing.premium_feature_notice
|
||||
billable_user={@current_user}
|
||||
current_user={@current_user}
|
||||
feature_mod={Plausible.Billing.Feature.StatsAPI}
|
||||
|
@ -1,5 +1,5 @@
|
||||
<section class="shadow bg-white dark:bg-gray-800 sm:rounded-md sm:overflow-hidden">
|
||||
<PlausibleWeb.Components.Billing.extra_feature_notice
|
||||
<PlausibleWeb.Components.Billing.premium_feature_notice
|
||||
billable_user={@site.owner}
|
||||
current_user={@current_user}
|
||||
feature_mod={Plausible.Billing.Feature.Funnels}
|
||||
|
@ -1,5 +1,5 @@
|
||||
<section class="shadow bg-white dark:bg-gray-800 sm:rounded-md sm:overflow-hidden">
|
||||
<PlausibleWeb.Components.Billing.extra_feature_notice
|
||||
<PlausibleWeb.Components.Billing.premium_feature_notice
|
||||
billable_user={@site.owner}
|
||||
current_user={@current_user}
|
||||
feature_mod={Plausible.Billing.Feature.Props}
|
||||
|
@ -6,7 +6,7 @@
|
||||
"yearly_product_id":"572810",
|
||||
"site_limit":50,
|
||||
"team_member_limit":"unlimited",
|
||||
"extra_features":["props","stats_api"]
|
||||
"features":["goals","props","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"growth",
|
||||
@ -15,7 +15,7 @@
|
||||
"yearly_product_id":"590752",
|
||||
"site_limit":50,
|
||||
"team_member_limit":"unlimited",
|
||||
"extra_features":["props","stats_api"]
|
||||
"features":["goals","props","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"growth",
|
||||
@ -24,7 +24,7 @@
|
||||
"yearly_product_id":"597486",
|
||||
"site_limit":50,
|
||||
"team_member_limit":"unlimited",
|
||||
"extra_features":["props","stats_api"]
|
||||
"features":["goals","props","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"growth",
|
||||
@ -33,7 +33,7 @@
|
||||
"yearly_product_id":"597488",
|
||||
"site_limit":50,
|
||||
"team_member_limit":"unlimited",
|
||||
"extra_features":["props","stats_api"]
|
||||
"features":["goals","props","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"growth",
|
||||
@ -42,7 +42,7 @@
|
||||
"yearly_product_id":"597643",
|
||||
"site_limit":50,
|
||||
"team_member_limit":"unlimited",
|
||||
"extra_features":["props","stats_api"]
|
||||
"features":["goals","props","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"growth",
|
||||
@ -51,7 +51,7 @@
|
||||
"yearly_product_id":"597310",
|
||||
"site_limit":50,
|
||||
"team_member_limit":"unlimited",
|
||||
"extra_features":["props","stats_api"]
|
||||
"features":["goals","props","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"growth",
|
||||
@ -60,7 +60,7 @@
|
||||
"yearly_product_id":"597312",
|
||||
"site_limit":50,
|
||||
"team_member_limit":"unlimited",
|
||||
"extra_features":["props","stats_api"]
|
||||
"features":["goals","props","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"growth",
|
||||
@ -69,7 +69,7 @@
|
||||
"yearly_product_id":"642354",
|
||||
"site_limit":50,
|
||||
"team_member_limit":"unlimited",
|
||||
"extra_features":["props","stats_api"]
|
||||
"features":["goals","props","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"growth",
|
||||
@ -78,7 +78,7 @@
|
||||
"yearly_product_id":"642356",
|
||||
"site_limit":50,
|
||||
"team_member_limit":"unlimited",
|
||||
"extra_features":["props","stats_api"]
|
||||
"features":["goals","props","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"growth",
|
||||
@ -87,6 +87,6 @@
|
||||
"yearly_product_id":"650653",
|
||||
"site_limit":50,
|
||||
"team_member_limit":"unlimited",
|
||||
"extra_features":["props","stats_api"]
|
||||
"features":["goals","props","stats_api"]
|
||||
}
|
||||
]
|
||||
|
@ -6,7 +6,7 @@
|
||||
"yearly_product_id":"653232",
|
||||
"site_limit":50,
|
||||
"team_member_limit":"unlimited",
|
||||
"extra_features":["props","stats_api"]
|
||||
"features":["goals","props","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"growth",
|
||||
@ -15,7 +15,7 @@
|
||||
"yearly_product_id":"653234",
|
||||
"site_limit":50,
|
||||
"team_member_limit":"unlimited",
|
||||
"extra_features":["props","stats_api"]
|
||||
"features":["goals","props","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"growth",
|
||||
@ -24,7 +24,7 @@
|
||||
"yearly_product_id":"653236",
|
||||
"site_limit":50,
|
||||
"team_member_limit":"unlimited",
|
||||
"extra_features":["props","stats_api"]
|
||||
"features":["goals","props","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"growth",
|
||||
@ -33,7 +33,7 @@
|
||||
"yearly_product_id":"653239",
|
||||
"site_limit":50,
|
||||
"team_member_limit":"unlimited",
|
||||
"extra_features":["props","stats_api"]
|
||||
"features":["goals","props","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"growth",
|
||||
@ -42,7 +42,7 @@
|
||||
"yearly_product_id":"653242",
|
||||
"site_limit":50,
|
||||
"team_member_limit":"unlimited",
|
||||
"extra_features":["props","stats_api"]
|
||||
"features":["goals","props","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"growth",
|
||||
@ -51,7 +51,7 @@
|
||||
"yearly_product_id":"653254",
|
||||
"site_limit":50,
|
||||
"team_member_limit":"unlimited",
|
||||
"extra_features":["props","stats_api"]
|
||||
"features":["goals","props","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"growth",
|
||||
@ -60,7 +60,7 @@
|
||||
"yearly_product_id":"653256",
|
||||
"site_limit":50,
|
||||
"team_member_limit":"unlimited",
|
||||
"extra_features":["props","stats_api"]
|
||||
"features":["goals","props","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"growth",
|
||||
@ -69,7 +69,7 @@
|
||||
"yearly_product_id":"653257",
|
||||
"site_limit":50,
|
||||
"team_member_limit":"unlimited",
|
||||
"extra_features":["props","stats_api"]
|
||||
"features":["goals","props","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"growth",
|
||||
@ -78,7 +78,7 @@
|
||||
"yearly_product_id":"653258",
|
||||
"site_limit":50,
|
||||
"team_member_limit":"unlimited",
|
||||
"extra_features":["props","stats_api"]
|
||||
"features":["goals","props","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"growth",
|
||||
@ -87,6 +87,6 @@
|
||||
"yearly_product_id":"653259",
|
||||
"site_limit":50,
|
||||
"team_member_limit":"unlimited",
|
||||
"extra_features":["props","stats_api"]
|
||||
"features":["goals","props","stats_api"]
|
||||
}
|
||||
]
|
||||
|
@ -6,7 +6,7 @@
|
||||
"yearly_product_id":"749343",
|
||||
"site_limit":50,
|
||||
"team_member_limit":"unlimited",
|
||||
"extra_features":["props","stats_api"]
|
||||
"features":["goals","props","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"growth",
|
||||
@ -15,7 +15,7 @@
|
||||
"yearly_product_id":"749345",
|
||||
"site_limit":50,
|
||||
"team_member_limit":"unlimited",
|
||||
"extra_features":["props","stats_api"]
|
||||
"features":["goals","props","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"growth",
|
||||
@ -24,7 +24,7 @@
|
||||
"yearly_product_id":"749347",
|
||||
"site_limit":50,
|
||||
"team_member_limit":"unlimited",
|
||||
"extra_features":["props","stats_api"]
|
||||
"features":["goals","props","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"growth",
|
||||
@ -33,7 +33,7 @@
|
||||
"yearly_product_id":"749349",
|
||||
"site_limit":50,
|
||||
"team_member_limit":"unlimited",
|
||||
"extra_features":["props","stats_api"]
|
||||
"features":["goals","props","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"growth",
|
||||
@ -42,7 +42,7 @@
|
||||
"yearly_product_id":"749352",
|
||||
"site_limit":50,
|
||||
"team_member_limit":"unlimited",
|
||||
"extra_features":["props","stats_api"]
|
||||
"features":["goals","props","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"growth",
|
||||
@ -51,7 +51,7 @@
|
||||
"yearly_product_id":"749355",
|
||||
"site_limit":50,
|
||||
"team_member_limit":"unlimited",
|
||||
"extra_features":["props","stats_api"]
|
||||
"features":["goals","props","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"growth",
|
||||
@ -60,7 +60,7 @@
|
||||
"yearly_product_id":"749357",
|
||||
"site_limit":50,
|
||||
"team_member_limit":"unlimited",
|
||||
"extra_features":["props","stats_api"]
|
||||
"features":["goals","props","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"growth",
|
||||
@ -69,6 +69,6 @@
|
||||
"yearly_product_id":"749359",
|
||||
"site_limit":50,
|
||||
"team_member_limit":"unlimited",
|
||||
"extra_features":["props","stats_api"]
|
||||
"features":["goals","props","stats_api"]
|
||||
}
|
||||
]
|
||||
|
@ -6,7 +6,7 @@
|
||||
"yearly_product_id":"change-me-749343",
|
||||
"site_limit":10,
|
||||
"team_member_limit":5,
|
||||
"extra_features":[]
|
||||
"features":["goals"]
|
||||
},
|
||||
{
|
||||
"kind":"growth",
|
||||
@ -15,7 +15,7 @@
|
||||
"yearly_product_id":"change-me-749345",
|
||||
"site_limit":10,
|
||||
"team_member_limit":5,
|
||||
"extra_features":[]
|
||||
"features":["goals"]
|
||||
},
|
||||
{
|
||||
"kind":"growth",
|
||||
@ -24,7 +24,7 @@
|
||||
"yearly_product_id":"change-me-749347",
|
||||
"site_limit":10,
|
||||
"team_member_limit":5,
|
||||
"extra_features":[]
|
||||
"features":["goals"]
|
||||
},
|
||||
{
|
||||
"kind":"growth",
|
||||
@ -33,7 +33,7 @@
|
||||
"yearly_product_id":"change-me-749349",
|
||||
"site_limit":10,
|
||||
"team_member_limit":5,
|
||||
"extra_features":[]
|
||||
"features":["goals"]
|
||||
},
|
||||
{
|
||||
"kind":"growth",
|
||||
@ -42,7 +42,7 @@
|
||||
"yearly_product_id":"change-me-749352",
|
||||
"site_limit":10,
|
||||
"team_member_limit":5,
|
||||
"extra_features":[]
|
||||
"features":["goals"]
|
||||
},
|
||||
{
|
||||
"kind":"growth",
|
||||
@ -51,7 +51,7 @@
|
||||
"yearly_product_id":"change-me-749355",
|
||||
"site_limit":10,
|
||||
"team_member_limit":5,
|
||||
"extra_features":[]
|
||||
"features":["goals"]
|
||||
},
|
||||
{
|
||||
"kind":"growth",
|
||||
@ -60,7 +60,7 @@
|
||||
"yearly_product_id":"change-me-749357",
|
||||
"site_limit":10,
|
||||
"team_member_limit":5,
|
||||
"extra_features":[]
|
||||
"features":["goals"]
|
||||
},
|
||||
{
|
||||
"kind":"growth",
|
||||
@ -69,7 +69,7 @@
|
||||
"yearly_product_id":"change-me-749359",
|
||||
"site_limit":10,
|
||||
"team_member_limit":5,
|
||||
"extra_features":[]
|
||||
"features":["goals"]
|
||||
},
|
||||
{
|
||||
"kind":"business",
|
||||
@ -78,7 +78,7 @@
|
||||
"yearly_product_id":"change-me-b749343",
|
||||
"site_limit":50,
|
||||
"team_member_limit":50,
|
||||
"extra_features":["props","revenue_goals","funnels","stats_api"]
|
||||
"features":["goals","props","revenue_goals","funnels","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"business",
|
||||
@ -87,7 +87,7 @@
|
||||
"yearly_product_id":"change-me-b749345",
|
||||
"site_limit":50,
|
||||
"team_member_limit":50,
|
||||
"extra_features":["props","revenue_goals","funnels","stats_api"]
|
||||
"features":["goals","props","revenue_goals","funnels","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"business",
|
||||
@ -96,7 +96,7 @@
|
||||
"yearly_product_id":"change-me-b749347",
|
||||
"site_limit":50,
|
||||
"team_member_limit":50,
|
||||
"extra_features":["props","revenue_goals","funnels","stats_api"]
|
||||
"features":["goals","props","revenue_goals","funnels","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"business",
|
||||
@ -105,7 +105,7 @@
|
||||
"yearly_product_id":"change-me-b749349",
|
||||
"site_limit":50,
|
||||
"team_member_limit":50,
|
||||
"extra_features":["props","revenue_goals","funnels","stats_api"]
|
||||
"features":["goals","props","revenue_goals","funnels","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"business",
|
||||
@ -114,7 +114,7 @@
|
||||
"yearly_product_id":"change-me-b749352",
|
||||
"site_limit":50,
|
||||
"team_member_limit":50,
|
||||
"extra_features":["props","revenue_goals","funnels","stats_api"]
|
||||
"features":["goals","props","revenue_goals","funnels","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"business",
|
||||
@ -123,7 +123,7 @@
|
||||
"yearly_product_id":"change-me-b749355",
|
||||
"site_limit":50,
|
||||
"team_member_limit":50,
|
||||
"extra_features":["props","revenue_goals","funnels","stats_api"]
|
||||
"features":["goals","props","revenue_goals","funnels","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"business",
|
||||
@ -132,7 +132,7 @@
|
||||
"yearly_product_id":"change-me-b749357",
|
||||
"site_limit":50,
|
||||
"team_member_limit":50,
|
||||
"extra_features":["props","revenue_goals","funnels","stats_api"]
|
||||
"features":["goals","props","revenue_goals","funnels","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"business",
|
||||
@ -141,6 +141,6 @@
|
||||
"yearly_product_id":"change-me-b749359",
|
||||
"site_limit":50,
|
||||
"team_member_limit":50,
|
||||
"extra_features":["props","revenue_goals","funnels","stats_api"]
|
||||
"features":["goals","props","revenue_goals","funnels","stats_api"]
|
||||
}
|
||||
]
|
||||
|
@ -6,7 +6,7 @@
|
||||
"yearly_product_id":"63859",
|
||||
"site_limit":10,
|
||||
"team_member_limit":5,
|
||||
"extra_features":["props","stats_api"]
|
||||
"features":["goals","props","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"growth",
|
||||
@ -15,7 +15,7 @@
|
||||
"yearly_product_id":"63860",
|
||||
"site_limit":10,
|
||||
"team_member_limit":5,
|
||||
"extra_features":["props","stats_api"]
|
||||
"features":["goals","props","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"growth",
|
||||
@ -24,7 +24,7 @@
|
||||
"yearly_product_id":"63861",
|
||||
"site_limit":10,
|
||||
"team_member_limit":5,
|
||||
"extra_features":["props","stats_api"]
|
||||
"features":["goals","props","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"growth",
|
||||
@ -33,7 +33,7 @@
|
||||
"yearly_product_id":"63862",
|
||||
"site_limit":10,
|
||||
"team_member_limit":5,
|
||||
"extra_features":["props","stats_api"]
|
||||
"features":["goals","props","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"growth",
|
||||
@ -42,7 +42,7 @@
|
||||
"yearly_product_id":"63863",
|
||||
"site_limit":10,
|
||||
"team_member_limit":5,
|
||||
"extra_features":["props","stats_api"]
|
||||
"features":["goals","props","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"growth",
|
||||
@ -51,7 +51,7 @@
|
||||
"yearly_product_id":"63864",
|
||||
"site_limit":10,
|
||||
"team_member_limit":5,
|
||||
"extra_features":["props","stats_api"]
|
||||
"features":["goals","props","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"growth",
|
||||
@ -60,7 +60,7 @@
|
||||
"yearly_product_id":"63865",
|
||||
"site_limit":10,
|
||||
"team_member_limit":5,
|
||||
"extra_features":["props","stats_api"]
|
||||
"features":["goals","props","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"growth",
|
||||
@ -69,7 +69,7 @@
|
||||
"yearly_product_id":"63866",
|
||||
"site_limit":10,
|
||||
"team_member_limit":5,
|
||||
"extra_features":["props","stats_api"]
|
||||
"features":["goals","props","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"business",
|
||||
@ -78,7 +78,7 @@
|
||||
"yearly_product_id":"63867",
|
||||
"site_limit":50,
|
||||
"team_member_limit":50,
|
||||
"extra_features":["props", "revenue_goals", "funnels","stats_api"]
|
||||
"features":["goals","props", "revenue_goals", "funnels","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"business",
|
||||
@ -87,7 +87,7 @@
|
||||
"yearly_product_id":"63868",
|
||||
"site_limit":50,
|
||||
"team_member_limit":50,
|
||||
"extra_features":["props", "revenue_goals", "funnels","stats_api"]
|
||||
"features":["goals","props", "revenue_goals", "funnels","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"business",
|
||||
@ -96,7 +96,7 @@
|
||||
"yearly_product_id":"63869",
|
||||
"site_limit":50,
|
||||
"team_member_limit":50,
|
||||
"extra_features":["props", "revenue_goals", "funnels","stats_api"]
|
||||
"features":["goals","props", "revenue_goals", "funnels","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"business",
|
||||
@ -105,7 +105,7 @@
|
||||
"yearly_product_id":"63870",
|
||||
"site_limit":50,
|
||||
"team_member_limit":50,
|
||||
"extra_features":["props", "revenue_goals", "funnels","stats_api"]
|
||||
"features":["goals","props", "revenue_goals", "funnels","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"business",
|
||||
@ -114,7 +114,7 @@
|
||||
"yearly_product_id":"63871",
|
||||
"site_limit":50,
|
||||
"team_member_limit":50,
|
||||
"extra_features":["props", "revenue_goals", "funnels","stats_api"]
|
||||
"features":["goals","props", "revenue_goals", "funnels","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"business",
|
||||
@ -123,7 +123,7 @@
|
||||
"yearly_product_id":"63872",
|
||||
"site_limit":50,
|
||||
"team_member_limit":50,
|
||||
"extra_features":["props", "revenue_goals", "funnels","stats_api"]
|
||||
"features":["goals","props", "revenue_goals", "funnels","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"business",
|
||||
@ -132,7 +132,7 @@
|
||||
"yearly_product_id":"63873",
|
||||
"site_limit":50,
|
||||
"team_member_limit":50,
|
||||
"extra_features":["props", "revenue_goals", "funnels","stats_api"]
|
||||
"features":["goals","props", "revenue_goals", "funnels","stats_api"]
|
||||
},
|
||||
{
|
||||
"kind":"business",
|
||||
@ -141,6 +141,6 @@
|
||||
"yearly_product_id":"63874",
|
||||
"site_limit":50,
|
||||
"team_member_limit":50,
|
||||
"extra_features":["props", "revenue_goals", "funnels","stats_api"]
|
||||
"features":["goals","props", "revenue_goals", "funnels","stats_api"]
|
||||
}
|
||||
]
|
||||
|
@ -6,6 +6,6 @@
|
||||
"monthly_product_id":null,
|
||||
"site_limit":50,
|
||||
"team_member_limit":"unlimited",
|
||||
"extra_features":["props"]
|
||||
"features":["goals","props"]
|
||||
}
|
||||
]
|
||||
|
@ -6,6 +6,6 @@
|
||||
"yearly_product_id":null,
|
||||
"site_limit":50,
|
||||
"team_member_limit":"unlimited",
|
||||
"extra_features":["props"]
|
||||
"features":["goals","props"]
|
||||
}
|
||||
]
|
||||
|
@ -1,6 +1,7 @@
|
||||
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"
|
||||
@ -364,13 +365,13 @@ defmodule Plausible.Billing.QuotaTest do
|
||||
end
|
||||
end
|
||||
|
||||
describe "extra_features_usage/1" do
|
||||
describe "features_usage/1" do
|
||||
test "returns an empty list" do
|
||||
user = insert(:user)
|
||||
assert [] == Quota.extra_features_usage(user)
|
||||
assert [] == Quota.features_usage(user)
|
||||
end
|
||||
|
||||
test "returns :props when user uses custom props" do
|
||||
test "returns [Props] when user uses custom props" do
|
||||
user = insert(:user)
|
||||
|
||||
insert(:site,
|
||||
@ -378,10 +379,10 @@ defmodule Plausible.Billing.QuotaTest do
|
||||
memberships: [build(:site_membership, user: user, role: :owner)]
|
||||
)
|
||||
|
||||
assert [:props] == Quota.extra_features_usage(user)
|
||||
assert [Props] == Quota.features_usage(user)
|
||||
end
|
||||
|
||||
test "returns :funnels when user uses funnels" do
|
||||
test "returns [Funnels] when user uses funnels" do
|
||||
user = insert(:user)
|
||||
site = insert(:site, memberships: [build(:site_membership, user: user, role: :owner)])
|
||||
|
||||
@ -389,18 +390,18 @@ defmodule Plausible.Billing.QuotaTest do
|
||||
steps = Enum.map(goals, &%{"goal_id" => &1.id})
|
||||
Plausible.Funnels.create(site, "dummy", steps)
|
||||
|
||||
assert [:funnels] == Quota.extra_features_usage(user)
|
||||
assert [Funnels] == Quota.features_usage(user)
|
||||
end
|
||||
|
||||
test "returns :revenue_goals when user uses revenue goals" do
|
||||
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 [:revenue_goals] == Quota.extra_features_usage(user)
|
||||
assert [RevenueGoals] == Quota.features_usage(user)
|
||||
end
|
||||
|
||||
test "returns multiple extra features" do
|
||||
test "returns multiple features" do
|
||||
user = insert(:user)
|
||||
|
||||
site =
|
||||
@ -415,7 +416,7 @@ defmodule Plausible.Billing.QuotaTest do
|
||||
steps = Enum.map(goals, &%{"goal_id" => &1.id})
|
||||
Plausible.Funnels.create(site, "dummy", steps)
|
||||
|
||||
assert [:revenue_goals, :funnels, :props] == Quota.extra_features_usage(user)
|
||||
assert [RevenueGoals, Funnels, Props] == Quota.features_usage(user)
|
||||
end
|
||||
|
||||
test "accounts only for sites the user owns" do
|
||||
@ -426,27 +427,27 @@ defmodule Plausible.Billing.QuotaTest do
|
||||
memberships: [build(:site_membership, user: user, role: :admin)]
|
||||
)
|
||||
|
||||
assert [] == Quota.extra_features_usage(user)
|
||||
assert [] == Quota.features_usage(user)
|
||||
end
|
||||
end
|
||||
|
||||
describe "extra_features_limit/1" do
|
||||
test "returns props when user is on an old plan" do
|
||||
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 [:props, :stats_api] == Quota.extra_features_limit(user_on_v1)
|
||||
assert [:props, :stats_api] == Quota.extra_features_limit(user_on_v2)
|
||||
assert [:props, :stats_api] == Quota.extra_features_limit(user_on_v3)
|
||||
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 an empty list when user is on free_10k plan" do
|
||||
test "returns [Goals] when user is on free_10k plan" do
|
||||
user = insert(:user, subscription: build(:subscription, paddle_plan_id: "free_10k"))
|
||||
assert [] == Quota.extra_features_limit(user)
|
||||
assert [Goals] == Quota.allowed_features_for(user)
|
||||
end
|
||||
|
||||
test "returns all extra features when user is on an enterprise plan" do
|
||||
test "returns all features when user is on an enterprise plan" do
|
||||
user = insert(:user)
|
||||
|
||||
enterprise_plan =
|
||||
@ -459,12 +460,13 @@ defmodule Plausible.Billing.QuotaTest do
|
||||
_subscription =
|
||||
insert(:subscription, user_id: user.id, paddle_plan_id: enterprise_plan.paddle_plan_id)
|
||||
|
||||
assert [:props, :revenue_goals, :funnels, :stats_api] == Quota.extra_features_limit(user)
|
||||
assert Plausible.Billing.Feature.list() == Quota.allowed_features_for(user)
|
||||
end
|
||||
|
||||
test "returns all extra features when user in on trial" do
|
||||
test "returns all features when user in on trial" do
|
||||
user = insert(:user, trial_expiry_date: Timex.shift(Timex.now(), days: 7))
|
||||
assert [:props, :revenue_goals, :funnels, :stats_api] == Quota.extra_features_limit(user)
|
||||
|
||||
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
|
||||
@ -474,30 +476,30 @@ defmodule Plausible.Billing.QuotaTest do
|
||||
subscription: build(:subscription, paddle_plan_id: @v1_plan_id)
|
||||
)
|
||||
|
||||
assert [:props, :stats_api] == Quota.extra_features_limit(user)
|
||||
assert [Goals, StatsAPI, Props] == Quota.allowed_features_for(user)
|
||||
end
|
||||
|
||||
test "returns trial limits for enterprise users who have not upgraded yet and are on trial" do
|
||||
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 [:props, :revenue_goals, :funnels, :stats_api] == Quota.extra_features_limit(user)
|
||||
assert Plausible.Billing.Feature.list() == Quota.allowed_features_for(user)
|
||||
end
|
||||
|
||||
test "returns all extra features for enterprise customers" do
|
||||
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 [:props, :revenue_goals, :funnels, :stats_api] == Quota.extra_features_limit(user)
|
||||
assert Plausible.Billing.Feature.list() == Quota.allowed_features_for(user)
|
||||
end
|
||||
|
||||
test "returns all extra features for enterprise customers who are due to change a plan" do
|
||||
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"),
|
||||
@ -505,7 +507,7 @@ defmodule Plausible.Billing.QuotaTest do
|
||||
)
|
||||
|
||||
insert(:enterprise_plan, user_id: user.id, paddle_plan_id: "new-paddle-plan-id")
|
||||
assert [:props, :revenue_goals, :funnels, :stats_api] == Quota.extra_features_limit(user)
|
||||
assert Plausible.Billing.Feature.list() == Quota.allowed_features_for(user)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -6,10 +6,10 @@ defmodule PlausibleWeb.Components.BillingTest do
|
||||
@v4_growth_plan_id "change-me-749342"
|
||||
@v4_business_plan_id "change-me-b749342"
|
||||
|
||||
test "extra_feature_notice/1 renders a message when user is on trial" do
|
||||
test "premium_feature_notice/1 renders a message when user is on trial" do
|
||||
me = insert(:user)
|
||||
|
||||
assert render_component(&Billing.extra_feature_notice/1,
|
||||
assert render_component(&Billing.premium_feature_notice/1,
|
||||
billable_user: me,
|
||||
current_user: me,
|
||||
feature_mod: Plausible.Billing.Feature.Props
|
||||
@ -17,11 +17,11 @@ defmodule PlausibleWeb.Components.BillingTest do
|
||||
"Custom Properties is part of the Plausible Business plan. You can access it during your trial"
|
||||
end
|
||||
|
||||
test "extra_feature_notice/1 renders an upgrade link when user is the site owner and does not have access to the feature" do
|
||||
test "premium_feature_notice/1 renders an upgrade link when user is the site owner and does not have access to the feature" do
|
||||
me = insert(:user, subscription: build(:subscription, paddle_plan_id: @v4_growth_plan_id))
|
||||
|
||||
rendered =
|
||||
render_component(&Billing.extra_feature_notice/1,
|
||||
render_component(&Billing.premium_feature_notice/1,
|
||||
billable_user: me,
|
||||
current_user: me,
|
||||
feature_mod: Plausible.Billing.Feature.Props
|
||||
@ -32,12 +32,12 @@ defmodule PlausibleWeb.Components.BillingTest do
|
||||
assert rendered =~ "/billing/upgrade"
|
||||
end
|
||||
|
||||
test "extra_feature_notice/1 does not render an upgrade link when user is not the site owner" do
|
||||
test "premium_feature_notice/1 does not render an upgrade link when user is not the site owner" do
|
||||
me = insert(:user)
|
||||
owner = insert(:user, subscription: build(:subscription, paddle_plan_id: @v4_growth_plan_id))
|
||||
|
||||
rendered =
|
||||
render_component(&Billing.extra_feature_notice/1,
|
||||
render_component(&Billing.premium_feature_notice/1,
|
||||
billable_user: owner,
|
||||
current_user: me,
|
||||
feature_mod: Plausible.Billing.Feature.Funnels
|
||||
@ -49,11 +49,11 @@ defmodule PlausibleWeb.Components.BillingTest do
|
||||
refute rendered =~ "/billing/upgrade"
|
||||
end
|
||||
|
||||
test "extra_feature_notice/1 does not render a notice when the user has access to the feature" do
|
||||
test "premium_feature_notice/1 does not render a notice when the user has access to the feature" do
|
||||
me = insert(:user, subscription: build(:subscription, paddle_plan_id: @v4_business_plan_id))
|
||||
|
||||
rendered =
|
||||
render_component(&Billing.extra_feature_notice/1,
|
||||
render_component(&Billing.premium_feature_notice/1,
|
||||
billable_user: me,
|
||||
current_user: me,
|
||||
feature_mod: Plausible.Billing.Feature.Funnels
|
||||
|
Loading…
Reference in New Issue
Block a user