berrypod/test/berrypod_web/live/admin/analytics_test.exs
jamey 0b0adba0fe
All checks were successful
deploy / deploy (push) Successful in 1m23s
add no-JS progressive enhancement for all shop flows
Every key shop flow now works via plain HTML forms when JS is
unavailable. LiveView progressively enhances when JS connects.

- PDP: form wraps variant/qty/add-to-cart with action="/cart/add"
- Cart page: qty +/- and remove use form POST fallbacks
- Cart/search header icons are now links with phx-click enhancement
- Collection sort form has GET action + noscript submit button
- New /search page with form-based search for no-JS users
- CartController gains add/remove/update_item POST actions
- CartHook gains update_quantity_form and remove_item_form handlers
- Fix flaky analytics tests caused by event table pollution

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 22:56:19 +00:00

166 lines
5.0 KiB
Elixir

defmodule BerrypodWeb.Admin.AnalyticsTest do
use BerrypodWeb.ConnCase, async: false
import Phoenix.LiveViewTest
import Berrypod.AccountsFixtures
alias Berrypod.Analytics.{Buffer, Event}
alias Berrypod.Repo
setup do
send(Buffer, :flush)
:timer.sleep(50)
Repo.delete_all(Event)
user = user_fixture()
%{user: user}
end
describe "unauthenticated" do
test "redirects to login", %{conn: conn} do
{:error, redirect} = live(conn, ~p"/admin/analytics")
assert {:redirect, %{to: path}} = redirect
assert path == ~p"/users/log-in"
end
end
describe "analytics dashboard" do
setup %{conn: conn, user: user} do
%{conn: log_in_user(conn, user)}
end
test "renders the analytics page", %{conn: conn} do
{:ok, _view, html} = live(conn, ~p"/admin/analytics")
assert html =~ "Analytics"
assert html =~ "Unique visitors"
assert html =~ "Total pageviews"
assert html =~ "Bounce rate"
assert html =~ "Visit duration"
end
test "shows zero state with no data", %{conn: conn} do
{:ok, _view, html} = live(conn, ~p"/admin/analytics")
assert html =~ "No data for this period"
end
test "shows data when events exist", %{conn: conn} do
now = DateTime.utc_now() |> DateTime.truncate(:second)
Repo.insert_all(Event, [
[
id: Ecto.UUID.generate(),
name: "pageview",
pathname: "/",
visitor_hash: :crypto.strong_rand_bytes(8),
session_hash: :crypto.strong_rand_bytes(8),
browser: "Chrome",
os: "macOS",
inserted_at: now
]
])
{:ok, view, _html} = live(conn, ~p"/admin/analytics")
assert has_element?(view, "[data-bars]")
end
test "changes period", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/admin/analytics")
html = render_click(view, "change_period", %{"period" => "7d"})
assert html =~ "Analytics"
end
test "changes tab to sources", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/admin/analytics")
html = render_click(view, "change_tab", %{"tab" => "sources"})
assert html =~ "Top sources"
assert html =~ "Top referrers"
end
test "changes tab to countries", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/admin/analytics")
html = render_click(view, "change_tab", %{"tab" => "countries"})
assert html =~ "Countries"
end
test "changes tab to devices", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/admin/analytics")
html = render_click(view, "change_tab", %{"tab" => "devices"})
assert html =~ "Browsers"
assert html =~ "Operating systems"
assert html =~ "Screen sizes"
end
test "changes tab to funnel", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/admin/analytics")
html = render_click(view, "change_tab", %{"tab" => "funnel"})
assert html =~ "Conversion funnel"
end
test "clicking a source adds a filter chip", %{conn: conn} do
now = DateTime.utc_now() |> DateTime.truncate(:second)
Repo.insert_all(Event, [
[
id: Ecto.UUID.generate(),
name: "pageview",
pathname: "/",
visitor_hash: :crypto.strong_rand_bytes(8),
session_hash: :crypto.strong_rand_bytes(8),
referrer_source: "Google",
inserted_at: now
]
])
{:ok, view, _html} = live(conn, ~p"/admin/analytics")
# Switch to sources tab and click the source
render_click(view, "change_tab", %{"tab" => "sources"})
html =
render_click(view, "add_filter", %{"dimension" => "referrer_source", "value" => "Google"})
assert html =~ "Source: Google"
assert has_element?(view, "#analytics-filters")
end
test "removing a filter chip clears it", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/admin/analytics")
render_click(view, "add_filter", %{"dimension" => "country_code", "value" => "GB"})
assert render(view) =~ "Country: United Kingdom"
html = render_click(view, "remove_filter", %{"dimension" => "country_code"})
refute html =~ "Country: United Kingdom"
end
test "clear all removes all filters", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/admin/analytics")
render_click(view, "add_filter", %{"dimension" => "country_code", "value" => "GB"})
render_click(view, "add_filter", %{"dimension" => "browser", "value" => "Chrome"})
assert render(view) =~ "Clear all"
html = render_click(view, "clear_filters", %{})
refute html =~ "Country: United Kingdom"
refute html =~ "Browser: Chrome"
end
test "changing period preserves filters", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/admin/analytics")
render_click(view, "add_filter", %{"dimension" => "country_code", "value" => "GB"})
html = render_click(view, "change_period", %{"period" => "7d"})
assert html =~ "Country: United Kingdom"
end
end
end