defmodule BerrypodWeb.Plugs.AnalyticsTest do use BerrypodWeb.ConnCase, async: false import Ecto.Query alias Berrypod.Analytics.{Buffer, Event} alias Berrypod.Repo setup do send(Buffer, :flush) :timer.sleep(50) Repo.delete_all(Event) :ok end describe "analytics plug" do test "records a pageview on GET request", %{conn: conn} do conn |> put_req_header("user-agent", "Mozilla/5.0 Chrome/120.0") |> get(~p"/") send(Buffer, :flush) :timer.sleep(50) events = from(e in Event, where: e.pathname == "/" and e.name == "pageview") |> Repo.all() assert length(events) >= 1 event = hd(events) assert event.browser == "Chrome" end test "does not record on POST request", %{conn: conn} do count_before = Repo.aggregate(Event, :count) conn |> put_req_header("user-agent", "Mozilla/5.0 Chrome/120.0") |> post(~p"/checkout", %{}) send(Buffer, :flush) :timer.sleep(50) count_after = Repo.aggregate(Event, :count) # POST to /checkout shouldn't create a pageview event via the plug # (it may fail with a redirect, but the plug should have skipped) assert count_after == count_before end test "skips bots", %{conn: conn} do count_before = Repo.aggregate(Event, :count) conn |> put_req_header("user-agent", "Googlebot/2.1 (+http://www.google.com/bot.html)") |> get(~p"/") send(Buffer, :flush) :timer.sleep(50) count_after = Repo.aggregate(Event, :count) assert count_after == count_before end test "stores analytics data in session", %{conn: conn} do conn = conn |> put_req_header("user-agent", "Mozilla/5.0 Firefox/121.0") |> get(~p"/") assert get_session(conn, "analytics_visitor_hash") |> is_binary() assert get_session(conn, "analytics_browser") == "Firefox" end test "extracts referrer", %{conn: conn} do conn |> put_req_header("user-agent", "Mozilla/5.0 Chrome/120.0") |> put_req_header("referer", "https://www.google.com/search?q=test") |> get(~p"/") send(Buffer, :flush) :timer.sleep(50) event = from(e in Event, where: e.referrer == "google.com", order_by: [desc: e.inserted_at], limit: 1 ) |> Repo.one() assert event assert event.referrer_source == "Google" end test "extracts UTM params", %{conn: conn} do conn |> put_req_header("user-agent", "Mozilla/5.0 Chrome/120.0") |> get(~p"/?utm_source=newsletter&utm_medium=email&utm_campaign=spring") send(Buffer, :flush) :timer.sleep(50) event = from(e in Event, where: e.utm_source == "newsletter", order_by: [desc: e.inserted_at], limit: 1 ) |> Repo.one() assert event assert event.utm_medium == "email" assert event.utm_campaign == "spring" end end end