<.favicon domain={@site.domain} />
@@ -411,7 +507,7 @@ defmodule PlausibleWeb.Live.Sites do
href={"/#{URI.encode_www_form(@site.domain)}/settings/general"}
class="group/item !flex items-center gap-x-2"
>
-
+
Settings
@@ -433,13 +529,13 @@ defmodule PlausibleWeb.Live.Sites do
<.icon_pin
:if={@site.pinned_at}
filled={true}
- class="size-[1.15rem] text-indigo-600 dark:text-indigo-500 group-hover/item:text-indigo-700 dark:group-hover/item:text-indigo-400 transition-colors duration-150"
+ class="size-[1.15rem] text-indigo-600 dark:text-indigo-500 group-hover/item:text-indigo-700 dark:group-hover/item:text-indigo-400"
/>
Unpin site
<.icon_pin
:if={!@site.pinned_at}
- class="size-5 text-gray-600 dark:text-gray-400 group-hover/item:text-gray-900 dark:group-hover/item:text-gray-100 transition-colors duration-150"
+ class="size-5 text-gray-600 dark:text-gray-400 group-hover/item:text-gray-900 dark:group-hover/item:text-gray-100"
/>
Pin site
@@ -490,7 +586,7 @@ defmodule PlausibleWeb.Live.Sites do
-
+
def percentage_change(assigns) do
~H"""
-
+
diff --git a/mix.exs b/mix.exs
index b68bd8abee32..ccee086569e4 100644
--- a/mix.exs
+++ b/mix.exs
@@ -114,7 +114,7 @@ defmodule Plausible.MixProject do
{:phoenix_live_view, "~> 1.1"},
{:php_serializer, "~> 2.0"},
{:plug, "~> 1.13", override: true},
- {:prima, "~> 0.1.7"},
+ {:prima, "~> 0.1.8"},
{:plug_cowboy, "~> 2.3"},
{:polymorphic_embed, "~> 5.0"},
{:postgrex, "~> 0.19.0"},
diff --git a/mix.lock b/mix.lock
index 65fd7cc76461..523ec8712d57 100644
--- a/mix.lock
+++ b/mix.lock
@@ -124,7 +124,7 @@
"phoenix_html": {:hex, :phoenix_html, "4.3.0", "d3577a5df4b6954cd7890c84d955c470b5310bb49647f0a114a6eeecc850f7ad", [:mix], [], "hexpm", "3eaa290a78bab0f075f791a46a981bbe769d94bc776869f4f3063a14f30497ad"},
"phoenix_html_helpers": {:hex, :phoenix_html_helpers, "1.0.1", "7eed85c52eff80a179391036931791ee5d2f713d76a81d0d2c6ebafe1e11e5ec", [:mix], [{:phoenix_html, "~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "cffd2385d1fa4f78b04432df69ab8da63dc5cf63e07b713a4dcf36a3740e3090"},
"phoenix_live_reload": {:hex, :phoenix_live_reload, "1.5.3", "f2161c207fda0e4fb55165f650f7f8db23f02b29e3bff00ff7ef161d6ac1f09d", [:mix], [{:file_system, "~> 0.3 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "b4ec9cd73cb01ff1bd1cac92e045d13e7030330b74164297d1aee3907b54803c"},
- "phoenix_live_view": {:hex, :phoenix_live_view, "1.1.16", "e42f95337b912a73a1c4ddb077af2eb13491712d7ab79b67e13de4237dfcac50", [:mix], [{:igniter, ">= 0.6.16 and < 1.0.0-0", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:lazy_html, "~> 0.1.0", [hex: :lazy_html, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0 or ~> 1.8.0-rc", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.15", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "f2a0093895b8ef4880af76d41de4a9cf7cff6c66ad130e15a70bdabc4d279feb"},
+ "phoenix_live_view": {:hex, :phoenix_live_view, "1.1.17", "1d782b5901cf13b137c6d8c56542ff6cb618359b2adca7e185b21df728fa0c6c", [:mix], [{:igniter, ">= 0.6.16 and < 1.0.0-0", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:lazy_html, "~> 0.1.0", [hex: :lazy_html, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0 or ~> 1.8.0-rc", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.15", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "fa82307dd9305657a8236d6b48e60ef2e8d9f742ee7ed832de4b8bcb7e0e5ed2"},
"phoenix_pubsub": {:hex, :phoenix_pubsub, "2.2.0", "ff3a5616e1bed6804de7773b92cbccfc0b0f473faf1f63d7daf1206c7aeaaa6f", [:mix], [], "hexpm", "adc313a5bf7136039f63cfd9668fde73bba0765e0614cba80c06ac9460ff3e96"},
"phoenix_storybook": {:hex, :phoenix_storybook, "0.9.3", "4f94e731d4c40d4dd7d1eddf7d5c6914366da7d78552dc565b222e4036d0d76f", [:mix], [{:earmark, "~> 1.4", [hex: :earmark, repo: "hexpm", optional: false]}, {:jason, "~> 1.3", [hex: :jason, repo: "hexpm", optional: true]}, {:makeup_eex, "~> 2.0.2", [hex: :makeup_eex, repo: "hexpm", optional: false]}, {:makeup_html, "~> 0.2.0", [hex: :makeup_html, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.8.1", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html_helpers, "~> 1.0", [hex: :phoenix_html_helpers, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 1.1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: false]}], "hexpm", "4c8658b756fd8238f7e8e4343a0f12bdb91d4eba592b1c4e8118b37b6fd43e4b"},
"phoenix_template": {:hex, :phoenix_template, "1.0.4", "e2092c132f3b5e5b2d49c96695342eb36d0ed514c5b252a77048d5969330d639", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "2c0c81f0e5c6753faf5cca2f229c9709919aba34fab866d3bc05060c9c444206"},
@@ -135,7 +135,7 @@
"plug_crypto": {:hex, :plug_crypto, "1.2.5", "918772575e48e81e455818229bf719d4ab4181fcbf7f85b68a35620f78d89ced", [:mix], [], "hexpm", "26549a1d6345e2172eb1c233866756ae44a9609bd33ee6f99147ab3fd87fd842"},
"polymorphic_embed": {:hex, :polymorphic_embed, "5.0.3", "37444e0af941026a2c29b0539b6471bdd6737a6492a19264bf2bb0118e3ac242", [:mix], [{:attrs, "~> 0.6", [hex: :attrs, repo: "hexpm", optional: false]}, {:ecto, "~> 3.12", [hex: :ecto, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 4.1", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_html_helpers, "~> 1.0", [hex: :phoenix_html_helpers, repo: "hexpm", optional: true]}, {:phoenix_live_view, "~> 0.20 or ~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: true]}], "hexpm", "2fed44f57abf0a0fc7642e0eb0807a55b65de1562712cc0620772cbbb80e49c1"},
"postgrex": {:hex, :postgrex, "0.19.3", "a0bda6e3bc75ec07fca5b0a89bffd242ca209a4822a9533e7d3e84ee80707e19", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "d31c28053655b78f47f948c85bb1cf86a9c1f8ead346ba1aa0d0df017fa05b61"},
- "prima": {:hex, :prima, "0.1.7", "197fe29aa1cb6cc0c38fddb7daca017b9d4cfc1aef0b30694e02e45fcf22710f", [:mix], [{:esbuild, "~> 0.7", [hex: :esbuild, repo: "hexpm", optional: false]}, {:phoenix, ">= 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 4.2", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 1.1", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}], "hexpm", "662ea3f8698358087c1632db8969050a74df101e202d026e2f26bc3f740737f9"},
+ "prima": {:hex, :prima, "0.1.8", "1f57fb7000046bb463b2a31200b138dd10c86fd78a289f1e947a970f740b68e0", [:mix], [{:esbuild, "~> 0.7", [hex: :esbuild, repo: "hexpm", optional: false]}, {:phoenix, ">= 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 4.2", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 1.1", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}], "hexpm", "b559ee8213a8302fd40520cc55b0fcafbc884d471d198b262dd1e0a10170de17"},
"prom_ex": {:hex, :prom_ex, "1.11.0", "1f6d67f2dead92224cb4f59beb3e4d319257c5728d9638b4a5e8ceb51a4f9c7e", [:mix], [{:absinthe, ">= 1.7.0", [hex: :absinthe, repo: "hexpm", optional: true]}, {:broadway, ">= 1.1.0", [hex: :broadway, repo: "hexpm", optional: true]}, {:ecto, ">= 3.11.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:finch, "~> 0.18", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:oban, ">= 2.10.0", [hex: :oban, repo: "hexpm", optional: true]}, {:octo_fetch, "~> 0.4", [hex: :octo_fetch, repo: "hexpm", optional: false]}, {:peep, "~> 3.0", [hex: :peep, repo: "hexpm", optional: false]}, {:phoenix, ">= 1.7.0", [hex: :phoenix, repo: "hexpm", optional: true]}, {:phoenix_live_view, ">= 0.20.0", [hex: :phoenix_live_view, repo: "hexpm", optional: true]}, {:plug, ">= 1.16.0", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, ">= 2.6.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, ">= 1.0.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}, {:telemetry_metrics_prometheus_core, "~> 1.2", [hex: :telemetry_metrics_prometheus_core, repo: "hexpm", optional: false]}, {:telemetry_poller, "~> 1.1", [hex: :telemetry_poller, repo: "hexpm", optional: false]}], "hexpm", "76b074bc3730f0802978a7eb5c7091a65473eaaf07e99ec9e933138dcc327805"},
"public_suffix": {:git, "https://github.com/axelson/publicsuffix-elixir", "fa40c243d4b5d8598b90cff268bc4e33f3bb63f1", []},
"ranch": {:hex, :ranch, "1.8.1", "208169e65292ac5d333d6cdbad49388c1ae198136e4697ae2f474697140f201c", [:make, :rebar3], [], "hexpm", "aed58910f4e21deea992a67bf51632b6d60114895eb03bb392bb733064594dd0"},
@@ -165,7 +165,7 @@
"ua_inspector": {:git, "https://github.com/plausible/ua_inspector.git", "25cba4c910e80d7c34bbb1bbb939372260d088e8", [branch: "sanitize-pre"]},
"unicode_util_compat": {:hex, :unicode_util_compat, "0.7.1", "a48703a25c170eedadca83b11e88985af08d35f37c6f664d6dcfb106a97782fc", [:rebar3], [], "hexpm", "b3a917854ce3ae233619744ad1e0102e05673136776fb2fa76234f3e03b23642"},
"websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"},
- "websock_adapter": {:hex, :websock_adapter, "0.5.8", "3b97dc94e407e2d1fc666b2fb9acf6be81a1798a2602294aac000260a7c4a47d", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "315b9a1865552212b5f35140ad194e67ce31af45bcee443d4ecb96b5fd3f3782"},
+ "websock_adapter": {:hex, :websock_adapter, "0.5.9", "43dc3ba6d89ef5dec5b1d0a39698436a1e856d000d84bf31a3149862b01a287f", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "5534d5c9adad3c18a0f58a9371220d75a803bf0b9a3d87e6fe072faaeed76a08"},
"x509": {:hex, :x509, "0.9.1", "c92026a17b7d93f19029842ca218f82ec1f1e7cc9d4aa0c48327ee778f7f482e", [:mix], [], "hexpm", "99328951a1480cfd7b1b8aa688f857f7f5bbea03077b78cad211fb3b30c2f4a8"},
"xml_builder": {:hex, :xml_builder, "2.4.0", "b20d23077266c81f593360dc037ea398461dddb6638a329743da6c73afa56725", [:mix], [], "hexpm", "833e325bb997f032b5a1b740d2fd6feed3c18ca74627f9f5f30513a9ae1a232d"},
"yamerl": {:hex, :yamerl, "0.10.0", "4ff81fee2f1f6a46f1700c0d880b24d193ddb74bd14ef42cb0bcf46e81ef2f8e", [:rebar3], [], "hexpm", "346adb2963f1051dc837a2364e4acf6eb7d80097c0f53cbdc3046ec8ec4b4e6e"},
diff --git a/priv/plans_v3.json b/priv/plans_v3.json
index 55f4a03ee5da..37aa5f0d422a 100644
--- a/priv/plans_v3.json
+++ b/priv/plans_v3.json
@@ -134,7 +134,8 @@
"funnels",
"stats_api",
"site_segments",
- "shared_links"
+ "shared_links",
+ "consolidated_view"
]
},
{
@@ -152,7 +153,8 @@
"funnels",
"stats_api",
"site_segments",
- "shared_links"
+ "shared_links",
+ "consolidated_view"
]
},
{
@@ -170,7 +172,8 @@
"funnels",
"stats_api",
"site_segments",
- "shared_links"
+ "shared_links",
+ "consolidated_view"
]
},
{
@@ -188,7 +191,8 @@
"funnels",
"stats_api",
"site_segments",
- "shared_links"
+ "shared_links",
+ "consolidated_view"
]
},
{
@@ -206,7 +210,8 @@
"funnels",
"stats_api",
"site_segments",
- "shared_links"
+ "shared_links",
+ "consolidated_view"
]
},
{
@@ -224,7 +229,8 @@
"funnels",
"stats_api",
"site_segments",
- "shared_links"
+ "shared_links",
+ "consolidated_view"
]
},
{
@@ -242,7 +248,8 @@
"funnels",
"stats_api",
"site_segments",
- "shared_links"
+ "shared_links",
+ "consolidated_view"
]
},
{
@@ -260,7 +267,8 @@
"funnels",
"stats_api",
"site_segments",
- "shared_links"
+ "shared_links",
+ "consolidated_view"
]
}
-]
\ No newline at end of file
+]
diff --git a/priv/plans_v4.json b/priv/plans_v4.json
index 36e7f0a352d8..de39f7ac369b 100644
--- a/priv/plans_v4.json
+++ b/priv/plans_v4.json
@@ -126,7 +126,8 @@
"funnels",
"stats_api",
"site_segments",
- "shared_links"
+ "shared_links",
+ "consolidated_view"
],
"data_retention_in_years": 5
},
@@ -145,7 +146,8 @@
"funnels",
"stats_api",
"site_segments",
- "shared_links"
+ "shared_links",
+ "consolidated_view"
],
"data_retention_in_years": 5
},
@@ -164,7 +166,8 @@
"funnels",
"stats_api",
"site_segments",
- "shared_links"
+ "shared_links",
+ "consolidated_view"
],
"data_retention_in_years": 5
},
@@ -183,7 +186,8 @@
"funnels",
"stats_api",
"site_segments",
- "shared_links"
+ "shared_links",
+ "consolidated_view"
],
"data_retention_in_years": 5
},
@@ -202,7 +206,8 @@
"funnels",
"stats_api",
"site_segments",
- "shared_links"
+ "shared_links",
+ "consolidated_view"
],
"data_retention_in_years": 5
},
@@ -221,7 +226,8 @@
"funnels",
"stats_api",
"site_segments",
- "shared_links"
+ "shared_links",
+ "consolidated_view"
],
"data_retention_in_years": 5
},
@@ -240,7 +246,8 @@
"funnels",
"stats_api",
"site_segments",
- "shared_links"
+ "shared_links",
+ "consolidated_view"
],
"data_retention_in_years": 5
},
@@ -259,8 +266,9 @@
"funnels",
"stats_api",
"site_segments",
- "shared_links"
+ "shared_links",
+ "consolidated_view"
],
"data_retention_in_years": 5
}
-]
\ No newline at end of file
+]
diff --git a/priv/plans_v5.json b/priv/plans_v5.json
index 00158886805e..69c3641a2329 100644
--- a/priv/plans_v5.json
+++ b/priv/plans_v5.json
@@ -238,7 +238,8 @@
"props",
"stats_api",
"revenue_goals",
- "funnels"
+ "funnels",
+ "consolidated_view"
],
"data_retention_in_years": 5
},
@@ -257,7 +258,8 @@
"props",
"stats_api",
"revenue_goals",
- "funnels"
+ "funnels",
+ "consolidated_view"
],
"data_retention_in_years": 5
},
@@ -276,7 +278,8 @@
"props",
"stats_api",
"revenue_goals",
- "funnels"
+ "funnels",
+ "consolidated_view"
],
"data_retention_in_years": 5
},
@@ -295,7 +298,8 @@
"props",
"stats_api",
"revenue_goals",
- "funnels"
+ "funnels",
+ "consolidated_view"
],
"data_retention_in_years": 5
},
@@ -314,7 +318,8 @@
"props",
"stats_api",
"revenue_goals",
- "funnels"
+ "funnels",
+ "consolidated_view"
],
"data_retention_in_years": 5
},
@@ -333,7 +338,8 @@
"props",
"stats_api",
"revenue_goals",
- "funnels"
+ "funnels",
+ "consolidated_view"
],
"data_retention_in_years": 5
},
@@ -352,7 +358,8 @@
"props",
"stats_api",
"revenue_goals",
- "funnels"
+ "funnels",
+ "consolidated_view"
],
"data_retention_in_years": 5
},
@@ -371,8 +378,9 @@
"props",
"stats_api",
"revenue_goals",
- "funnels"
+ "funnels",
+ "consolidated_view"
],
"data_retention_in_years": 5
}
-]
\ No newline at end of file
+]
diff --git a/priv/repo/seeds.exs b/priv/repo/seeds.exs
index 1522defcfcc5..7316a6c7a23f 100644
--- a/priv/repo/seeds.exs
+++ b/priv/repo/seeds.exs
@@ -13,6 +13,8 @@ use Plausible
import Plausible.Teams.Test
+FunWithFlags.enable(:consolidated_view)
+
words =
for i <- 0..(:erlang.system_info(:atom_count) - 1),
do: :erlang.binary_to_term(<<131, 75, i::24>>)
diff --git a/test/plausible/billing/feature_test.exs b/test/plausible/billing/feature_test.exs
index 2b208553280b..37c40ee85bb0 100644
--- a/test/plausible/billing/feature_test.exs
+++ b/test/plausible/billing/feature_test.exs
@@ -10,14 +10,15 @@ defmodule Plausible.Billing.FeatureTest do
Funnels,
RevenueGoals,
StatsAPI,
- Props
+ Props,
+ ConsolidatedView
}
@v1_growth_plan_id "558018"
@v5_growth_plan_id "910429"
describe "business features (for everyone)" do
- for mod <- [Funnels, RevenueGoals] do
+ for mod <- [Funnels, RevenueGoals, ConsolidatedView] do
test "#{mod}.check_availability/1 returns :ok when site owner is on a enterprise plan that supports #{mod}" do
team =
new_user()
diff --git a/test/plausible/billing/plan_benefits_test.exs b/test/plausible/billing/plan_benefits_test.exs
index 74fdd79df8fa..c2525bf31b7e 100644
--- a/test/plausible/billing/plan_benefits_test.exs
+++ b/test/plausible/billing/plan_benefits_test.exs
@@ -80,7 +80,8 @@ defmodule Plausible.Billing.PlanBenefitsTest do
"Stats API (600 requests per hour)",
"Looker Studio Connector",
"Ecommerce revenue attribution",
- "Funnels"
+ "Funnels",
+ "Consolidated View"
]
end
@@ -99,7 +100,8 @@ defmodule Plausible.Billing.PlanBenefitsTest do
"Funnels",
"Stats API (600 requests per hour)",
"Looker Studio Connector",
- "Shared Segments"
+ "Shared Segments",
+ "Consolidated View"
]
end
@@ -120,7 +122,8 @@ defmodule Plausible.Billing.PlanBenefitsTest do
"Everything in Growth",
"Ecommerce revenue attribution",
"Funnels",
- "Shared Segments"
+ "Shared Segments",
+ "Consolidated View"
]
end
end
diff --git a/test/plausible/consolidated_view/cache_test.exs b/test/plausible/consolidated_view/cache_test.exs
index 9a93af0765a4..2ad2722193c0 100644
--- a/test/plausible/consolidated_view/cache_test.exs
+++ b/test/plausible/consolidated_view/cache_test.exs
@@ -63,6 +63,7 @@ defmodule Plausible.CondolidatedView.CacheTest do
owner = new_user()
new_site(owner: owner, updated_at: yesterday())
+ new_site(owner: owner, updated_at: yesterday())
team = team_of(owner)
@@ -70,7 +71,7 @@ defmodule Plausible.CondolidatedView.CacheTest do
:ok = Cache.refresh_updated_recently(cache_name: test)
- assert [_] = Cache.get(consolidated_view.domain, cache_name: test, force?: true)
+ assert [_, _] = Cache.get(consolidated_view.domain, cache_name: test, force?: true)
end
test "get_from_source/1", %{test: test} do
diff --git a/test/plausible/consolidated_view_test.exs b/test/plausible/consolidated_view_test.exs
index 572bb12107cb..1960838e4bd3 100644
--- a/test/plausible/consolidated_view_test.exs
+++ b/test/plausible/consolidated_view_test.exs
@@ -8,17 +8,71 @@ defmodule Plausible.ConsolidatedViewTest do
alias Plausible.ConsolidatedView
alias Plausible.Teams
+ describe "cta state" do
+ setup [:create_user, :create_team]
+
+ test "by default CTA should be shown", %{user: user, team: team} do
+ assert ConsolidatedView.cta_dismissed?(user, team) == false
+ end
+
+ test "CTA dismissed and restored", %{user: user, team: team} do
+ assert :ok = ConsolidatedView.dismiss_cta(user, team)
+ assert ConsolidatedView.cta_dismissed?(user, team) == true
+
+ assert :ok = ConsolidatedView.restore_cta(user, team)
+ assert ConsolidatedView.cta_dismissed?(user, team) == false
+ end
+ end
+
+ describe "ok_to_display?/1" do
+ setup [:create_user, :create_team]
+
+ test "returns false when team is nil" do
+ refute ConsolidatedView.ok_to_display?(nil)
+ end
+
+ test "returns false when feature flag is disabled", %{team: team} do
+ FunWithFlags.disable(:consolidated_view, for_actor: team)
+ refute ConsolidatedView.ok_to_display?(team)
+ end
+
+ test "returns false when consolidated view is not enabled", %{team: team} do
+ ConsolidatedView.disable(team)
+ refute ConsolidatedView.ok_to_display?(team)
+ end
+
+ test "returns false when there are no sites to consolidate", %{team: team} do
+ new_site(team: team)
+ site = new_site(team: team)
+ team = Teams.complete_setup(team)
+ {:ok, _} = ConsolidatedView.enable(team)
+ Plausible.Repo.delete(site)
+ refute ConsolidatedView.ok_to_display?(team)
+ end
+
+ test "returns true when all conditions are met", %{team: team} do
+ new_site(team: team)
+ new_site(team: team)
+ team = Teams.complete_setup(team)
+ {:ok, _} = ConsolidatedView.enable(team)
+
+ assert ConsolidatedView.ok_to_display?(team)
+ end
+ end
+
describe "enable/1 and enabled?/1" do
setup [:create_user, :create_team]
test "creates and persists a new consolidated site instance", %{team: team} do
+ new_site(team: team)
new_site(team: team)
team = Teams.complete_setup(team)
assert {:ok, %Plausible.Site{consolidated: true}} = ConsolidatedView.enable(team)
- assert ConsolidatedView.enabled?(team)
+ assert ConsolidatedView.get(team)
end
test "is idempotent", %{team: team} do
+ new_site(team: team)
new_site(team: team)
team = Teams.complete_setup(team)
assert {:ok, s1} = ConsolidatedView.enable(team)
@@ -31,15 +85,36 @@ defmodule Plausible.ConsolidatedViewTest do
assert s1.domain == s2.domain
end
+ test "returns {:error, :upgrade_required} for ineligible subscription", %{
+ team: team,
+ user: user
+ } do
+ subscribe_to_growth_plan(user)
+ new_site(team: team)
+ new_site(team: team)
+ team = Teams.complete_setup(team)
+
+ assert ConsolidatedView.enable(team) == {:error, :upgrade_required}
+ end
+
test "returns {:error, :no_sites} when the team does not have any sites", %{team: team} do
team = Teams.complete_setup(team)
assert {:error, :no_sites} = ConsolidatedView.enable(team)
- refute ConsolidatedView.enabled?(team)
+ refute ConsolidatedView.get(team)
end
- test "returns {:error, :team_not_setup} when the team is not set up", %{team: team} do
+ test "returns {:error, :team_not_setup} when the team has sites but isn't setup", %{
+ team: team
+ } do
+ new_site(team: team)
+ new_site(team: team)
assert {:error, :team_not_setup} = ConsolidatedView.enable(team)
- refute ConsolidatedView.enabled?(team)
+ refute ConsolidatedView.get(team)
+ end
+
+ test "returns {:error, :no_sites} when the team is not set up", %{team: team} do
+ assert {:error, :no_sites} = ConsolidatedView.enable(team)
+ refute ConsolidatedView.get(team)
end
@tag :skip
@@ -66,14 +141,17 @@ defmodule Plausible.ConsolidatedViewTest do
test "enable/1 updates cache", %{team: team} do
team = Teams.complete_setup(team)
site = new_site(team: team)
+ new_site(team: team)
{:ok, _} = ConsolidatedView.enable(team)
assert eventually(fn ->
- {ConsolidatedView.Cache.get(team.identifier) == [site.id], :ok}
+ site_ids = ConsolidatedView.Cache.get(team.identifier)
+ {is_list(site_ids) and length(site_ids) == 2 and site.id in site_ids, :ok}
end)
end
test "sets Etc/UTC by default", %{team: team} do
+ new_site(team: team)
new_site(team: team)
team = Teams.complete_setup(team)
@@ -82,6 +160,7 @@ defmodule Plausible.ConsolidatedViewTest do
end
test "sets Etc/UTC for UTC sites", %{team: team} do
+ new_site(team: team, timezone: "UTC")
new_site(team: team, timezone: "UTC")
team = Teams.complete_setup(team)
@@ -106,6 +185,7 @@ defmodule Plausible.ConsolidatedViewTest do
setup [:create_user, :create_team, :create_site]
setup %{team: team} do
+ new_site(team: team)
new_consolidated_view(team)
:ok
end
@@ -169,8 +249,11 @@ defmodule Plausible.ConsolidatedViewTest do
team: team,
site: site
} do
+ new_site(team: team)
new_consolidated_view(team)
- assert ConsolidatedView.site_ids(team) == {:ok, [site.id]}
+ assert {:ok, site_ids} = ConsolidatedView.site_ids(team)
+ assert length(site_ids) == 2
+ assert site.id in site_ids
end
end
@@ -179,12 +262,14 @@ defmodule Plausible.ConsolidatedViewTest do
test "can get by team", %{team: team} do
assert is_nil(ConsolidatedView.get(team))
+ new_site(team: team)
new_consolidated_view(team)
assert %Plausible.Site{} = ConsolidatedView.get(team)
end
test "can get by team.identifier", %{team: team} do
assert is_nil(ConsolidatedView.get(team.identifier))
+ new_site(team: team)
new_consolidated_view(team)
assert %Plausible.Site{} = ConsolidatedView.get(team.identifier)
end
@@ -196,7 +281,7 @@ defmodule Plausible.ConsolidatedViewTest do
test "no-op if disabled", %{team: team} do
:ok = ConsolidatedView.reset_if_enabled(team)
- refute ConsolidatedView.enabled?(team)
+ refute ConsolidatedView.get(team)
refute ConsolidatedView.get(team)
end
@@ -209,6 +294,13 @@ defmodule Plausible.ConsolidatedViewTest do
timezone: "Europe/Warsaw"
)
+ _site =
+ new_site(
+ team: team,
+ native_stats_start_at: ~N[2024-01-01 12:00:00],
+ timezone: "Europe/Tiraspol"
+ )
+
team = Teams.complete_setup(team)
{:ok, first_enable} = ConsolidatedView.enable(team)
@@ -223,7 +315,7 @@ defmodule Plausible.ConsolidatedViewTest do
Process.sleep(1_000)
:ok = ConsolidatedView.reset_if_enabled(team)
- assert ConsolidatedView.enabled?(team)
+ assert ConsolidatedView.get(team)
consolidated_view = ConsolidatedView.get(team)
assert consolidated_view.native_stats_start_at == another_site.native_stats_start_at
diff --git a/test/plausible/site/site_removal_test.exs b/test/plausible/site/site_removal_test.exs
index d349785b8dc6..9cb7ef927899 100644
--- a/test/plausible/site/site_removal_test.exs
+++ b/test/plausible/site/site_removal_test.exs
@@ -57,14 +57,15 @@ defmodule Plausible.Site.SiteRemovalTest do
test "site deletion disables consolidated view if need be" do
owner = new_user()
site = new_site(owner: owner)
+ new_site(owner: owner)
team = team_of(owner)
new_consolidated_view(team)
- assert Plausible.ConsolidatedView.enabled?(team)
+ assert Plausible.ConsolidatedView.get(team)
assert {:ok, _} = Removal.run(site)
- refute Plausible.ConsolidatedView.enabled?(team)
+ refute Plausible.ConsolidatedView.get(team)
end
test "site deletion keeps consolidated view if there's still regular sites" do
@@ -73,15 +74,17 @@ defmodule Plausible.Site.SiteRemovalTest do
# another site
new_site(owner: owner)
+ # third site to ensure we still have 2+ after deletion
+ new_site(owner: owner)
team = team_of(owner)
new_consolidated_view(team)
- assert Plausible.ConsolidatedView.enabled?(team)
+ assert Plausible.ConsolidatedView.get(team)
assert {:ok, _} = Removal.run(site)
- assert Plausible.ConsolidatedView.enabled?(team)
+ assert Plausible.ConsolidatedView.get(team)
end
end
end
diff --git a/test/plausible/sites_test.exs b/test/plausible/sites_test.exs
index fef7794db50e..b6aed3386f48 100644
--- a/test/plausible/sites_test.exs
+++ b/test/plausible/sites_test.exs
@@ -179,6 +179,7 @@ defmodule Plausible.SitesTest do
test "resets consolidated view stats dates every time" do
owner = new_user()
new_site(owner: owner)
+ new_site(owner: owner)
team = team_of(owner)
consolidated_view = new_consolidated_view(team)
diff --git a/test/plausible/stats/consolidated_view_sync_test.exs b/test/plausible/stats/consolidated_view_sync_test.exs
deleted file mode 100644
index 5a50dfd98844..000000000000
--- a/test/plausible/stats/consolidated_view_sync_test.exs
+++ /dev/null
@@ -1,55 +0,0 @@
-defmodule Plausible.Stats.ConsolidatedViewSyncTest do
- use Plausible.DataCase, async: true
-
- on_ee do
- import Plausible.Teams.Test
- import Plausible.ConsolidatedView, only: [ok_to_display?: 2, enable: 1]
-
- describe "ok_to_display?/2" do
- setup [:create_user, :create_team]
-
- test "no user", %{team: team} do
- refute ok_to_display?(team, nil)
- end
-
- test "no team", %{user: user} do
- refute ok_to_display?(nil, user)
- end
-
- test "success", %{team: team, user: user} do
- new_site(owner: user)
- new_site(owner: user)
-
- team = Plausible.Teams.complete_setup(team)
-
- {:ok, _} = enable(team)
-
- patch_env(:super_admin_user_ids, [user.id])
-
- assert ok_to_display?(team, user)
- end
-
- test "not super-admin (temporary - feature-flag-like)", %{team: team, user: user} do
- new_site(owner: user)
- new_site(owner: user)
-
- team = Plausible.Teams.complete_setup(team)
-
- {:ok, _} = enable(team)
-
- refute ok_to_display?(team, user)
- end
-
- test "not enabled", %{team: team, user: user} do
- new_site(owner: user)
- new_site(owner: user)
-
- team = Plausible.Teams.complete_setup(team)
-
- patch_env(:super_admin_user_ids, [user.id])
-
- refute ok_to_display?(team, user)
- end
- end
- end
-end
diff --git a/test/plausible/stats/consolidated_view_test.exs b/test/plausible/stats/consolidated_view_test.exs
index 5ccce28b6046..316bb2bd7a6d 100644
--- a/test/plausible/stats/consolidated_view_test.exs
+++ b/test/plausible/stats/consolidated_view_test.exs
@@ -72,6 +72,7 @@ defmodule Plausible.Stats.ConsolidatedViewTest do
fixed_now = ~N[2025-10-20 12:49:15]
owner = new_user()
site = new_site(owner: owner)
+ new_site(owner: owner)
populate_stats(site, [
build(:pageview, user_id: 111, timestamp: ~N[2025-10-20 12:00:00]),
@@ -95,6 +96,7 @@ defmodule Plausible.Stats.ConsolidatedViewTest do
fixed_now = ~N[2025-10-20 12:49:15]
owner = new_user()
site = new_site(owner: owner)
+ new_site(owner: owner)
populate_stats(site, [
build(:pageview, user_id: 111, timestamp: ~N[2025-10-19 11:00:00]),
@@ -122,6 +124,7 @@ defmodule Plausible.Stats.ConsolidatedViewTest do
fixed_now = ~N[2025-10-20 12:49:15]
owner = new_user()
site = new_site(owner: owner)
+ new_site(owner: owner)
populate_stats(site, [
build(:pageview, user_id: 111, timestamp: ~N[2025-10-20 12:00:00]),
diff --git a/test/plausible/stats/query_parser_test.exs b/test/plausible/stats/query_parser_test.exs
index f3187c13a481..ab4eb5b4d809 100644
--- a/test/plausible/stats/query_parser_test.exs
+++ b/test/plausible/stats/query_parser_test.exs
@@ -2718,6 +2718,7 @@ defmodule Plausible.Stats.Filters.QueryParserTest do
end
test "is set to a list of site_ids when site is consolidated", %{site: site} do
+ new_site(team: site.team)
cv = new_consolidated_view(site.team)
params = %{
@@ -2726,10 +2727,13 @@ defmodule Plausible.Stats.Filters.QueryParserTest do
"date_range" => "all"
}
- site_id = site.id
+ assert {:ok, %{consolidated_site_ids: site_ids}} = parse(cv, :public, params)
+ assert length(site_ids) == 2
+ assert site.id in site_ids
- assert {:ok, %{consolidated_site_ids: [^site_id]}} = parse(cv, :public, params)
- assert {:ok, %{consolidated_site_ids: [^site_id]}} = parse(cv, :internal, params)
+ assert {:ok, %{consolidated_site_ids: site_ids}} = parse(cv, :internal, params)
+ assert length(site_ids) == 2
+ assert site.id in site_ids
end
end
end
diff --git a/test/plausible/stats/query_test.exs b/test/plausible/stats/query_test.exs
index 6d8252c0c6aa..d1fd76fb5b10 100644
--- a/test/plausible/stats/query_test.exs
+++ b/test/plausible/stats/query_test.exs
@@ -492,10 +492,12 @@ defmodule Plausible.Stats.QueryTest do
end
test "is set to a list of site_ids when site is consolidated", %{site: site} do
+ new_site(team: site.team)
cv = new_consolidated_view(site.team)
- site_id = site.id
- assert %{consolidated_site_ids: [^site_id]} = Query.from(cv, %{"period" => "day"})
+ assert %{consolidated_site_ids: site_ids} = Query.from(cv, %{"period" => "day"})
+ assert length(site_ids) == 2
+ assert site.id in site_ids
end
end
end
diff --git a/test/plausible/teams/sites/transfer_test.exs b/test/plausible/teams/sites/transfer_test.exs
index 620852624ff0..389beecb7a92 100644
--- a/test/plausible/teams/sites/transfer_test.exs
+++ b/test/plausible/teams/sites/transfer_test.exs
@@ -90,10 +90,11 @@ defmodule Plausible.Teams.Sites.TransferTest do
test "disables consolidated view if sites transferred out of team" do
user = new_user()
site = new_site(owner: user)
+ new_site(owner: user)
team = team_of(user)
new_consolidated_view(team)
- assert ConsolidatedView.enabled?(team)
+ assert ConsolidatedView.get(team)
another_owner = new_user()
subscribe_to_growth_plan(another_owner)
@@ -104,7 +105,7 @@ defmodule Plausible.Teams.Sites.TransferTest do
:ok = Transfer.change_team(site, user, another_team)
- refute ConsolidatedView.enabled?(team)
+ refute ConsolidatedView.get(team)
end
end
diff --git a/test/plausible_web/controllers/api/external_sites_controller_sites_crud_api_test.exs b/test/plausible_web/controllers/api/external_sites_controller_sites_crud_api_test.exs
index 785ddfccf254..79db3fee07d1 100644
--- a/test/plausible_web/controllers/api/external_sites_controller_sites_crud_api_test.exs
+++ b/test/plausible_web/controllers/api/external_sites_controller_sites_crud_api_test.exs
@@ -757,7 +757,8 @@ defmodule PlausibleWeb.Api.ExternalSitesControllerSitesCrudApiTest do
subscribe_to_enterprise_plan(user,
features: [
Plausible.Billing.Feature.StatsAPI,
- Plausible.Billing.Feature.SitesAPI
+ Plausible.Billing.Feature.SitesAPI,
+ Plausible.Billing.Feature.ConsolidatedView
]
)
diff --git a/test/plausible_web/controllers/site_controller_test.exs b/test/plausible_web/controllers/site_controller_test.exs
index 5555caee4568..aa28867508d1 100644
--- a/test/plausible_web/controllers/site_controller_test.exs
+++ b/test/plausible_web/controllers/site_controller_test.exs
@@ -504,7 +504,9 @@ defmodule PlausibleWeb.SiteControllerTest do
on_ee do
test "renders only timezone section for a consolidated site", %{conn: conn, user: user} do
- consolidated_view = user |> team_of() |> new_consolidated_view()
+ team = team_of(user)
+ new_site(team: team)
+ consolidated_view = new_consolidated_view(team)
conn = get(conn, "/#{consolidated_view.domain}/settings/general")
resp = html_response(conn, 200)
@@ -584,6 +586,7 @@ defmodule PlausibleWeb.SiteControllerTest do
user: user
} do
team = user |> team_of()
+ new_site(team: team)
site = new_consolidated_view(team)
conn = get(conn, "/#{site.domain}/settings/general")
resp = html_response(conn, 200)
diff --git a/test/plausible_web/controllers/stats_controller_test.exs b/test/plausible_web/controllers/stats_controller_test.exs
index a2e6783aeb28..618b1419c909 100644
--- a/test/plausible_web/controllers/stats_controller_test.exs
+++ b/test/plausible_web/controllers/stats_controller_test.exs
@@ -30,7 +30,7 @@ defmodule PlausibleWeb.StatsControllerTest do
assert text_of_attr(resp, @react_container, "data-current-user-id") == "null"
assert text_of_attr(resp, @react_container, "data-embedded") == ""
assert text_of_attr(resp, @react_container, "data-is-consolidated-view") == "false"
- assert text_of_attr(resp, @react_container, "data-team-has-consolidated-view") == "false"
+ assert text_of_attr(resp, @react_container, "data-consolidated-view-available") == "false"
assert text_of_attr(resp, @react_container, "data-team-identifier") == site.team.identifier
assert "noindex, nofollow" ==
@@ -185,6 +185,8 @@ defmodule PlausibleWeb.StatsControllerTest do
conn: conn,
user: user
} do
+ new_site(owner: user)
+ new_site(owner: user)
cv = user |> team_of() |> new_consolidated_view()
conn = get(conn, "/" <> cv.domain)
@@ -195,6 +197,23 @@ defmodule PlausibleWeb.StatsControllerTest do
assert text_of_attr(resp, @react_container, "data-current-user-role") == "owner"
assert text_of_attr(resp, @react_container, "data-current-user-id") == "#{user.id}"
end
+
+ test "redirects to /sites if for some reason ineligible anymore", %{
+ conn: conn,
+ user: user
+ } do
+ new_site(owner: user)
+ new_site(owner: user)
+ cv = user |> team_of() |> new_consolidated_view()
+
+ user
+ |> team_of()
+ |> Plausible.Teams.Team.end_trial()
+ |> Plausible.Repo.update!()
+
+ conn = get(conn, "/" <> cv.domain)
+ assert redirected_to(conn, 302) == "/sites"
+ end
end
@tag :ee_only
diff --git a/test/plausible_web/live/customer_support/teams_test.exs b/test/plausible_web/live/customer_support/teams_test.exs
index 7124dde6f382..10212a1eb3ea 100644
--- a/test/plausible_web/live/customer_support/teams_test.exs
+++ b/test/plausible_web/live/customer_support/teams_test.exs
@@ -16,13 +16,13 @@ defmodule PlausibleWeb.Live.CustomerSupport.TeamsTest do
Routes.customer_support_team_path(PlausibleWeb.Endpoint, :show, id, qs)
end
- describe "overview" do
- setup [:create_user, :log_in, :create_site]
+ setup [:create_user, :log_in, :create_site]
- setup %{user: user} do
- patch_env(:super_admin_user_ids, [user.id])
- end
+ setup %{user: user} do
+ patch_env(:super_admin_user_ids, [user.id])
+ end
+ describe "overview" do
test "renders", %{conn: conn, user: user} do
team = team_of(user)
new_site(owner: user)
@@ -165,12 +165,6 @@ defmodule PlausibleWeb.Live.CustomerSupport.TeamsTest do
end
describe "sites" do
- setup [:create_user, :log_in, :create_site]
-
- setup %{user: user} do
- patch_env(:super_admin_user_ids, [user.id])
- end
-
test "lists sites belonging to a team", %{conn: conn, user: user} do
team = team_of(user)
new_site(owner: user, domain: "primary.example.com/test")
@@ -198,13 +192,7 @@ defmodule PlausibleWeb.Live.CustomerSupport.TeamsTest do
@consolidated_views_tab_content ~s|div[data-test-id="consolidated-views-tab-content"]|
describe "consolidated views" do
- setup [:create_user, :log_in, :create_site]
-
- setup %{user: user} do
- patch_env(:super_admin_user_ids, [user.id])
- end
-
- test "renders button to create one inonef exist yet", %{conn: conn, user: user} do
+ test "renders button to create one if none exist yet", %{conn: conn, user: user} do
team = team_of(user)
{:ok, lv, _html} = live(conn, open_team(team.id, tab: "consolidated_views"))
@@ -217,16 +205,19 @@ defmodule PlausibleWeb.Live.CustomerSupport.TeamsTest do
end
test "can create a consolidated view for team", %{conn: conn, user: user} do
+ new_site(owner: user)
+ new_site(owner: user)
team = user |> team_of() |> Plausible.Teams.complete_setup()
{:ok, lv, _html} = live(conn, open_team(team.id, tab: "consolidated_views"))
lv |> element(@create_consolidated_view_button) |> render_click()
- assert Plausible.ConsolidatedView.enabled?(team)
+ assert Plausible.ConsolidatedView.get(team)
end
test "renders existing consolidated view", %{conn: conn, user: user} do
+ new_site(owner: user)
team = team_of(user)
new_consolidated_view(team)
@@ -242,24 +233,21 @@ defmodule PlausibleWeb.Live.CustomerSupport.TeamsTest do
end
test "can delete consolidated view", %{conn: conn, user: user} do
+ new_site(owner: user)
team = team_of(user)
new_consolidated_view(team)
+ assert Plausible.ConsolidatedView.get(team)
+
{:ok, lv, _html} = live(conn, open_team(team.id, tab: "consolidated_views"))
lv |> element(@delete_consolidated_view_button) |> render_click()
- assert not Plausible.ConsolidatedView.enabled?(team)
+ refute Plausible.ConsolidatedView.get(team)
end
end
describe "billing" do
- setup [:create_user, :log_in, :create_site]
-
- setup %{user: user} do
- patch_env(:super_admin_user_ids, [user.id])
- end
-
test "renders custom plan form", %{conn: conn, user: user} do
lv = open_custom_plan(conn, team_of(user))
html = render(lv)
@@ -327,7 +315,8 @@ defmodule PlausibleWeb.Live.CustomerSupport.TeamsTest do
"site_segments" => "false",
"shared_links" => "true",
"sites_api" => "true",
- "sso" => "false"
+ "sso" => "false",
+ "consolidated_view" => "true"
}
}
})
@@ -342,6 +331,7 @@ defmodule PlausibleWeb.Live.CustomerSupport.TeamsTest do
%Plausible.Billing.EnterprisePlan{
billing_interval: :yearly,
features: [
+ Plausible.Billing.Feature.ConsolidatedView,
Plausible.Billing.Feature.SharedLinks,
Plausible.Billing.Feature.SitesAPI
],
@@ -745,12 +735,6 @@ defmodule PlausibleWeb.Live.CustomerSupport.TeamsTest do
end
describe "sso" do
- setup [:create_user, :log_in, :create_site]
-
- setup %{user: user} do
- patch_env(:super_admin_user_ids, [user.id])
- end
-
test "sso tab normally won't render", %{conn: conn, user: user} do
team = team_of(user)
{:ok, _lv, html} = live(conn, open_team(team.id))
@@ -840,12 +824,6 @@ defmodule PlausibleWeb.Live.CustomerSupport.TeamsTest do
end
describe "audit" do
- setup [:create_user, :log_in, :create_site]
-
- setup %{user: user} do
- patch_env(:super_admin_user_ids, [user.id])
- end
-
test "audit tab is present", %{conn: conn, user: user} do
team = team_of(user)
{:ok, _lv, html} = live(conn, open_team(team.id))
diff --git a/test/plausible_web/live/goal_settings/form_test.exs b/test/plausible_web/live/goal_settings/form_test.exs
index 1910bb54d528..ef6d2b6afdb0 100644
--- a/test/plausible_web/live/goal_settings/form_test.exs
+++ b/test/plausible_web/live/goal_settings/form_test.exs
@@ -135,6 +135,7 @@ defmodule PlausibleWeb.Live.GoalSettings.FormTest do
user: user
} do
{:ok, team} = Plausible.Teams.get_or_create(user)
+ new_site(team: team)
site = new_consolidated_view(team)
lv = get_liveview(conn, site)
diff --git a/test/plausible_web/live/sites_test.exs b/test/plausible_web/live/sites_test.exs
index 3b0801c61b63..bd073cffaede 100644
--- a/test/plausible_web/live/sites_test.exs
+++ b/test/plausible_web/live/sites_test.exs
@@ -283,14 +283,10 @@ defmodule PlausibleWeb.Live.SitesTest do
on_ee do
describe "consolidated views appearance" do
- setup %{user: user} do
- # this is temporary, instead of feature flag we'll only show consolidated views to super admins
- patch_env(:super_admin_user_ids, [user.id])
- end
-
test "consolidated view shows up", %{conn: conn, user: user} do
new_site(owner: user)
- team = team_of(user)
+ new_site(owner: user)
+ team = user |> team_of()
conn = set_current_team(conn, team)
@@ -298,7 +294,8 @@ defmodule PlausibleWeb.Live.SitesTest do
refute element_exists?(html, ~s|[data-test-id="consolidated-view-card"]|)
- new_consolidated_view(team)
+ team = Plausible.Teams.complete_setup(team)
+ conn = set_current_team(conn, team)
{:ok, _lv, html} = live(conn, "/sites")
@@ -321,12 +318,10 @@ defmodule PlausibleWeb.Live.SitesTest do
build(:pageview, user_id: 3)
])
- team = team_of(user)
+ team = user |> team_of() |> Plausible.Teams.complete_setup()
conn = set_current_team(conn, team)
- new_consolidated_view(team)
-
{:ok, _lv, html} = live(conn, "/sites")
stats = text_of_element(html, ~s|[data-test-id="consolidated-view-stats-loaded"]|)
@@ -336,24 +331,219 @@ defmodule PlausibleWeb.Live.SitesTest do
assert stats =~ "Views per visit 1.33"
end
- test "consolidated view does not show up for non-superadmin (temp)", %{conn: conn} do
- user = new_user()
+ test "consolidated view does not show up when flag is down (temp) during trial", %{
+ conn: conn,
+ user: user
+ } do
+ new_site(owner: user)
new_site(owner: user)
- team = team_of(user)
+
+ team = user |> team_of() |> Plausible.Teams.complete_setup()
+
+ FunWithFlags.disable(:consolidated_view, for_actor: team)
conn = set_current_team(conn, team)
{:ok, _lv, html} = live(conn, "/sites")
refute element_exists?(html, ~s|[data-test-id="consolidated-view-card"]|)
+ refute element_exists?(html, ~s|[data-test-id="consolidated-view-stats-loaded"]|)
+ refute element_exists?(html, ~s|[data-test-id="consolidated-view-chart-loaded"]|)
+ refute element_exists?(html, ~s|[data-test-id="consolidated-view-card-cta"]|)
+ end
+
+ test "consolidated view does not show up when flag is down (temp) after trial ends", %{
+ conn: conn,
+ user: user
+ } do
+ new_site(owner: user)
+ new_site(owner: user)
- new_consolidated_view(team)
+ team =
+ user
+ |> team_of()
+ |> Plausible.Teams.Team.end_trial()
+ |> Plausible.Repo.update!()
+
+ FunWithFlags.disable(:consolidated_view, for_actor: team)
+
+ conn = set_current_team(conn, team)
{:ok, _lv, html} = live(conn, "/sites")
refute element_exists?(html, ~s|[data-test-id="consolidated-view-card"]|)
refute element_exists?(html, ~s|[data-test-id="consolidated-view-stats-loaded"]|)
refute element_exists?(html, ~s|[data-test-id="consolidated-view-chart-loaded"]|)
+ refute element_exists?(html, ~s|[data-test-id="consolidated-view-card-cta"]|)
+ end
+
+ test "consolidated view disappears when trial ends - CTA is shown instead", %{
+ conn: conn,
+ user: user
+ } do
+ new_site(owner: user)
+ new_site(owner: user)
+ team = user |> team_of() |> Plausible.Teams.complete_setup()
+
+ conn = set_current_team(conn, team)
+
+ {:ok, _lv, html} = live(conn, "/sites")
+
+ refute element_exists?(html, ~s|[data-test-id="consolidated-view-card-cta"]|)
+ assert element_exists?(html, ~s|[data-test-id="consolidated-view-card"]|)
+
+ team |> Plausible.Teams.Team.end_trial() |> Plausible.Repo.update!()
+
+ {:ok, _lv, html} = live(conn, "/sites")
+
+ refute element_exists?(html, ~s|[data-test-id="consolidated-view-card"]|)
+ assert element_exists?(html, ~s|[data-test-id="consolidated-view-card-cta"]|)
+
+ assert text_of_element(html, ~s|[data-test-id="consolidated-view-card-cta"]|) =~
+ "Upgrade to the Business plan to enable consolidated views."
+
+ assert element_exists?(
+ html,
+ ~s|[data-test-id="consolidated-view-card-cta"] a[href$="/billing/choose-plan"]|
+ )
+ end
+
+ test "a team that hasn't been set up shows different CTA", %{
+ conn: conn,
+ user: user
+ } do
+ new_site(owner: user)
+ new_site(owner: user)
+
+ {:ok, _lv, html} = live(conn, "/sites")
+
+ assert element_exists?(html, ~s|[data-test-id="consolidated-view-card-cta"]|)
+
+ assert text_of_element(html, ~s|[data-test-id="consolidated-view-card-cta"]|) =~
+ "To create a consolidated view, you'll need to set up a team."
+ end
+
+ test "single site won't show neither CTA or view - team not setup", %{
+ conn: conn,
+ user: user
+ } do
+ new_site(owner: user)
+
+ {:ok, _lv, html} = live(conn, "/sites")
+
+ refute element_exists?(html, ~s|[data-test-id="consolidated-view-card-cta"]|)
+ refute element_exists?(html, ~s|[data-test-id="consolidated-view-card"]|)
+ end
+
+ test "single site won't show neither CTA or view - team setup", %{
+ conn: conn,
+ user: user
+ } do
+ new_site(owner: user)
+
+ user |> team_of() |> Plausible.Teams.complete_setup()
+
+ {:ok, _lv, html} = live(conn, "/sites")
+
+ refute element_exists?(html, ~s|[data-test-id="consolidated-view-card-cta"]|)
+ refute element_exists?(html, ~s|[data-test-id="consolidated-view-card"]|)
+ end
+
+ test "CTA advertises contacting team owner to viewers", %{
+ conn: conn,
+ user: user
+ } do
+ new_site(owner: user)
+ new_site(owner: user)
+
+ subscribe_to_growth_plan(user)
+
+ team = user |> team_of() |> Plausible.Teams.complete_setup()
+
+ viewer = add_member(team, role: :viewer)
+
+ {:ok, conn: conn} = log_in(%{user: viewer, conn: conn})
+
+ {:ok, _lv, html} = live(conn, "/sites?__team=#{team.identifier}")
+
+ assert element_exists?(html, ~s|[data-test-id="consolidated-view-card-cta"]|)
+
+ assert text_of_element(html, ~s|[data-test-id="consolidated-view-card-cta"]|) =~
+ "Available on Business plans. Contact your team owner to create it."
+
+ refute element_exists?(
+ html,
+ ~s|[data-test-id="consolidated-view-card-cta"] a[href="/billing/choose-plan"]|
+ )
+ end
+
+ test "CTA can be permanently dismissed, in which case dropdown option to restore it shows up",
+ %{conn: conn, user: user} do
+ new_site(owner: user)
+ new_site(owner: user)
+
+ dismiss_selector = ~s|[phx-click="consolidated-view-cta-dismiss"]|
+ cta_selector = ~s|[data-test-id="consolidated-view-card-cta"]|
+ restore_selector = ~s|[phx-click="consolidated-view-cta-restore"]|
+
+ subscribe_to_growth_plan(user)
+
+ {:ok, lv, html} = live(conn, "/sites")
+
+ assert element_exists?(html, cta_selector)
+ refute element_exists?(html, restore_selector)
+
+ lv
+ |> element(dismiss_selector)
+ |> render_click()
+
+ html = render(lv)
+
+ refute element_exists?(html, cta_selector)
+ assert element_exists?(html, restore_selector)
+
+ {:ok, _lv, html} = live(conn, "/sites")
+ refute element_exists?(html, cta_selector)
+
+ lv
+ |> element(restore_selector)
+ |> render_click()
+
+ html = render(lv)
+ assert element_exists?(html, cta_selector)
+ end
+
+ test "consolidated view card disappears when searching", %{conn: conn, user: user} do
+ new_site(owner: user)
+ new_site(owner: user)
+
+ team = user |> team_of() |> Plausible.Teams.complete_setup()
+ conn = set_current_team(conn, team)
+
+ {:ok, lv, html} = live(conn, "/sites")
+
+ assert element_exists?(html, ~s|[data-test-id="consolidated-view-card"]|)
+
+ type_into_input(lv, "filter-text", "a")
+
+ html = render(lv)
+
+ refute element_exists?(html, ~s|[data-test-id="consolidated-view-card"]|)
+ end
+
+ test "CTA card disappears when searching", %{conn: conn, user: user} do
+ new_site(owner: user)
+ new_site(owner: user)
+
+ {:ok, lv, html} = live(conn, "/sites")
+
+ assert element_exists?(html, ~s|[data-test-id="consolidated-view-card-cta"]|)
+
+ type_into_input(lv, "filter-text", "a")
+
+ html = render(lv)
+
+ refute element_exists?(html, ~s|[data-test-id="consolidated-view-card-cta"]|)
end
end
end
diff --git a/test/plausible_web/plugins/api/controllers/capabilities_test.exs b/test/plausible_web/plugins/api/controllers/capabilities_test.exs
index ee1efb19927d..39eec985defd 100644
--- a/test/plausible_web/plugins/api/controllers/capabilities_test.exs
+++ b/test/plausible_web/plugins/api/controllers/capabilities_test.exs
@@ -33,7 +33,8 @@ defmodule PlausibleWeb.Plugins.API.Controllers.CapabilitiesTest do
"SitesAPI" => false,
"SiteSegments" => false,
"SharedLinks" => false,
- "SSO" => false
+ "SSO" => false,
+ "ConsolidatedView" => false
}
}
@@ -61,7 +62,8 @@ defmodule PlausibleWeb.Plugins.API.Controllers.CapabilitiesTest do
"SitesAPI" => false,
"SiteSegments" => false,
"SharedLinks" => false,
- "SSO" => false
+ "SSO" => false,
+ "ConsolidatedView" => false
}
}
@@ -91,7 +93,8 @@ defmodule PlausibleWeb.Plugins.API.Controllers.CapabilitiesTest do
"SitesAPI" => false,
"SiteSegments" => true,
"SharedLinks" => true,
- "SSO" => false
+ "SSO" => false,
+ "ConsolidatedView" => true
}
}
@@ -123,7 +126,8 @@ defmodule PlausibleWeb.Plugins.API.Controllers.CapabilitiesTest do
"SitesAPI" => false,
"SiteSegments" => false,
"SharedLinks" => true,
- "SSO" => false
+ "SSO" => false,
+ "ConsolidatedView" => false
}
}
@@ -158,7 +162,8 @@ defmodule PlausibleWeb.Plugins.API.Controllers.CapabilitiesTest do
"SitesAPI" => true,
"SiteSegments" => false,
"SharedLinks" => false,
- "SSO" => false
+ "SSO" => false,
+ "ConsolidatedView" => false
}
}
diff --git a/test/test_helper.exs b/test/test_helper.exs
index 8f7a58d08cba..60dcf4286664 100644
--- a/test/test_helper.exs
+++ b/test/test_helper.exs
@@ -11,8 +11,7 @@ Mox.defmock(Plausible.DnsLookup.Mock,
Application.ensure_all_started(:double)
-FunWithFlags.enable(:channels)
-FunWithFlags.enable(:scroll_depth)
+FunWithFlags.enable(:consolidated_view)
Ecto.Adapters.SQL.Sandbox.mode(Plausible.Repo, :manual)