Template
Closes #9. Shop-gated buyer accounts, purchase reviews, Stripe customer ids, shipment tracking, slim public contact form, and a template-neutral seed_demo command.
151 lines
5.9 KiB
Python
151 lines
5.9 KiB
Python
import os
|
|
from io import StringIO
|
|
from unittest.mock import patch
|
|
|
|
from django.core.management import call_command
|
|
from django.test import Client, TestCase, override_settings
|
|
from django.urls import reverse
|
|
|
|
|
|
class HealthzTests(TestCase):
|
|
def test_healthz_ok(self):
|
|
response = Client().get("/healthz/")
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertEqual(response.json()["status"], "ok")
|
|
|
|
|
|
class UnderConstructionTests(TestCase):
|
|
@override_settings(SITE_UNDER_CONSTRUCTION=True)
|
|
def test_home_redirects_when_gated(self):
|
|
response = Client().get("/")
|
|
self.assertEqual(response.status_code, 302)
|
|
self.assertIn("/under-construction", response["Location"])
|
|
|
|
@override_settings(SITE_UNDER_CONSTRUCTION=False)
|
|
def test_home_ok_when_open(self):
|
|
response = Client().get("/")
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
|
|
class PublicSmokeTests(TestCase):
|
|
def test_about_and_contact_get(self):
|
|
client = Client()
|
|
self.assertEqual(client.get(reverse("public:about")).status_code, 200)
|
|
self.assertEqual(client.get(reverse("public:contact")).status_code, 200)
|
|
contact = client.get(reverse("public:contact"))
|
|
self.assertContains(contact, "contact-email")
|
|
self.assertNotContains(contact, "contact-first-name")
|
|
self.assertNotContains(contact, "contact-phone")
|
|
self.assertNotContains(contact, "contact-address-line1")
|
|
|
|
|
|
class DispatchDueTests(TestCase):
|
|
def test_quiet_when_nothing_due(self):
|
|
out = StringIO()
|
|
call_command("dispatch_due", stdout=out)
|
|
self.assertEqual(out.getvalue(), "")
|
|
|
|
|
|
class SeedDemoTests(TestCase):
|
|
def test_refuses_prod(self):
|
|
from django.core.management.base import CommandError
|
|
|
|
with patch.dict(os.environ, {"DJANGO_ENV": "prod"}):
|
|
with self.assertRaises(CommandError) as ctx:
|
|
call_command("seed_demo", stdout=StringIO())
|
|
self.assertIn("prod", str(ctx.exception).lower())
|
|
|
|
def test_seeds_shop_and_portal_rows(self):
|
|
out = StringIO()
|
|
call_command("seed_demo", stdout=out)
|
|
self.assertIn("Demo seed ready", out.getvalue())
|
|
from contacts.models import Contact
|
|
from leads.models import Lead
|
|
from shop.models import Order, Product
|
|
|
|
self.assertTrue(Product.objects.filter(sku="DEMO-NOTEBOOK").exists())
|
|
self.assertTrue(Product.objects.filter(sku="DEMO-PROTO", is_published=False).exists())
|
|
self.assertGreaterEqual(Contact.objects.filter(email__startswith="demo+").count(), 8)
|
|
self.assertTrue(Lead.objects.filter(message__startswith="[demo-seed]").exists())
|
|
self.assertTrue(Order.objects.filter(number="DEMO-ORD-001", status="paid").exists())
|
|
listing = Client().get(reverse("shop:list"))
|
|
self.assertContains(listing, "Notebook")
|
|
|
|
from django.contrib.auth import get_user_model
|
|
from shop.models import ProductReview
|
|
from shipping.models import Shipment
|
|
|
|
User = get_user_model()
|
|
jordan = User.objects.get(username="demo+jordan@example.com")
|
|
self.assertFalse(jordan.is_staff)
|
|
self.assertTrue(jordan.check_password("Demo-buyer-pass-123"))
|
|
self.assertEqual(
|
|
Order.objects.get(number="DEMO-ORD-001").user_id, jordan.pk
|
|
)
|
|
self.assertIsNone(Order.objects.get(number="DEMO-ORD-004").user_id)
|
|
self.assertTrue(
|
|
ProductReview.objects.filter(
|
|
user=jordan, product__sku="DEMO-NOTEBOOK", rating=5
|
|
).exists()
|
|
)
|
|
delivered = Shipment.objects.get(order__number="DEMO-ORD-002")
|
|
self.assertEqual(delivered.tracking_status, "delivered")
|
|
self.assertGreaterEqual(len(delivered.tracking_events), 2)
|
|
transit = Shipment.objects.get(order__number="DEMO-ORD-001")
|
|
self.assertEqual(transit.tracking_status, "in_transit")
|
|
|
|
client = Client()
|
|
self.assertTrue(
|
|
client.login(
|
|
username="demo+jordan@example.com", password="Demo-buyer-pass-123"
|
|
)
|
|
)
|
|
history = client.get(reverse("account:orders"))
|
|
self.assertContains(history, "DEMO-ORD-001")
|
|
self.assertNotContains(history, "DEMO-ORD-004")
|
|
detail = client.get(reverse("shop:detail", kwargs={"slug": "demo-notebook"}))
|
|
self.assertContains(detail, "Solid notebook")
|
|
|
|
def test_second_run_is_idempotent(self):
|
|
call_command("seed_demo", stdout=StringIO())
|
|
from shop.models import Product
|
|
|
|
count = Product.objects.filter(sku__startswith="DEMO-").count()
|
|
call_command("seed_demo", stdout=StringIO())
|
|
self.assertEqual(Product.objects.filter(sku__startswith="DEMO-").count(), count)
|
|
|
|
def test_reset_rebuilds_tagged_rows(self):
|
|
call_command("seed_demo", stdout=StringIO())
|
|
from shop.models import Product
|
|
|
|
Product.objects.filter(sku="DEMO-NOTEBOOK").delete()
|
|
call_command("seed_demo", reset=True, stdout=StringIO())
|
|
self.assertTrue(Product.objects.filter(sku="DEMO-NOTEBOOK").exists())
|
|
from django.contrib.auth import get_user_model
|
|
|
|
self.assertTrue(
|
|
get_user_model().objects.filter(username="demo+jordan@example.com").exists()
|
|
)
|
|
|
|
@patch.dict(os.environ, {"DJANGO_ENV": "beta"})
|
|
def test_allows_beta(self):
|
|
call_command("seed_demo", stdout=StringIO())
|
|
from shop.models import Product
|
|
|
|
self.assertTrue(Product.objects.filter(sku__startswith="DEMO-").exists())
|
|
|
|
def test_succeeds_when_shop_not_installed(self):
|
|
from django.apps import apps
|
|
from contacts.models import Contact
|
|
|
|
real = apps.is_installed
|
|
|
|
def fake(name):
|
|
if name in {"shop", "shipping"}:
|
|
return False
|
|
return real(name)
|
|
|
|
with patch("django.apps.apps.is_installed", side_effect=fake):
|
|
call_command("seed_demo", stdout=StringIO())
|
|
self.assertTrue(Contact.objects.filter(email__startswith="demo+").exists())
|