defmodule PlausibleWeb.EmailTest do alias PlausibleWeb.Email use ExUnit.Case, async: true import Plausible.Factory describe "base_email layout" do test "greets user by first name if user in template assigns" do email = Email.base_email() |> Email.render("welcome_email.html", %{ user: build(:user, name: "John Doe"), code: "123" }) assert email.html_body =~ "Hey John," end test "greets impersonally when user not in template assigns" do email = Email.base_email() |> Email.render("welcome_email.html") assert email.html_body =~ "Hey," end test "renders plausible link" do email = Email.base_email() |> Email.render("welcome_email.html") assert email.html_body =~ plausible_link() end @tag :ee_only test "renders unsubscribe placeholder" do email = Email.base_email() |> Email.render("welcome_email.html") assert email.html_body =~ "{{{ pm:unsubscribe }}}" end test "can be disabled with a nil layout" do email = Email.base_email(%{layout: nil}) |> Email.render("welcome_email.html", %{ user: build(:user, name: "John Doe") }) refute email.html_body =~ "Hey John," refute email.html_body =~ plausible_link() end end describe "priority email layout" do test "uses the `priority` message stream in Postmark" do email = Email.priority_email() |> Email.render("activation_email.html", %{ user: build(:user, name: "John Doe"), code: "123" }) assert %{"MessageStream" => "priority"} = email.private[:message_params] end test "greets user by first name if user in template assigns" do email = Email.priority_email() |> Email.render("activation_email.html", %{ user: build(:user, name: "John Doe"), code: "123" }) assert email.html_body =~ "Hey John," end test "greets impersonally when user not in template assigns" do email = Email.priority_email() |> Email.render("password_reset_email.html", %{ reset_link: "imaginary" }) assert email.html_body =~ "Hey," end test "renders plausible link" do email = Email.priority_email() |> Email.render("password_reset_email.html", %{ reset_link: "imaginary" }) assert email.html_body =~ plausible_link() end test "does not render unsubscribe placeholder" do email = Email.priority_email() |> Email.render("password_reset_email.html", %{ reset_link: "imaginary" }) refute email.html_body =~ "{{{ pm:unsubscribe }}}" end test "can be disabled with a nil layout" do email = Email.priority_email(%{layout: nil}) |> Email.render("password_reset_email.html", %{ reset_link: "imaginary" }) refute email.html_body =~ "Hey John," refute email.html_body =~ plausible_link() end end describe "over_limit_email/3" do test "renders usage, suggested plan, and links to upgrade and account settings" do user = build(:user) penultimate_cycle = Date.range(~D[2023-03-01], ~D[2023-03-31]) last_cycle = Date.range(~D[2023-04-01], ~D[2023-04-30]) suggested_plan = %Plausible.Billing.Plan{volume: "100k"} usage = %{ penultimate_cycle: %{date_range: penultimate_cycle, total: 12_300}, last_cycle: %{date_range: last_cycle, total: 32_100} } %{html_body: html_body, subject: subject} = PlausibleWeb.Email.over_limit_email(user, usage, suggested_plan) assert subject == "[Action required] You have outgrown your Plausible subscription tier" assert html_body =~ PlausibleWeb.TextHelpers.format_date_range(last_cycle) assert html_body =~ "We recommend you upgrade to the 100k/mo plan" assert html_body =~ "your account recorded 32,100 billable pageviews" assert html_body =~ "cycle before that (#{PlausibleWeb.TextHelpers.format_date_range(penultimate_cycle)}), your account used 12,300 billable pageviews" assert html_body =~ "/billing/choose-plan\">Click here to upgrade your subscription" assert html_body =~ PlausibleWeb.Router.Helpers.billing_url(PlausibleWeb.Endpoint, :choose_plan) assert html_body =~ "/settings\">account settings" end test "asks enterprise level usage to contact us" do user = build(:user) penultimate_cycle = Date.range(~D[2023-03-01], ~D[2023-03-31]) last_cycle = Date.range(~D[2023-04-01], ~D[2023-04-30]) suggested_plan = :enterprise usage = %{ penultimate_cycle: %{date_range: penultimate_cycle, total: 12_300}, last_cycle: %{date_range: last_cycle, total: 32_100} } %{html_body: html_body} = PlausibleWeb.Email.over_limit_email(user, usage, suggested_plan) refute html_body =~ "Click here to upgrade your subscription" assert html_body =~ "Your usage exceeds our standard plans, so please reply back" end end describe "dashboard_locked/3" do test "renders usage, suggested plan, and links to upgrade and account settings" do user = build(:user) penultimate_cycle = Date.range(~D[2023-03-01], ~D[2023-03-31]) last_cycle = Date.range(~D[2023-04-01], ~D[2023-04-30]) suggested_plan = %Plausible.Billing.Plan{volume: "100k"} usage = %{ penultimate_cycle: %{date_range: penultimate_cycle, total: 12_300}, last_cycle: %{date_range: last_cycle, total: 32_100} } %{html_body: html_body, subject: subject} = PlausibleWeb.Email.dashboard_locked(user, usage, suggested_plan) assert subject == "[Action required] Your Plausible dashboard is now locked" assert html_body =~ PlausibleWeb.TextHelpers.format_date_range(last_cycle) assert html_body =~ "We recommend you upgrade to the 100k/mo plan" assert html_body =~ "your account recorded 32,100 billable pageviews" assert html_body =~ "cycle before that (#{PlausibleWeb.TextHelpers.format_date_range(penultimate_cycle)}), the usage was 12,300 billable pageviews" assert html_body =~ "/billing/choose-plan\">Click here to upgrade your subscription" assert html_body =~ PlausibleWeb.Router.Helpers.billing_url(PlausibleWeb.Endpoint, :choose_plan) assert html_body =~ "/settings\">account settings" end test "asks enterprise level usage to contact us" do user = build(:user) penultimate_cycle = Date.range(~D[2023-03-01], ~D[2023-03-31]) last_cycle = Date.range(~D[2023-04-01], ~D[2023-04-30]) suggested_plan = :enterprise usage = %{ penultimate_cycle: %{date_range: penultimate_cycle, total: 12_300}, last_cycle: %{date_range: last_cycle, total: 32_100} } %{html_body: html_body} = PlausibleWeb.Email.dashboard_locked(user, usage, suggested_plan) refute html_body =~ "Click here to upgrade your subscription" assert html_body =~ "Your usage exceeds our standard plans, so please reply back" end end describe "enterprise_over_limit_internal_email/4" do test "renders pageview usage by billing cycles + sites usage/limit" do user = build(:user) penultimate_cycle = Date.range(~D[2023-03-01], ~D[2023-03-31]) last_cycle = Date.range(~D[2023-04-01], ~D[2023-04-30]) pageview_usage = %{ penultimate_cycle: %{date_range: penultimate_cycle, total: 100_141_888}, last_cycle: %{date_range: last_cycle, total: 100_222_999} } %{html_body: html_body, subject: subject} = PlausibleWeb.Email.enterprise_over_limit_internal_email(user, pageview_usage, 80, 50) assert subject == "#{user.email} has outgrown their enterprise plan" assert html_body =~ "Last billing cycle: #{PlausibleWeb.TextHelpers.format_date_range(last_cycle)}" assert html_body =~ "Last cycle pageview usage: 100,222,999 billable pageviews" assert html_body =~ "Penultimate billing cycle: #{PlausibleWeb.TextHelpers.format_date_range(penultimate_cycle)}" assert html_body =~ "Penultimate cycle pageview usage: 100,141,888 billable pageviews" assert html_body =~ "Site usage: 80 / 50 allowed sites" end end describe "approaching accept_traffic_until" do test "renders first warning" do user = build(:user, name: "John Doe") %{html_body: body, subject: subject} = PlausibleWeb.Email.approaching_accept_traffic_until(user) assert subject == "We'll stop counting your stats" assert body =~ plausible_link() assert body =~ "Hey John," assert body =~ "We've noticed that you're still sending us stats so we're writing to inform you that we'll stop accepting stats from your sites next week." end test "renders final warning" do user = build(:user) %{html_body: body, subject: subject} = PlausibleWeb.Email.approaching_accept_traffic_until_tomorrow(user) assert subject == "A reminder that we'll stop counting your stats tomorrow" assert body =~ plausible_link() assert body =~ "We've noticed that you're still sending us stats so we're writing to inform you that we'll stop accepting stats from your sites tomorrow." end end def plausible_link() do plausible_url = PlausibleWeb.EmailView.plausible_url() "#{plausible_url}" end end