2026-09-15 11:45:03 +08:00
|
|
|
|
import pytest
|
2026-09-15 13:38:01 +08:00
|
|
|
|
from django.db import IntegrityError
|
2026-09-15 11:45:03 +08:00
|
|
|
|
from tracker.models import Site, Visitor, VisitSession, Event
|
|
|
|
|
|
|
|
|
|
|
|
pytestmark = pytest.mark.django_db
|
|
|
|
|
|
|
2026-09-18 10:38:20 +08:00
|
|
|
|
|
|
|
|
|
|
def _base_event_kwargs():
|
|
|
|
|
|
"""合法 Event 基线 kwargs(schema v2 测试用)"""
|
|
|
|
|
|
site = Site.objects.create(name="s", domains=["a.com"])
|
|
|
|
|
|
visitor = Visitor.objects.create(site=site, visitor_id="vid1")
|
|
|
|
|
|
session = VisitSession.objects.create(site=site, visitor=visitor, session_id="sid1",
|
|
|
|
|
|
started_at="2026-09-15T10:00:00Z", ended_at="2026-09-15T10:01:00Z")
|
|
|
|
|
|
return dict(site=site, visitor=visitor, session=session, event_id="e1",
|
|
|
|
|
|
event_name="page_stay", occurred_at="2026-09-15T10:00:30Z", path="/")
|
|
|
|
|
|
|
2026-09-15 11:45:03 +08:00
|
|
|
|
def test_create_site_generates_public_site_id():
|
|
|
|
|
|
site = Site.objects.create(name="官网", domains=["www.example.com"])
|
|
|
|
|
|
assert site.site_id.startswith("site_") and len(site.site_id) == 21
|
|
|
|
|
|
assert site.is_active is True
|
|
|
|
|
|
|
|
|
|
|
|
def test_visitor_first_touch_fields():
|
|
|
|
|
|
site = Site.objects.create(name="s", domains=["a.com"])
|
|
|
|
|
|
v = Visitor.objects.create(site=site, visitor_id="vid1",
|
|
|
|
|
|
first_referrer_domain="google.com", first_utm={"utm_source": "google"},
|
|
|
|
|
|
first_landing_path="/p", country="美国", device_type="PC")
|
|
|
|
|
|
assert v.visit_count == 0 and v.active_days == 0
|
|
|
|
|
|
|
|
|
|
|
|
def test_event_unique_site_event_id():
|
|
|
|
|
|
site = Site.objects.create(name="s", domains=["a.com"])
|
|
|
|
|
|
v = Visitor.objects.create(site=site, visitor_id="vid1")
|
2026-09-15 11:46:51 +08:00
|
|
|
|
s = VisitSession.objects.create(site=site, visitor=v, session_id="sid1",
|
|
|
|
|
|
started_at="2026-09-15T10:00:00Z", ended_at="2026-09-15T10:01:00Z")
|
2026-09-15 11:45:03 +08:00
|
|
|
|
Event.objects.create(site=site, visitor=v, session=s, event_id="e1",
|
|
|
|
|
|
event_name="page_view", occurred_at="2026-09-15T10:00:00Z", path="/")
|
2026-09-15 13:38:01 +08:00
|
|
|
|
with pytest.raises(IntegrityError):
|
2026-09-15 11:45:03 +08:00
|
|
|
|
Event.objects.create(site=site, visitor=v, session=s, event_id="e1",
|
|
|
|
|
|
event_name="page_view", occurred_at="2026-09-15T10:01:00Z", path="/")
|
2026-09-15 13:38:01 +08:00
|
|
|
|
|
|
|
|
|
|
def test_site_cascade_deletes_children():
|
|
|
|
|
|
site = Site.objects.create(name="s", domains=["a.com"])
|
|
|
|
|
|
v = Visitor.objects.create(site=site, visitor_id="v")
|
|
|
|
|
|
s = VisitSession.objects.create(site=site, visitor=v, session_id="s",
|
|
|
|
|
|
started_at="2026-09-15T10:00:00Z", ended_at="2026-09-15T10:01:00Z")
|
|
|
|
|
|
Event.objects.create(site=site, visitor=v, session=s, event_id="e",
|
|
|
|
|
|
event_name="page_view", occurred_at="2026-09-15T10:00:00Z", path="/")
|
|
|
|
|
|
site.delete()
|
|
|
|
|
|
assert Visitor.objects.count() == 0 and VisitSession.objects.count() == 0 and Event.objects.count() == 0
|
2026-09-18 10:38:20 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_event_has_phase_a_fields():
|
|
|
|
|
|
e = Event(**_base_event_kwargs(), page_id="p1", active_from_ms=0,
|
|
|
|
|
|
active_to_ms=15000, flush_reason="periodic",
|
|
|
|
|
|
time_quality="ok", sdk_version="0.2.0", schema_version=2)
|
|
|
|
|
|
e.full_clean()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_visit_session_resume_of_self_fk():
|
|
|
|
|
|
assert VisitSession._meta.get_field("resume_of").related_model is VisitSession
|