Files
web_django_template/site/analytics/tests.py
T
westfarn f3e34f5099 Add shopper accounts, reviews, tracking, and seed_demo (#10)
## Summary
- Closes #9. Port shop-gated buyer accounts (register/login/profile, password reset, order history), purchase-gated reviews, and Stripe customer ids. Cards stay on Stripe.
- Slim public contact form to email + interest + message. Shipping tracking status, scan events, paste-in numbers, and EasyPost webhook when FEATURE_SHIPPING is on.
- Add template-neutral `seed_demo` (generic SKUs, demo shoppers, guest orders, tracking stubs). Prod refused. `--reset` deletes tagged demo rows after invoices.

## Test plan
- [ ] `cd site && uv run python manage.py test` (173 tests passed locally)
- [ ] Shop on: `/account/register`, login, profile, password reset, claim guest orders by email
- [ ] Shop off: `/account/` URLs absent; Sign in / Account links hidden
- [ ] Checkout as logged-in buyer stores `Order.user` and Stripe customer id; product review only after paid purchase
- [ ] Shipping on: portal paste-in tracking + EasyPost webhook updates status; shipping off: orders still work without tracking UI
- [ ] `seed_demo` refused in prod; `--reset` rebuilds tagged catalog/shoppers without deleting staff invoices

Reviewed-on: #10
2026-09-21 13:29:36 -07:00

84 lines
3.0 KiB
Python

from datetime import timedelta
from django.contrib.auth import get_user_model
from django.test import Client, TestCase
from django.urls import reverse
from django.utils import timezone
from analytics.models import PageView, UTMVisit
class PublicPageViewTests(TestCase):
def setUp(self):
self.client = Client()
def test_home_records_page_view(self):
response = self.client.get("/")
self.assertEqual(response.status_code, 200)
self.assertEqual(PageView.objects.count(), 1)
self.assertEqual(PageView.objects.get().path, "/")
def test_about_records_page_view(self):
self.client.get(reverse("public:about"))
self.assertEqual(PageView.objects.filter(path="/about/").count(), 1)
def test_plain_visit_does_not_create_utm_visit(self):
self.client.get("/")
self.assertEqual(PageView.objects.count(), 1)
self.assertEqual(UTMVisit.objects.count(), 0)
def test_utm_hit_records_both(self):
self.client.get("/?utm_source=test&utm_campaign=demo")
self.assertEqual(PageView.objects.count(), 1)
self.assertEqual(UTMVisit.objects.count(), 1)
def test_healthz_not_recorded(self):
self.client.get("/healthz/")
self.assertEqual(PageView.objects.count(), 0)
def test_portal_and_admin_not_recorded(self):
self.client.get("/portal/")
self.client.get("/admin/")
self.assertEqual(PageView.objects.count(), 0)
def test_robots_and_sitemap_not_recorded(self):
self.client.get("/robots.txt")
self.client.get("/sitemap.xml")
self.assertEqual(PageView.objects.count(), 0)
def test_missing_page_not_recorded(self):
response = self.client.get("/not-a-real-page/")
self.assertEqual(response.status_code, 404)
self.assertEqual(PageView.objects.count(), 0)
def test_contact_post_not_recorded(self):
self.client.post(reverse("public:contact"), {})
self.assertEqual(PageView.objects.count(), 0)
class AnalyticsReportTests(TestCase):
def setUp(self):
self.client = Client()
user = get_user_model().objects.create_user(
username="monica", password="pass-word-1", is_staff=True)
self.client.force_login(user)
def test_views_card_uses_public_pageviews(self):
self.client.get("/")
self.client.get(reverse("public:about"))
self.client.get(reverse("public:about"))
stale = PageView.objects.create(path="/terms/")
PageView.objects.filter(pk=stale.pk).update(
created_at=timezone.now() - timedelta(days=31)
)
response = self.client.get(reverse("analytics:report"))
self.assertEqual(response.status_code, 200)
self.assertEqual(response.context["pageviews_last_30_days"], 3)
top = {row["path"]: row["count"] for row in response.context["top_pages"]}
self.assertEqual(top["/about/"], 2)
self.assertEqual(top["/"], 1)
self.assertNotIn("/terms/", top)
self.assertContains(response, "Top pages")
self.assertContains(response, "/about/")