|
import time
|
|
from datetime import datetime, timedelta, timezone
|
|
|
|
import requests
|
|
|
|
from tests.conftest import BASE_URL
|
|
from devplacepy.database import get_table, get_activity_calendar, get_streaks, get_activity_heatmap
|
|
from devplacepy.utils import generate_uid, check_milestone_badges
|
|
|
|
_counter = [0]
|
|
|
|
|
|
def _make_user():
|
|
_counter[0] += 1
|
|
uid = generate_uid()
|
|
name = f"stk{int(time.time() * 1000)}{_counter[0]}"
|
|
get_table("users").insert({
|
|
"uid": uid, "username": name, "email": f"{name}@t.dev",
|
|
"role": "Member", "is_active": True, "xp": 0, "level": 1,
|
|
"created_at": datetime.now(timezone.utc).isoformat(),
|
|
})
|
|
return uid
|
|
|
|
|
|
def _insert_post(user_uid, dt):
|
|
uid = generate_uid()
|
|
get_table("posts").insert({
|
|
"uid": uid, "user_uid": user_uid, "slug": f"{uid[:8]}-streak",
|
|
"title": None, "content": "streak activity", "topic": "random",
|
|
"project_uid": None, "image": None, "stars": 0,
|
|
"created_at": dt.isoformat(),
|
|
})
|
|
return uid
|
|
|
|
|
|
def _insert_comment(user_uid, post_uid, dt):
|
|
uid = generate_uid()
|
|
get_table("comments").insert({
|
|
"uid": uid, "target_type": "post", "target_uid": post_uid, "post_uid": post_uid,
|
|
"user_uid": user_uid, "content": "streak comment", "parent_uid": None,
|
|
"created_at": dt.isoformat(),
|
|
})
|
|
return uid
|
|
|
|
|
|
def test_consecutive_days_build_streak(app_server):
|
|
uid = _make_user()
|
|
today = datetime.now(timezone.utc)
|
|
for offset in (0, 1, 2):
|
|
_insert_post(uid, today - timedelta(days=offset))
|
|
streaks = get_streaks(uid)
|
|
assert streaks["current"] == 3
|
|
assert streaks["longest"] >= 3
|
|
|
|
|
|
def test_gap_resets_current_streak(app_server):
|
|
uid = _make_user()
|
|
today = datetime.now(timezone.utc)
|
|
_insert_post(uid, today)
|
|
_insert_post(uid, today - timedelta(days=3))
|
|
streaks = get_streaks(uid)
|
|
assert streaks["current"] == 1
|
|
|
|
|
|
def test_yesterday_only_counts_as_current(app_server):
|
|
uid = _make_user()
|
|
yesterday = datetime.now(timezone.utc) - timedelta(days=1)
|
|
_insert_post(uid, yesterday)
|
|
assert get_streaks(uid)["current"] == 1
|
|
|
|
|
|
def test_calendar_sums_across_sources(app_server):
|
|
uid = _make_user()
|
|
today = datetime.now(timezone.utc)
|
|
post_uid = _insert_post(uid, today)
|
|
_insert_comment(uid, post_uid, today)
|
|
calendar = get_activity_calendar(uid)
|
|
assert calendar.get(today.date().isoformat()) == 2
|
|
|
|
|
|
def test_heatmap_shape(app_server):
|
|
uid = _make_user()
|
|
weeks = get_activity_heatmap(uid)
|
|
assert 52 <= len(weeks) <= 54
|
|
assert all(len(week) <= 7 for week in weeks)
|
|
|
|
|
|
def test_seven_day_streak_awards_on_fire_badge(app_server):
|
|
uid = _make_user()
|
|
today = datetime.now(timezone.utc)
|
|
for offset in range(7):
|
|
_insert_post(uid, today - timedelta(days=offset))
|
|
check_milestone_badges(uid)
|
|
assert get_table("badges").count(user_uid=uid, badge_name="On Fire") == 1
|
|
|
|
|
|
def test_profile_renders_heatmap_and_streak(app_server):
|
|
_counter[0] += 1
|
|
name = f"stkp{int(time.time() * 1000)}{_counter[0]}"
|
|
s = requests.Session()
|
|
s.post(f"{BASE_URL}/auth/signup", data={
|
|
"username": name, "email": f"{name}@t.dev",
|
|
"password": "secret123", "confirm_password": "secret123",
|
|
}, allow_redirects=True)
|
|
s.post(f"{BASE_URL}/posts/create", data={
|
|
"content": "A post created today for the streak heatmap.",
|
|
"title": "Streak heatmap post", "topic": "devlog",
|
|
}, allow_redirects=True)
|
|
html = s.get(f"{BASE_URL}/profile/{name}").text
|
|
assert "heatmap-grid" in html
|
|
assert "1 day streak" in html
|