feat(C-02):工具热榜周榜+最近使用
新增ToolUsageRecord使用日志(tool+created_at索引);/tool/top/总榜按累计排序、周榜按近7天聚合(无日志回退总榜,兼容period旧参);/tool/recent/登录去重倒序;seed新增AI图片放大/代码运行两个工具。
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
"""C-02 工具热榜聚合用例:总榜/周榜窗口/匿名归因/recent 权限/兼容参数。"""
|
||||
from datetime import timedelta
|
||||
|
||||
from django.test import TestCase
|
||||
from django.utils import timezone
|
||||
from rest_framework.test import APIClient
|
||||
|
||||
from tool.models import Tool, ToolUsageRecord
|
||||
from user.models import FUser
|
||||
|
||||
|
||||
class ToolTopTest(TestCase):
|
||||
def setUp(self):
|
||||
self.client = APIClient()
|
||||
self.a = Tool.objects.create(name='A', url_path='/utility/a-tool', usage_count=10)
|
||||
self.b = Tool.objects.create(name='B', url_path='/utility/b-tool', usage_count=5)
|
||||
self.c = Tool.objects.create(name='C', url_path='/utility/c-tool', usage_count=1)
|
||||
self.u = FUser.objects.create_user(username='c02u', password='x12345678')
|
||||
|
||||
def test_total_rank_order(self):
|
||||
r = self.client.get('/tool/top/', {'range': 'all', 'limit': 3})
|
||||
self.assertEqual(r.status_code, 200)
|
||||
data = r.json()['data']
|
||||
self.assertEqual([x['id'] for x in data], [self.a.id, self.b.id, self.c.id])
|
||||
self.assertEqual([x['rank'] for x in data], [1, 2, 3])
|
||||
for x in data:
|
||||
self.assertIn('usage_count', x)
|
||||
self.assertIn('weekly_count', x)
|
||||
|
||||
def test_period_alias_total(self):
|
||||
r = self.client.get('/tool/top/', {'period': 'total', 'limit': 3})
|
||||
self.assertEqual(r.status_code, 200)
|
||||
self.assertEqual([x['rank'] for x in r.json()['data']], [1, 2, 3])
|
||||
|
||||
def test_weekly_window_aggregation(self):
|
||||
now = timezone.now()
|
||||
for _ in range(3):
|
||||
ToolUsageRecord.objects.create(tool=self.c, user=self.u)
|
||||
old = ToolUsageRecord.objects.create(tool=self.a, user=self.u)
|
||||
old.created_at = now - timedelta(days=8)
|
||||
old.save(update_fields=['created_at'])
|
||||
r = self.client.get('/tool/top/', {'range': 'week', 'limit': 3})
|
||||
self.assertEqual(r.status_code, 200)
|
||||
data = r.json()['data']
|
||||
# C 近7天3次应排第一
|
||||
self.assertEqual(data[0]['id'], self.c.id)
|
||||
self.assertEqual(data[0]['weekly_count'], 3)
|
||||
|
||||
def test_weekly_boundary_7days(self):
|
||||
now = timezone.now()
|
||||
edge = ToolUsageRecord.objects.create(tool=self.b)
|
||||
edge.created_at = now - timedelta(days=7) + timedelta(seconds=60)
|
||||
edge.save(update_fields=['created_at'])
|
||||
out = ToolUsageRecord.objects.create(tool=self.b)
|
||||
out.created_at = now - timedelta(days=7, seconds=60)
|
||||
out.save(update_fields=['created_at'])
|
||||
r = self.client.get('/tool/top/', {'range': 'week', 'limit': 10})
|
||||
data = {x['id']: x['weekly_count'] for x in r.json()['data']}
|
||||
self.assertEqual(data[self.b.id], 1)
|
||||
|
||||
def test_weekly_empty_fallback_to_total(self):
|
||||
r = self.client.get('/tool/top/', {'range': 'week', 'limit': 3})
|
||||
self.assertEqual(r.status_code, 200)
|
||||
self.assertEqual([x['id'] for x in r.json()['data']], [self.a.id, self.b.id, self.c.id])
|
||||
|
||||
def test_increment_writes_record_anonymous(self):
|
||||
r = self.client.post(f'/tool/usage/{self.a.id}/increment/')
|
||||
self.assertEqual(r.status_code, 200)
|
||||
self.assertEqual(ToolUsageRecord.objects.filter(tool=self.a).count(), 1)
|
||||
self.a.refresh_from_db()
|
||||
self.assertEqual(self.a.usage_count, 11)
|
||||
|
||||
def test_increment_writes_record_login(self):
|
||||
self.client.force_authenticate(user=self.u)
|
||||
r = self.client.post(f'/tool/usage/{self.b.id}/increment/')
|
||||
self.assertEqual(r.status_code, 200)
|
||||
rec = ToolUsageRecord.objects.filter(tool=self.b).order_by('-id').first()
|
||||
self.assertEqual(rec.user_id, self.u.id)
|
||||
|
||||
def test_recent_requires_login(self):
|
||||
r = self.client.get('/tool/recent/')
|
||||
self.assertIn(r.status_code, (401, 403))
|
||||
|
||||
def test_recent_dedup_order(self):
|
||||
ToolUsageRecord.objects.create(tool=self.a, user=self.u)
|
||||
ToolUsageRecord.objects.create(tool=self.b, user=self.u)
|
||||
ToolUsageRecord.objects.create(tool=self.a, user=self.u)
|
||||
self.client.force_authenticate(user=self.u)
|
||||
r = self.client.get('/tool/recent/', {'limit': 10})
|
||||
self.assertEqual(r.status_code, 200)
|
||||
ids = [x['id'] for x in r.json()['data']]
|
||||
self.assertEqual(ids, [self.a.id, self.b.id])
|
||||
Reference in New Issue
Block a user