diff --git a/lib/plausible/installation_support/browserless_config.ex b/extra/lib/plausible/installation_support/browserless_config.ex similarity index 100% rename from lib/plausible/installation_support/browserless_config.ex rename to extra/lib/plausible/installation_support/browserless_config.ex diff --git a/lib/plausible/installation_support/check.ex b/extra/lib/plausible/installation_support/check.ex similarity index 100% rename from lib/plausible/installation_support/check.ex rename to extra/lib/plausible/installation_support/check.ex diff --git a/lib/plausible/installation_support/check_runner.ex b/extra/lib/plausible/installation_support/check_runner.ex similarity index 100% rename from lib/plausible/installation_support/check_runner.ex rename to extra/lib/plausible/installation_support/check_runner.ex diff --git a/lib/plausible/installation_support/checks/csp.ex b/extra/lib/plausible/installation_support/checks/csp.ex similarity index 100% rename from lib/plausible/installation_support/checks/csp.ex rename to extra/lib/plausible/installation_support/checks/csp.ex diff --git a/lib/plausible/installation_support/checks/detection.ex b/extra/lib/plausible/installation_support/checks/detection.ex similarity index 100% rename from lib/plausible/installation_support/checks/detection.ex rename to extra/lib/plausible/installation_support/checks/detection.ex diff --git a/lib/plausible/installation_support/checks/fetch_body.ex b/extra/lib/plausible/installation_support/checks/fetch_body.ex similarity index 100% rename from lib/plausible/installation_support/checks/fetch_body.ex rename to extra/lib/plausible/installation_support/checks/fetch_body.ex diff --git a/lib/plausible/installation_support/checks/installation.ex b/extra/lib/plausible/installation_support/checks/installation.ex similarity index 100% rename from lib/plausible/installation_support/checks/installation.ex rename to extra/lib/plausible/installation_support/checks/installation.ex diff --git a/lib/plausible/installation_support/checks/installation_v2.ex b/extra/lib/plausible/installation_support/checks/installation_v2.ex similarity index 100% rename from lib/plausible/installation_support/checks/installation_v2.ex rename to extra/lib/plausible/installation_support/checks/installation_v2.ex diff --git a/lib/plausible/installation_support/checks/installation_v2_cache_bust.ex b/extra/lib/plausible/installation_support/checks/installation_v2_cache_bust.ex similarity index 100% rename from lib/plausible/installation_support/checks/installation_v2_cache_bust.ex rename to extra/lib/plausible/installation_support/checks/installation_v2_cache_bust.ex diff --git a/lib/plausible/installation_support/checks/scan_body.ex b/extra/lib/plausible/installation_support/checks/scan_body.ex similarity index 100% rename from lib/plausible/installation_support/checks/scan_body.ex rename to extra/lib/plausible/installation_support/checks/scan_body.ex diff --git a/lib/plausible/installation_support/checks/snippet.ex b/extra/lib/plausible/installation_support/checks/snippet.ex similarity index 100% rename from lib/plausible/installation_support/checks/snippet.ex rename to extra/lib/plausible/installation_support/checks/snippet.ex diff --git a/lib/plausible/installation_support/checks/snippet_cache_bust.ex b/extra/lib/plausible/installation_support/checks/snippet_cache_bust.ex similarity index 100% rename from lib/plausible/installation_support/checks/snippet_cache_bust.ex rename to extra/lib/plausible/installation_support/checks/snippet_cache_bust.ex diff --git a/lib/plausible/installation_support/checks/url.ex b/extra/lib/plausible/installation_support/checks/url.ex similarity index 100% rename from lib/plausible/installation_support/checks/url.ex rename to extra/lib/plausible/installation_support/checks/url.ex diff --git a/lib/plausible/installation_support/detection/checks.ex b/extra/lib/plausible/installation_support/detection/checks.ex similarity index 100% rename from lib/plausible/installation_support/detection/checks.ex rename to extra/lib/plausible/installation_support/detection/checks.ex diff --git a/lib/plausible/installation_support/detection/diagnostics.ex b/extra/lib/plausible/installation_support/detection/diagnostics.ex similarity index 100% rename from lib/plausible/installation_support/detection/diagnostics.ex rename to extra/lib/plausible/installation_support/detection/diagnostics.ex diff --git a/lib/plausible/installation_support/installation_support.ex b/extra/lib/plausible/installation_support/installation_support.ex similarity index 100% rename from lib/plausible/installation_support/installation_support.ex rename to extra/lib/plausible/installation_support/installation_support.ex diff --git a/lib/plausible/installation_support/legacy_verification/checks.ex b/extra/lib/plausible/installation_support/legacy_verification/checks.ex similarity index 100% rename from lib/plausible/installation_support/legacy_verification/checks.ex rename to extra/lib/plausible/installation_support/legacy_verification/checks.ex diff --git a/lib/plausible/installation_support/legacy_verification/diagnostics.ex b/extra/lib/plausible/installation_support/legacy_verification/diagnostics.ex similarity index 100% rename from lib/plausible/installation_support/legacy_verification/diagnostics.ex rename to extra/lib/plausible/installation_support/legacy_verification/diagnostics.ex diff --git a/lib/plausible/installation_support/legacy_verification/errors.ex b/extra/lib/plausible/installation_support/legacy_verification/errors.ex similarity index 100% rename from lib/plausible/installation_support/legacy_verification/errors.ex rename to extra/lib/plausible/installation_support/legacy_verification/errors.ex diff --git a/lib/plausible/installation_support/result.ex b/extra/lib/plausible/installation_support/result.ex similarity index 100% rename from lib/plausible/installation_support/result.ex rename to extra/lib/plausible/installation_support/result.ex diff --git a/lib/plausible/installation_support/state.ex b/extra/lib/plausible/installation_support/state.ex similarity index 100% rename from lib/plausible/installation_support/state.ex rename to extra/lib/plausible/installation_support/state.ex diff --git a/lib/plausible/installation_support/url.ex b/extra/lib/plausible/installation_support/url.ex similarity index 100% rename from lib/plausible/installation_support/url.ex rename to extra/lib/plausible/installation_support/url.ex diff --git a/lib/plausible/installation_support/verification/checks.ex b/extra/lib/plausible/installation_support/verification/checks.ex similarity index 100% rename from lib/plausible/installation_support/verification/checks.ex rename to extra/lib/plausible/installation_support/verification/checks.ex diff --git a/lib/plausible/installation_support/verification/diagnostics.ex b/extra/lib/plausible/installation_support/verification/diagnostics.ex similarity index 100% rename from lib/plausible/installation_support/verification/diagnostics.ex rename to extra/lib/plausible/installation_support/verification/diagnostics.ex diff --git a/lib/plausible_web/live/verification.ex b/extra/lib/plausible_web/live/verification.ex similarity index 66% rename from lib/plausible_web/live/verification.ex rename to extra/lib/plausible_web/live/verification.ex index 8cfe7e9d74..898aad7c88 100644 --- a/lib/plausible_web/live/verification.ex +++ b/extra/lib/plausible_web/live/verification.ex @@ -4,7 +4,6 @@ defmodule PlausibleWeb.Live.Verification do Onboarding new sites, renders a standalone component. Embedded modal variant is available for general site settings. """ - use Plausible use PlausibleWeb, :live_view import PlausibleWeb.Components.Generic @@ -61,66 +60,29 @@ defmodule PlausibleWeb.Live.Verification do custom_url_input?: custom_url_input? ) - on_ee do - if connected?(socket) and not custom_url_input? do - launch_delayed(socket) - end + if connected?(socket) and not custom_url_input? do + launch_delayed(socket) end - on_ee do - {:ok, socket} - else - # on CE we skip the verification process and instead, - # we just wait for the first pageview to be recorded - socket = - if has_pageviews? do - redirect_to_stats(socket) - else - schedule_pageviews_check(socket) - end - - {:ok, socket} - end + {:ok, socket} end - on_ee do - def render(assigns) do - ~H""" - - <.custom_url_form :if={@custom_url_input?} domain={@domain} /> - <.live_component - :if={not @custom_url_input?} - module={@component} - installation_type={@installation_type} - domain={@domain} - id="verification-standalone" - attempts={@attempts} - flow={@flow} - awaiting_first_pageview?={not @has_pageviews?} - super_admin?={@super_admin?} - /> - """ - end - else - def render(assigns) do - ~H""" - - <.awaiting_pageviews /> - """ - end - end - - on_ce do - defp awaiting_pageviews(assigns) do - ~H""" - <.focus_box> -
-
-

Awaiting your first pageview …

-
- - """ - end + def render(assigns) do + ~H""" + + <.custom_url_form :if={@custom_url_input?} domain={@domain} /> + <.live_component + :if={not @custom_url_input?} + module={@component} + installation_type={@installation_type} + domain={@domain} + id="verification-standalone" + attempts={@attempts} + flow={@flow} + awaiting_first_pageview?={not @has_pageviews?} + super_admin?={@super_admin?} + /> + """ end def handle_event("launch-verification", _, socket) do @@ -300,48 +262,46 @@ defmodule PlausibleWeb.Live.Verification do Plausible.Stats.Clickhouse.has_pageviews?(site) end - on_ee do - defp custom_url_form(assigns) do - ~H""" - <.focus_box> -
- -
-
-

- Enter Your Custom URL -

-

- Please enter the URL where your website with the Plausible script is located. -

-
-
- - -
- -
-
- - """ - end + Website URL + + + + + + + + """ end end diff --git a/lib/plausible/ingestion/event.ex b/lib/plausible/ingestion/event.ex index bf59d039e8..2af01f58e1 100644 --- a/lib/plausible/ingestion/event.ex +++ b/lib/plausible/ingestion/event.ex @@ -21,8 +21,6 @@ defmodule Plausible.Ingestion.Event do salts: nil, changeset: nil - @verification_user_agent Plausible.InstallationSupport.user_agent() - @type drop_reason() :: :bot | :spam_referrer @@ -193,14 +191,20 @@ defmodule Plausible.Ingestion.Event do struct!(event, clickhouse_session_attrs: Map.merge(event.clickhouse_session_attrs, attrs)) end - defp drop_verification_agent(%__MODULE__{} = event, _context) do - case event.request.user_agent do - @verification_user_agent -> - drop(event, :verification_agent) + on_ee do + @verification_user_agent Plausible.InstallationSupport.user_agent() - _ -> - event + defp drop_verification_agent(%__MODULE__{} = event, _context) do + case event.request.user_agent do + @verification_user_agent -> + drop(event, :verification_agent) + + _ -> + event + end end + else + defp drop_verification_agent(%__MODULE__{} = event, _context), do: event end defp drop_datacenter_ip(%__MODULE__{} = event, _context) do diff --git a/lib/plausible/telemetry/plausible_metrics.ex b/lib/plausible/telemetry/plausible_metrics.ex index dd8d4ab25e..3bb814ab31 100644 --- a/lib/plausible/telemetry/plausible_metrics.ex +++ b/lib/plausible/telemetry/plausible_metrics.ex @@ -2,6 +2,7 @@ defmodule Plausible.PromEx.Plugins.PlausibleMetrics do @moduledoc """ Custom PromEx plugin for instrumenting code within Plausible app. """ + use Plausible use PromEx.Plugin alias Plausible.Site alias Plausible.Ingestion @@ -140,17 +141,26 @@ defmodule Plausible.PromEx.Plugins.PlausibleMetrics do tags: [:status], tag_values: &%{status: &1.status} ), - counter( - metric_prefix ++ [:verification, :js_elixir_diff], - event_name: - Plausible.InstallationSupport.Checks.Installation.telemetry_event(_diff = true) + on_ee( + do: + counter( + metric_prefix ++ [:verification, :js_elixir_diff], + event_name: + Plausible.InstallationSupport.Checks.Installation.telemetry_event(_diff = true) + ), + else: nil ), - counter( - metric_prefix ++ [:verification, :js_elixir_match], - event_name: - Plausible.InstallationSupport.Checks.Installation.telemetry_event(_diff = false) + on_ee( + do: + counter( + metric_prefix ++ [:verification, :js_elixir_match], + event_name: + Plausible.InstallationSupport.Checks.Installation.telemetry_event(_diff = false) + ), + else: nil ) ] + |> Enum.reject(&is_nil/1) ) end diff --git a/lib/plausible_web/live/awaiting_pageviews.ex b/lib/plausible_web/live/awaiting_pageviews.ex new file mode 100644 index 0000000000..29c4f3e731 --- /dev/null +++ b/lib/plausible_web/live/awaiting_pageviews.ex @@ -0,0 +1,99 @@ +defmodule PlausibleWeb.Live.AwaitingPageviews do + @moduledoc """ + A replacement for installation verification on Community Edition. + """ + use PlausibleWeb, :live_view + + import PlausibleWeb.Components.Generic + + def mount( + %{"domain" => domain} = params, + _session, + socket + ) do + current_user = socket.assigns.current_user + + site = + Plausible.Sites.get_for_user!(current_user, domain, + roles: [ + :owner, + :admin, + :editor, + :super_admin, + :viewer + ] + ) + + private = Map.get(socket.private.connect_info, :private, %{}) + + has_pageviews? = has_pageviews?(site) + + socket = + assign(socket, + site: site, + domain: domain, + has_pageviews?: has_pageviews?, + delay: private[:delay] || 500, + flow: params["flow"] || "", + polling_pageviews?: false + ) + + socket = + if has_pageviews? do + redirect_to_stats(socket) + else + schedule_pageviews_check(socket) + end + + {:ok, socket} + end + + def render(assigns) do + ~H""" + + <.awaiting_pageviews /> + """ + end + + defp awaiting_pageviews(assigns) do + ~H""" + <.focus_box> +
+
+

Awaiting your first pageview …

+
+ + """ + end + + def handle_info(:check_pageviews, socket) do + socket = + if has_pageviews?(socket.assigns.site) do + redirect_to_stats(socket) + else + socket + |> assign(polling_pageviews?: false) + |> schedule_pageviews_check() + end + + {:noreply, socket} + end + + defp schedule_pageviews_check(socket) do + if socket.assigns.polling_pageviews? do + socket + else + Process.send_after(self(), :check_pageviews, socket.assigns.delay * 2) + assign(socket, polling_pageviews?: true) + end + end + + defp redirect_to_stats(socket) do + stats_url = Routes.stats_path(PlausibleWeb.Endpoint, :stats, socket.assigns.domain, []) + redirect(socket, to: stats_url) + end + + defp has_pageviews?(site) do + Plausible.Stats.Clickhouse.has_pageviews?(site) + end +end diff --git a/lib/plausible_web/live/installation.ex b/lib/plausible_web/live/installation.ex index 9ba6bb0567..87f51accab 100644 --- a/lib/plausible_web/live/installation.ex +++ b/lib/plausible_web/live/installation.ex @@ -3,7 +3,10 @@ defmodule PlausibleWeb.Live.Installation do User assistance module around Plausible installation instructions/onboarding """ use PlausibleWeb, :live_view - alias Plausible.InstallationSupport.{State, Checks, LegacyVerification} + + on_ee do + alias Plausible.InstallationSupport.{State, Checks, LegacyVerification} + end @script_extension_params %{ "outbound_links" => "outbound-links", @@ -68,16 +71,18 @@ defmodule PlausibleWeb.Live.Installation do {key, Map.get(tracker_script_configuration, string_key)} end) - if connected?(socket) and is_nil(installation_type) do - LegacyVerification.Checks.run("https://#{domain}", domain, - checks: [ - Checks.FetchBody, - Checks.ScanBody - ], - report_to: self(), - async?: true, - slowdown: 0 - ) + on_ee do + if connected?(socket) and is_nil(installation_type) do + LegacyVerification.Checks.run("https://#{domain}", domain, + checks: [ + Checks.FetchBody, + Checks.ScanBody + ], + report_to: self(), + async?: true, + slowdown: 0 + ) + end end {:ok, @@ -95,23 +100,25 @@ defmodule PlausibleWeb.Live.Installation do end end - def handle_info({:all_checks_done, %State{} = state}, socket) do - installation_type = - case state.diagnostics do - %{wordpress_likely?: true} -> "wordpress" - %{gtm_likely?: true} -> "gtm" - _ -> "manual" - end + on_ee do + def handle_info({:all_checks_done, %State{} = state}, socket) do + installation_type = + case state.diagnostics do + %{wordpress_likely?: true} -> "wordpress" + %{gtm_likely?: true} -> "gtm" + _ -> "manual" + end - {:noreply, - assign(socket, - initial_installation_type: installation_type, - installation_type: installation_type - )} - end + {:noreply, + assign(socket, + initial_installation_type: installation_type, + installation_type: installation_type + )} + end - def handle_info(_msg, socket) do - {:noreply, socket} + def handle_info(_msg, socket) do + {:noreply, socket} + end end def render(assigns) do diff --git a/lib/plausible_web/router.ex b/lib/plausible_web/router.ex index 13c07e08f8..7a6a70f524 100644 --- a/lib/plausible_web/router.ex +++ b/lib/plausible_web/router.ex @@ -629,7 +629,10 @@ defmodule PlausibleWeb.Router do scope assigns: %{ dogfood_page_path: "/:website/verification" } do - live "/:domain/verification", Verification, :verification, as: :site + live "/:domain/verification", + on_ee(do: Verification, else: AwaitingPageviews), + :verification, + as: :site end scope assigns: %{ diff --git a/test/plausible/ingestion/event_test.exs b/test/plausible/ingestion/event_test.exs index d36246ef3a..609b845d7d 100644 --- a/test/plausible/ingestion/event_test.exs +++ b/test/plausible/ingestion/event_test.exs @@ -80,22 +80,24 @@ defmodule Plausible.Ingestion.EventTest do assert_receive :telemetry_handled end - test "drops installation support user agent" do - site = new_site() + on_ee do + test "drops installation support user agent" do + site = new_site() - payload = %{ - name: "pageview", - url: "http://#{site.domain}" - } + payload = %{ + name: "pageview", + url: "http://#{site.domain}" + } - conn = - build_conn(:post, "/api/events", payload) - |> Plug.Conn.put_req_header("user-agent", Plausible.InstallationSupport.user_agent()) + conn = + build_conn(:post, "/api/events", payload) + |> Plug.Conn.put_req_header("user-agent", Plausible.InstallationSupport.user_agent()) - assert {:ok, request} = Request.build(conn) + assert {:ok, request} = Request.build(conn) - assert {:ok, %{buffered: [], dropped: [dropped]}} = Event.build_and_buffer(request) - assert dropped.drop_reason == :verification_agent + assert {:ok, %{buffered: [], dropped: [dropped]}} = Event.build_and_buffer(request) + assert dropped.drop_reason == :verification_agent + end end test "drops a request when site does not exists" do diff --git a/test/plausible/installation_support/checks/csp_test.exs b/test/plausible/installation_support/checks/csp_test.exs index 34b76080f4..6ec2fa9cb2 100644 --- a/test/plausible/installation_support/checks/csp_test.exs +++ b/test/plausible/installation_support/checks/csp_test.exs @@ -1,40 +1,42 @@ defmodule Plausible.InstallationSupport.Checks.CSPTest do use Plausible.DataCase, async: true - alias Plausible.InstallationSupport.{State, LegacyVerification} + on_ee do + alias Plausible.InstallationSupport.{State, LegacyVerification} - @check Plausible.InstallationSupport.Checks.CSP - @default_state %State{diagnostics: %LegacyVerification.Diagnostics{}} + @check Plausible.InstallationSupport.Checks.CSP + @default_state %State{diagnostics: %LegacyVerification.Diagnostics{}} - test "skips no headers" do - state = @default_state - assert ^state = @check.perform(state) - end + test "skips no headers" do + state = @default_state + assert ^state = @check.perform(state) + end - test "skips no headers 2" do - state = @default_state |> State.assign(headers: %{}) - assert ^state = @check.perform(state) - end + test "skips no headers 2" do + state = @default_state |> State.assign(headers: %{}) + assert ^state = @check.perform(state) + end - test "disallowed" do - headers = %{"content-security-policy" => ["default-src 'self' foo.local; example.com"]} + test "disallowed" do + headers = %{"content-security-policy" => ["default-src 'self' foo.local; example.com"]} - state = - @default_state - |> State.assign(headers: headers) - |> @check.perform() + state = + @default_state + |> State.assign(headers: headers) + |> @check.perform() - assert state.diagnostics.disallowed_via_csp? - end + assert state.diagnostics.disallowed_via_csp? + end - test "allowed" do - headers = %{"content-security-policy" => ["default-src 'self' example.com; localhost"]} + test "allowed" do + headers = %{"content-security-policy" => ["default-src 'self' example.com; localhost"]} - state = - @default_state - |> State.assign(headers: headers) - |> @check.perform() + state = + @default_state + |> State.assign(headers: headers) + |> @check.perform() - refute state.diagnostics.disallowed_via_csp? + refute state.diagnostics.disallowed_via_csp? + end end end diff --git a/test/plausible/installation_support/checks/fetch_body_test.exs b/test/plausible/installation_support/checks/fetch_body_test.exs index af501ab1a0..86b58f1ee0 100644 --- a/test/plausible/installation_support/checks/fetch_body_test.exs +++ b/test/plausible/installation_support/checks/fetch_body_test.exs @@ -1,64 +1,66 @@ defmodule Plausible.InstallationSupport.Checks.FetchBodyTest do use Plausible.DataCase, async: true - import Plug.Conn + on_ee do + import Plug.Conn - alias Plausible.InstallationSupport.{State, Checks, LegacyVerification} + alias Plausible.InstallationSupport.{State, Checks, LegacyVerification} - @check Checks.FetchBody + @check Checks.FetchBody - @normal_body """ - - - - - Hello - - """ + @normal_body """ + + + + + Hello + + """ - setup do - {:ok, - state: %State{ - url: "https://example.com", - diagnostics: %LegacyVerification.Diagnostics{} - }} - end + setup do + {:ok, + state: %State{ + url: "https://example.com", + diagnostics: %LegacyVerification.Diagnostics{} + }} + end - test "extracts document", %{state: state} do - stub() - state = @check.perform(state) + test "extracts document", %{state: state} do + stub() + state = @check.perform(state) - assert state.assigns.raw_body == @normal_body - assert state.assigns.document == Floki.parse_document!(@normal_body) - assert state.assigns.headers["content-type"] == ["text/html; charset=utf-8"] + assert state.assigns.raw_body == @normal_body + assert state.assigns.document == Floki.parse_document!(@normal_body) + assert state.assigns.headers["content-type"] == ["text/html; charset=utf-8"] - assert state.diagnostics.body_fetched? - end + assert state.diagnostics.body_fetched? + end - test "does extract on non-2xx", %{state: state} do - stub(400) - state = @check.perform(state) - assert state.diagnostics.body_fetched? - end + test "does extract on non-2xx", %{state: state} do + stub(400) + state = @check.perform(state) + assert state.diagnostics.body_fetched? + end - test "doesn't extract non-HTML", %{state: state} do - stub(200, @normal_body, "text/plain") - state = @check.perform(state) + test "doesn't extract non-HTML", %{state: state} do + stub(200, @normal_body, "text/plain") + state = @check.perform(state) - assert state.assigns == %{final_domain: "example.com"} + assert state.assigns == %{final_domain: "example.com"} - refute state.diagnostics.body_fetched? - end + refute state.diagnostics.body_fetched? + end - defp stub(f) when is_function(f, 1) do - Req.Test.stub(@check, f) - end + defp stub(f) when is_function(f, 1) do + Req.Test.stub(@check, f) + end - defp stub(status \\ 200, body \\ @normal_body, content_type \\ "text/html") do - stub(fn conn -> - conn - |> put_resp_content_type(content_type) - |> send_resp(status, body) - end) + defp stub(status \\ 200, body \\ @normal_body, content_type \\ "text/html") do + stub(fn conn -> + conn + |> put_resp_content_type(content_type) + |> send_resp(status, body) + end) + end end end diff --git a/test/plausible/installation_support/checks/scan_body_test.exs b/test/plausible/installation_support/checks/scan_body_test.exs index 01bd85ca21..7b80e529d6 100644 --- a/test/plausible/installation_support/checks/scan_body_test.exs +++ b/test/plausible/installation_support/checks/scan_body_test.exs @@ -1,82 +1,84 @@ defmodule Plausible.InstallationSupport.Checks.ScanBodyTest do use Plausible.DataCase, async: true - alias Plausible.InstallationSupport.{State, Checks, LegacyVerification} + on_ee do + alias Plausible.InstallationSupport.{State, Checks, LegacyVerification} - @check Checks.ScanBody - @default_state %State{diagnostics: %LegacyVerification.Diagnostics{}} + @check Checks.ScanBody + @default_state %State{diagnostics: %LegacyVerification.Diagnostics{}} - test "skips on no raw body" do - assert @default_state = @check.perform(@default_state) - end + test "skips on no raw body" do + assert @default_state = @check.perform(@default_state) + end - test "detects nothing" do - state = - @default_state - |> State.assign(raw_body: "...") - |> @check.perform() - - refute state.diagnostics.gtm_likely? - refute state.diagnostics.wordpress_likely? - end - - test "detects GTM" do - state = - @default_state - |> State.assign(raw_body: "...googletagmanager.com/gtm.js...") - |> @check.perform() - - assert state.diagnostics.gtm_likely? - refute state.diagnostics.wordpress_likely? - refute state.diagnostics.cookie_banner_likely? - end - - test "detects GTM and cookie banner" do - state = - @default_state - |> State.assign(raw_body: "...googletagmanager.com/gtm.js...cookiebot...") - |> @check.perform() - - assert state.diagnostics.gtm_likely? - assert state.diagnostics.cookie_banner_likely? - refute state.diagnostics.wordpress_likely? - end - - for signature <- ["wp-content", "wp-includes", "wp-json"] do - test "detects WordPress: #{signature}" do + test "detects nothing" do state = @default_state - |> State.assign(raw_body: "...#{unquote(signature)}...") + |> State.assign(raw_body: "...") |> @check.perform() refute state.diagnostics.gtm_likely? + refute state.diagnostics.wordpress_likely? + end + + test "detects GTM" do + state = + @default_state + |> State.assign(raw_body: "...googletagmanager.com/gtm.js...") + |> @check.perform() + + assert state.diagnostics.gtm_likely? + refute state.diagnostics.wordpress_likely? + refute state.diagnostics.cookie_banner_likely? + end + + test "detects GTM and cookie banner" do + state = + @default_state + |> State.assign(raw_body: "...googletagmanager.com/gtm.js...cookiebot...") + |> @check.perform() + + assert state.diagnostics.gtm_likely? + assert state.diagnostics.cookie_banner_likely? + refute state.diagnostics.wordpress_likely? + end + + for signature <- ["wp-content", "wp-includes", "wp-json"] do + test "detects WordPress: #{signature}" do + state = + @default_state + |> State.assign(raw_body: "...#{unquote(signature)}...") + |> @check.perform() + + refute state.diagnostics.gtm_likely? + assert state.diagnostics.wordpress_likely? + refute state.diagnostics.wordpress_plugin? + end + end + + test "detects GTM and WordPress" do + state = + @default_state + |> State.assign(raw_body: "...googletagmanager.com/gtm.js....wp-content...") + |> @check.perform() + + assert state.diagnostics.gtm_likely? assert state.diagnostics.wordpress_likely? refute state.diagnostics.wordpress_plugin? end - end - test "detects GTM and WordPress" do - state = - @default_state - |> State.assign(raw_body: "...googletagmanager.com/gtm.js....wp-content...") - |> @check.perform() + @d """ + + """ - assert state.diagnostics.gtm_likely? - assert state.diagnostics.wordpress_likely? - refute state.diagnostics.wordpress_plugin? - end + test "detects official plugin" do + state = + @default_state + |> State.assign(raw_body: @d, document: Floki.parse_document!(@d)) + |> @check.perform() - @d """ - - """ - - test "detects official plugin" do - state = - @default_state - |> State.assign(raw_body: @d, document: Floki.parse_document!(@d)) - |> @check.perform() - - assert state.diagnostics.wordpress_likely? - assert state.diagnostics.wordpress_plugin? + assert state.diagnostics.wordpress_likely? + assert state.diagnostics.wordpress_plugin? + end end end diff --git a/test/plausible/installation_support/checks/snippet_test.exs b/test/plausible/installation_support/checks/snippet_test.exs index 7483851c8a..beffc28841 100644 --- a/test/plausible/installation_support/checks/snippet_test.exs +++ b/test/plausible/installation_support/checks/snippet_test.exs @@ -1,164 +1,166 @@ defmodule Plausible.InstallationSupport.Checks.SnippetTest do use Plausible.DataCase, async: true - alias Plausible.InstallationSupport.{State, Checks, LegacyVerification} + on_ee do + alias Plausible.InstallationSupport.{State, Checks, LegacyVerification} - @check Checks.Snippet - @default_state %State{diagnostics: %LegacyVerification.Diagnostics{}} + @check Checks.Snippet + @default_state %State{diagnostics: %LegacyVerification.Diagnostics{}} - test "skips when there's no document" do - state = @default_state - assert ^state = @check.perform(state) - end + test "skips when there's no document" do + state = @default_state + assert ^state = @check.perform(state) + end - @well_placed """ - - - - """ + @well_placed """ + + + + """ - test "figures out well placed snippet" do - state = - @well_placed - |> new_state() - |> @check.perform() + test "figures out well placed snippet" do + state = + @well_placed + |> new_state() + |> @check.perform() - assert state.diagnostics.snippets_found_in_head == 1 - assert state.diagnostics.snippets_found_in_body == 0 - refute state.diagnostics.data_domain_mismatch? - refute state.diagnostics.snippet_unknown_attributes? - refute state.diagnostics.proxy_likely? - refute state.diagnostics.manual_script_extension? - end + assert state.diagnostics.snippets_found_in_head == 1 + assert state.diagnostics.snippets_found_in_body == 0 + refute state.diagnostics.data_domain_mismatch? + refute state.diagnostics.snippet_unknown_attributes? + refute state.diagnostics.proxy_likely? + refute state.diagnostics.manual_script_extension? + end - @multi_domain """ - - - - """ + @multi_domain """ + + + + """ - test "figures out well placed snippet in a multi-domain setup" do - state = - @multi_domain - |> new_state() - |> @check.perform() + test "figures out well placed snippet in a multi-domain setup" do + state = + @multi_domain + |> new_state() + |> @check.perform() - assert state.diagnostics.snippets_found_in_head == 1 - assert state.diagnostics.snippets_found_in_body == 0 - refute state.diagnostics.data_domain_mismatch? - refute state.diagnostics.snippet_unknown_attributes? - refute state.diagnostics.proxy_likely? - refute state.diagnostics.manual_script_extension? - end + assert state.diagnostics.snippets_found_in_head == 1 + assert state.diagnostics.snippets_found_in_body == 0 + refute state.diagnostics.data_domain_mismatch? + refute state.diagnostics.snippet_unknown_attributes? + refute state.diagnostics.proxy_likely? + refute state.diagnostics.manual_script_extension? + end - @crazy """ - - - - - - - - - - """ - test "counts snippets" do - state = - @crazy - |> new_state() - |> @check.perform() + @crazy """ + + + + + + + + + + """ + test "counts snippets" do + state = + @crazy + |> new_state() + |> @check.perform() - assert state.diagnostics.snippets_found_in_head == 2 - assert state.diagnostics.snippets_found_in_body == 3 - refute state.diagnostics.manual_script_extension? - end + assert state.diagnostics.snippets_found_in_head == 2 + assert state.diagnostics.snippets_found_in_body == 3 + refute state.diagnostics.manual_script_extension? + end - test "figures out data-domain mismatch" do - state = - @well_placed - |> new_state(data_domain: "example.typo") - |> @check.perform() + test "figures out data-domain mismatch" do + state = + @well_placed + |> new_state(data_domain: "example.typo") + |> @check.perform() - assert state.diagnostics.snippets_found_in_head == 1 - assert state.diagnostics.snippets_found_in_body == 0 - assert state.diagnostics.data_domain_mismatch? - refute state.diagnostics.snippet_unknown_attributes? - refute state.diagnostics.proxy_likely? - refute state.diagnostics.manual_script_extension? - end + assert state.diagnostics.snippets_found_in_head == 1 + assert state.diagnostics.snippets_found_in_body == 0 + assert state.diagnostics.data_domain_mismatch? + refute state.diagnostics.snippet_unknown_attributes? + refute state.diagnostics.proxy_likely? + refute state.diagnostics.manual_script_extension? + end - @proxy_likely """ - - - - """ + @proxy_likely """ + + + + """ - test "figures out proxy likely" do - state = - @proxy_likely - |> new_state() - |> @check.perform() + test "figures out proxy likely" do + state = + @proxy_likely + |> new_state() + |> @check.perform() - assert state.diagnostics.snippets_found_in_head == 1 - assert state.diagnostics.snippets_found_in_body == 0 - refute state.diagnostics.data_domain_mismatch? - refute state.diagnostics.snippet_unknown_attributes? - assert state.diagnostics.proxy_likely? - refute state.diagnostics.manual_script_extension? - end + assert state.diagnostics.snippets_found_in_head == 1 + assert state.diagnostics.snippets_found_in_body == 0 + refute state.diagnostics.data_domain_mismatch? + refute state.diagnostics.snippet_unknown_attributes? + assert state.diagnostics.proxy_likely? + refute state.diagnostics.manual_script_extension? + end - @manual_extension """ - - - - """ + @manual_extension """ + + + + """ - test "figures out manual script extension" do - state = - @manual_extension - |> new_state() - |> @check.perform() + test "figures out manual script extension" do + state = + @manual_extension + |> new_state() + |> @check.perform() - assert state.diagnostics.manual_script_extension? - end + assert state.diagnostics.manual_script_extension? + end - @unknown_attributes """ - - - - """ + @unknown_attributes """ + + + + """ - @valid_attributes """ - - - - """ + @valid_attributes """ + + + + """ - test "figures out unknown attributes" do - state = - @valid_attributes - |> new_state() - |> @check.perform() + test "figures out unknown attributes" do + state = + @valid_attributes + |> new_state() + |> @check.perform() - refute state.diagnostics.snippet_unknown_attributes? + refute state.diagnostics.snippet_unknown_attributes? - state = - @unknown_attributes - |> new_state() - |> @check.perform() + state = + @unknown_attributes + |> new_state() + |> @check.perform() - assert state.diagnostics.snippet_unknown_attributes? - end + assert state.diagnostics.snippet_unknown_attributes? + end - defp new_state(html, opts \\ []) do - doc = Floki.parse_document!(html) + defp new_state(html, opts \\ []) do + doc = Floki.parse_document!(html) - opts = - [data_domain: "example.com"] - |> Keyword.merge(opts) + opts = + [data_domain: "example.com"] + |> Keyword.merge(opts) - @default_state - |> struct!(opts) - |> State.assign(document: doc) + @default_state + |> struct!(opts) + |> State.assign(document: doc) + end end end diff --git a/test/plausible/installation_support/checks/url_test.exs b/test/plausible/installation_support/checks/url_test.exs index 73c9b24b54..d736adc0bc 100644 --- a/test/plausible/installation_support/checks/url_test.exs +++ b/test/plausible/installation_support/checks/url_test.exs @@ -3,143 +3,151 @@ defmodule Plausible.InstallationSupport.Checks.UrlTest do Tests for URL check that is used in detection and verification checks pipelines to fail fast on non-existent domains. """ + use Plausible.DataCase, async: true - import Mox - alias Plausible.InstallationSupport.{State, Checks, Verification} + on_ee do + import Mox - @check Checks.Url + alias Plausible.InstallationSupport.{State, Checks, Verification} + + @check Checks.Url + + describe "when domain is set" do + for {site_domain, expected_lookup_domain} <- [ + {"plausible.io", ~c"plausible.io"}, + {"www.plausible.io", ~c"www.plausible.io"}, + {"plausible.io/sites", ~c"plausible.io"} + ] do + test "guesses 'https://#{site_domain}' if A-record is found for '#{site_domain}'" do + Plausible.DnsLookup.Mock + |> expect(:lookup, fn unquote(expected_lookup_domain), + _type, + _record, + _opts, + _timeout -> + [{192, 168, 1, 1}] + end) + + state = + @check.perform(%State{ + data_domain: unquote(site_domain), + url: nil, + diagnostics: %Verification.Diagnostics{} + }) + + assert state.url == "https://#{unquote(site_domain)}" + refute state.diagnostics.service_error + refute state.skip_further_checks? + end + end + + test "guesses 'www.{domain}' if A record is not found for 'domain'" do + site_domain = "example.com/any/deeper/path" - describe "when domain is set" do - for {site_domain, expected_lookup_domain} <- [ - {"plausible.io", ~c"plausible.io"}, - {"www.plausible.io", ~c"www.plausible.io"}, - {"plausible.io/sites", ~c"plausible.io"} - ] do - test "guesses 'https://#{site_domain}' if A-record is found for '#{site_domain}'" do Plausible.DnsLookup.Mock - |> expect(:lookup, fn unquote(expected_lookup_domain), _type, _record, _opts, _timeout -> + |> expect(:lookup, fn ~c"example.com", _type, _record, _opts, _timeout -> + [] + end) + |> expect(:lookup, fn ~c"www.example.com", _type, _record, _opts, _timeout -> + [{192, 168, 1, 2}] + end) + + state = + @check.perform(%State{ + data_domain: site_domain, + url: nil, + diagnostics: %Verification.Diagnostics{} + }) + + assert state.url == "https://www.example.com/any/deeper/path" + refute state.diagnostics.service_error + refute state.skip_further_checks? + end + + test "fails if no A-record is found for 'domain' or 'www.{domain}'" do + expected_lookups = 2 + + Plausible.DnsLookup.Mock + |> expect(:lookup, expected_lookups, fn _domain, _type, _record, _opts, _timeout -> + [] + end) + + domain = "any.example.com" + + state = + @check.perform(%State{ + data_domain: domain, + url: nil, + diagnostics: %Verification.Diagnostics{} + }) + + assert state.url == nil + assert state.diagnostics.service_error == :domain_not_found + assert state.skip_further_checks? + end + end + + describe "when url is set" do + test "for legitimate urls on domains that have an A-record, strips query and fragment" do + site_domain = "example-com-rollup" + url = "https://blog.example.com/recipes?foo=bar#baz" + + Plausible.DnsLookup.Mock + |> expect(:lookup, fn ~c"blog.example.com", _type, _record, _opts, _timeout -> [{192, 168, 1, 1}] end) state = @check.perform(%State{ - data_domain: unquote(site_domain), - url: nil, + data_domain: site_domain, + url: url, diagnostics: %Verification.Diagnostics{} }) - assert state.url == "https://#{unquote(site_domain)}" + assert state.url == "https://blog.example.com/recipes" refute state.diagnostics.service_error refute state.skip_further_checks? end + + test "rejects file:// scheme, does not check domain" do + state = + @check.perform(%State{ + data_domain: "example-com-rollup", + url: "file://example.com/archives/news?p=any#fragment", + diagnostics: %Verification.Diagnostics{} + }) + + assert state.url == "file://example.com/archives/news?p=any#fragment" + assert state.diagnostics.service_error == :invalid_url + assert state.skip_further_checks? + end + + test "rejects invalid urls" do + site_domain = "example-com-rollup" + url = "https://example.com/archives/news?p=any#fragment" + + Plausible.DnsLookup.Mock + |> expect(:lookup, fn ~c"example.com", _type, _record, _opts, _timeout -> + [] + end) + + state = + @check.perform(%State{ + data_domain: site_domain, + url: url, + diagnostics: %Verification.Diagnostics{} + }) + + assert state.url == url + assert state.diagnostics.service_error == :domain_not_found + assert state.skip_further_checks? + end end - test "guesses 'www.{domain}' if A record is not found for 'domain'" do - site_domain = "example.com/any/deeper/path" - - Plausible.DnsLookup.Mock - |> expect(:lookup, fn ~c"example.com", _type, _record, _opts, _timeout -> - [] - end) - |> expect(:lookup, fn ~c"www.example.com", _type, _record, _opts, _timeout -> - [{192, 168, 1, 2}] - end) - - state = - @check.perform(%State{ - data_domain: site_domain, - url: nil, - diagnostics: %Verification.Diagnostics{} - }) - - assert state.url == "https://www.example.com/any/deeper/path" - refute state.diagnostics.service_error - refute state.skip_further_checks? + test "reports progress correctly" do + assert @check.report_progress_as() == + "We're trying to reach your website" end - - test "fails if no A-record is found for 'domain' or 'www.{domain}'" do - expected_lookups = 2 - - Plausible.DnsLookup.Mock - |> expect(:lookup, expected_lookups, fn _domain, _type, _record, _opts, _timeout -> - [] - end) - - domain = "any.example.com" - - state = - @check.perform(%State{ - data_domain: domain, - url: nil, - diagnostics: %Verification.Diagnostics{} - }) - - assert state.url == nil - assert state.diagnostics.service_error == :domain_not_found - assert state.skip_further_checks? - end - end - - describe "when url is set" do - test "for legitimate urls on domains that have an A-record, strips query and fragment" do - site_domain = "example-com-rollup" - url = "https://blog.example.com/recipes?foo=bar#baz" - - Plausible.DnsLookup.Mock - |> expect(:lookup, fn ~c"blog.example.com", _type, _record, _opts, _timeout -> - [{192, 168, 1, 1}] - end) - - state = - @check.perform(%State{ - data_domain: site_domain, - url: url, - diagnostics: %Verification.Diagnostics{} - }) - - assert state.url == "https://blog.example.com/recipes" - refute state.diagnostics.service_error - refute state.skip_further_checks? - end - - test "rejects file:// scheme, does not check domain" do - state = - @check.perform(%State{ - data_domain: "example-com-rollup", - url: "file://example.com/archives/news?p=any#fragment", - diagnostics: %Verification.Diagnostics{} - }) - - assert state.url == "file://example.com/archives/news?p=any#fragment" - assert state.diagnostics.service_error == :invalid_url - assert state.skip_further_checks? - end - - test "rejects invalid urls" do - site_domain = "example-com-rollup" - url = "https://example.com/archives/news?p=any#fragment" - - Plausible.DnsLookup.Mock - |> expect(:lookup, fn ~c"example.com", _type, _record, _opts, _timeout -> - [] - end) - - state = - @check.perform(%State{ - data_domain: site_domain, - url: url, - diagnostics: %Verification.Diagnostics{} - }) - - assert state.url == url - assert state.diagnostics.service_error == :domain_not_found - assert state.skip_further_checks? - end - end - - test "reports progress correctly" do - assert @check.report_progress_as() == - "We're trying to reach your website" end end diff --git a/test/plausible_web/live/components/verification_test.exs b/test/plausible_web/live/components/verification_test.exs index 327c5076b8..857e3c278d 100644 --- a/test/plausible_web/live/components/verification_test.exs +++ b/test/plausible_web/live/components/verification_test.exs @@ -1,161 +1,164 @@ defmodule PlausibleWeb.Live.Components.VerificationTest do - use PlausibleWeb.ConnCase, async: true - import Phoenix.LiveViewTest, only: [render_component: 2] - import Plausible.Test.Support.HTML + use Plausible - alias Plausible.InstallationSupport.{State, LegacyVerification, Verification} + on_ee do + use PlausibleWeb.ConnCase, async: true + import Phoenix.LiveViewTest, only: [render_component: 2] + import Plausible.Test.Support.HTML - @component PlausibleWeb.Live.Components.Verification - @progress ~s|#verification-ui p#progress| + alias Plausible.InstallationSupport.{State, LegacyVerification, Verification} - @pulsating_circle ~s|div#verification-ui div.pulsating-circle| - @check_circle ~s|div#verification-ui #check-circle| - @error_circle ~s|div#verification-ui #error-circle| - @recommendations ~s|#recommendation| - @super_admin_report ~s|#super-admin-report| + @component PlausibleWeb.Live.Components.Verification + @progress ~s|#verification-ui p#progress| - test "renders initial state" do - html = render_component(@component, domain: "example.com") - assert element_exists?(html, @progress) + @pulsating_circle ~s|div#verification-ui div.pulsating-circle| + @check_circle ~s|div#verification-ui #check-circle| + @error_circle ~s|div#verification-ui #error-circle| + @recommendations ~s|#recommendation| + @super_admin_report ~s|#super-admin-report| - assert text_of_element(html, @progress) == - "We're visiting your site to ensure that everything is working" + test "renders initial state" do + html = render_component(@component, domain: "example.com") + assert element_exists?(html, @progress) - assert element_exists?(html, @pulsating_circle) - refute class_of_element(html, @pulsating_circle) =~ "hidden" - refute element_exists?(html, @recommendations) - refute element_exists?(html, @check_circle) - refute element_exists?(html, @super_admin_report) - end + assert text_of_element(html, @progress) == + "We're visiting your site to ensure that everything is working" - test "renders error badge on error" do - html = render_component(@component, domain: "example.com", success?: false, finished?: true) - refute element_exists?(html, @pulsating_circle) - refute element_exists?(html, @check_circle) - refute element_exists?(html, @recommendations) - assert element_exists?(html, @error_circle) - end + assert element_exists?(html, @pulsating_circle) + refute class_of_element(html, @pulsating_circle) =~ "hidden" + refute element_exists?(html, @recommendations) + refute element_exists?(html, @check_circle) + refute element_exists?(html, @super_admin_report) + end - test "renders diagnostic interpretation" do - interpretation = - LegacyVerification.Checks.interpret_diagnostics(%State{ + test "renders error badge on error" do + html = render_component(@component, domain: "example.com", success?: false, finished?: true) + refute element_exists?(html, @pulsating_circle) + refute element_exists?(html, @check_circle) + refute element_exists?(html, @recommendations) + assert element_exists?(html, @error_circle) + end + + test "renders diagnostic interpretation" do + interpretation = + LegacyVerification.Checks.interpret_diagnostics(%State{ + url: "example.com", + diagnostics: %LegacyVerification.Diagnostics{} + }) + + html = + render_component(@component, + domain: "example.com", + success?: false, + finished?: true, + interpretation: interpretation + ) + + recommendations = html |> find(@recommendations) |> Enum.map(&text/1) + + assert recommendations == [ + "If your site is running at a different location, please manually check your integration.  Learn more" + ] + + refute element_exists?(html, @super_admin_report) + end + + test "renders super-admin report" do + state = %State{ url: "example.com", diagnostics: %LegacyVerification.Diagnostics{} - }) + } - html = - render_component(@component, - domain: "example.com", - success?: false, - finished?: true, - interpretation: interpretation - ) + interpretation = + LegacyVerification.Checks.interpret_diagnostics(state) - recommendations = html |> find(@recommendations) |> Enum.map(&text/1) + html = + render_component(@component, + domain: "example.com", + success?: false, + finished?: true, + interpretation: interpretation, + verification_state: state, + super_admin?: true + ) - assert recommendations == [ - "If your site is running at a different location, please manually check your integration.  Learn more" - ] + assert element_exists?(html, @super_admin_report) + assert text_of_element(html, @super_admin_report) =~ "Snippets found in body: 0" + end - refute element_exists?(html, @super_admin_report) - end + test "hides pulsating circle when finished, shows check circle" do + html = + render_component(@component, + domain: "example.com", + success?: true, + finished?: true + ) - test "renders super-admin report" do - state = %State{ - url: "example.com", - diagnostics: %LegacyVerification.Diagnostics{} - } + refute element_exists?(html, @pulsating_circle) + assert element_exists?(html, @check_circle) + end - interpretation = - LegacyVerification.Checks.interpret_diagnostics(state) + test "renders a progress message" do + html = render_component(@component, domain: "example.com", message: "Arbitrary message") - html = - render_component(@component, - domain: "example.com", - success?: false, - finished?: true, - interpretation: interpretation, - verification_state: state, - super_admin?: true - ) + assert text_of_element(html, @progress) == "Arbitrary message" + end - assert element_exists?(html, @super_admin_report) - assert text_of_element(html, @super_admin_report) =~ "Snippets found in body: 0" - end + test "renders contact link on >3 attempts" do + html = render_component(@component, domain: "example.com", attempts: 2, finished?: true) + refute html =~ "Need further help with your installation?" + refute element_exists?(html, ~s|a[href="https://plausible.io/contact"]|) - test "hides pulsating circle when finished, shows check circle" do - html = - render_component(@component, - domain: "example.com", - success?: true, - finished?: true - ) + html = render_component(@component, domain: "example.com", attempts: 3, finished?: true) + assert html =~ "Need further help with your installation?" + assert element_exists?(html, ~s|a[href="https://plausible.io/contact"]|) + end - refute element_exists?(html, @pulsating_circle) - assert element_exists?(html, @check_circle) - end + test "renders link to verify installation at a different URL" do + interpretation = + Verification.Checks.interpret_diagnostics(%State{ + url: "example.com", + diagnostics: %Verification.Diagnostics{ + plausible_is_on_window: false, + plausible_is_initialized: false, + service_error: :domain_not_found + } + }) - test "renders a progress message" do - html = render_component(@component, domain: "example.com", message: "Arbitrary message") + assert interpretation.data.offer_custom_url_input == true - assert text_of_element(html, @progress) == "Arbitrary message" - end + expected_link_href = + PlausibleWeb.Router.Helpers.site_path(PlausibleWeb.Endpoint, :verification, "example.com") - @tag :ee_only - test "renders contact link on >3 attempts" do - html = render_component(@component, domain: "example.com", attempts: 2, finished?: true) - refute html =~ "Need further help with your installation?" - refute element_exists?(html, ~s|a[href="https://plausible.io/contact"]|) + html = + render_component(@component, + domain: "example.com", + finished?: true, + success?: false, + interpretation: interpretation + ) - html = render_component(@component, domain: "example.com", attempts: 3, finished?: true) - assert html =~ "Need further help with your installation?" - assert element_exists?(html, ~s|a[href="https://plausible.io/contact"]|) - end + assert text_of_element(html, "#verify-custom-url-link") =~ "different URL?" + assert text_of_attr(html, "#verify-custom-url-link a", "href") =~ expected_link_href + assert text_of_attr(html, "#verify-custom-url-link a", "href") =~ "custom_url=true" + end - test "renders link to verify installation at a different URL" do - interpretation = - Verification.Checks.interpret_diagnostics(%State{ - url: "example.com", - diagnostics: %Verification.Diagnostics{ - plausible_is_on_window: false, - plausible_is_initialized: false, - service_error: :domain_not_found - } - }) + test "offers escape paths: settings and installation instructions on failure" do + html = + render_component(@component, + domain: "example.com", + success?: false, + finished?: true, + installation_type: "wordpress", + flow: PlausibleWeb.Flows.review() + ) - assert interpretation.data.offer_custom_url_input == true + assert element_exists?(html, ~s|a[href="/example.com/settings/general"]|) - expected_link_href = - PlausibleWeb.Router.Helpers.site_path(PlausibleWeb.Endpoint, :verification, "example.com") - - html = - render_component(@component, - domain: "example.com", - finished?: true, - success?: false, - interpretation: interpretation - ) - - assert text_of_element(html, "#verify-custom-url-link") =~ "different URL?" - assert text_of_attr(html, "#verify-custom-url-link a", "href") =~ expected_link_href - assert text_of_attr(html, "#verify-custom-url-link a", "href") =~ "custom_url=true" - end - - test "offers escape paths: settings and installation instructions on failure" do - html = - render_component(@component, - domain: "example.com", - success?: false, - finished?: true, - installation_type: "wordpress", - flow: PlausibleWeb.Flows.review() - ) - - assert element_exists?(html, ~s|a[href="/example.com/settings/general"]|) - - assert element_exists?( - html, - ~s|a[href="/example.com/installation?flow=review&installation_type=wordpress"]| - ) + assert element_exists?( + html, + ~s|a[href="/example.com/installation?flow=review&installation_type=wordpress"]| + ) + end end end diff --git a/test/plausible_web/live/installation_test.exs b/test/plausible_web/live/installation_test.exs index 4bdfa0f3ea..727f82d881 100644 --- a/test/plausible_web/live/installation_test.exs +++ b/test/plausible_web/live/installation_test.exs @@ -130,42 +130,44 @@ defmodule PlausibleWeb.Live.InstallationTest do end describe "LiveView" do - test "mounts and detects installation type", %{conn: conn, site: site} do - stub_fetch_body(200, "wp-content") + on_ee do + test "mounts and detects installation type", %{conn: conn, site: site} do + stub_fetch_body(200, "wp-content") - {lv, _} = get_lv(conn, site) + {lv, _} = get_lv(conn, site, nil) - assert eventually(fn -> - html = render(lv) + assert eventually(fn -> + html = render(lv) - { - text(html) =~ "Install WordPress", - html - } - end) + { + text(html) =~ "Install WordPress", + html + } + end) - _ = render(lv) - end + _ = render(lv) + end - @tag :slow - test "mounts and does not detect installation type, if it's provided", %{ - conn: conn, - site: site - } do - stub_fetch_body(200, "wp-content") + @tag :slow + test "mounts and does not detect installation type, if it's provided", %{ + conn: conn, + site: site + } do + stub_fetch_body(200, "wp-content") - {lv, _} = get_lv(conn, site, "?installation_type=gtm") + {lv, _} = get_lv(conn, site, "?installation_type=gtm") - refute eventually(fn -> - html = render(lv) + refute eventually(fn -> + html = render(lv) - { - text(html) =~ "Install WordPress", - html - } - end) + { + text(html) =~ "Install WordPress", + html + } + end) - _ = render(lv) + _ = render(lv) + end end test "allows manual snippet customization", %{conn: conn, site: site} do @@ -354,19 +356,21 @@ defmodule PlausibleWeb.Live.InstallationTest do end end - defp stub_fetch_body(f) when is_function(f, 1) do - Req.Test.stub(Plausible.InstallationSupport.Checks.FetchBody, f) + on_ee do + defp stub_fetch_body(f) when is_function(f, 1) do + Req.Test.stub(Plausible.InstallationSupport.Checks.FetchBody, f) + end + + defp stub_fetch_body(status, body) do + stub_fetch_body(fn conn -> + conn + |> put_resp_content_type("text/html") + |> send_resp(status, body) + end) + end end - defp stub_fetch_body(status, body) do - stub_fetch_body(fn conn -> - conn - |> put_resp_content_type("text/html") - |> send_resp(status, body) - end) - end - - defp get_lv(conn, site, qs \\ nil) do + defp get_lv(conn, site, qs) do {:ok, lv, html} = live(conn, "/#{site.domain}/installation#{qs}") {lv, html}