"""C-06 签到幂等 + 学习聚合去重回归。""" from django.test import TestCase from rest_framework.test import APIClient from learn.models import Chapter, ChapterRead, Course from user.models import DailyCheckin, FUser class CheckinIdempotentTest(TestCase): def setUp(self): self.client = APIClient() self.u = FUser.objects.create_user(username='c06sa', password='x12345678') def test_double_checkin_second_400_no_double_points(self): self.client.force_authenticate(user=self.u) r1 = self.client.post('/user/wallet/checkin/') self.assertEqual(r1.status_code, 200) earned = r1.json()['data']['earned'] self.u.refresh_from_db() p1 = self.u.points self.assertGreaterEqual(p1, earned) r2 = self.client.post('/user/wallet/checkin/') self.assertEqual(r2.status_code, 400) self.u.refresh_from_db() self.assertEqual(self.u.points, p1) self.assertEqual(DailyCheckin.objects.filter(user=self.u).count(), 1) def test_checkin_status_reflects_signed(self): self.client.force_authenticate(user=self.u) self.client.post('/user/wallet/checkin/') r = self.client.get('/user/wallet/checkin/status/') self.assertEqual(r.status_code, 200) self.assertTrue(r.json()['data']['signed_today']) def test_anonymous_checkin_401(self): r = self.client.post('/user/wallet/checkin/') self.assertEqual(r.status_code, 401) class LearnersCountTest(TestCase): def setUp(self): self.client = APIClient() self.u1 = FUser.objects.create_user(username='c06la', password='x12345678') self.u2 = FUser.objects.create_user(username='c06lb', password='x12345678') self.course = Course.objects.create(title='C06聚合课', author=self.u1, status='published') self.ch1 = Chapter.objects.create(course=self.course, title='第一章') self.ch2 = Chapter.objects.create(course=self.course, title='第二章') def test_cross_read_dedup_two_users(self): ChapterRead.objects.create(user=self.u1, chapter=self.ch1, course=self.course) ChapterRead.objects.create(user=self.u1, chapter=self.ch2, course=self.course) ChapterRead.objects.create(user=self.u2, chapter=self.ch1, course=self.course) r = self.client.get('/learn/courses/') self.assertEqual(r.status_code, 200) items = {x['title']: x for x in r.json()['data']} self.assertEqual(items['C06聚合课']['students_count'], 2) def test_no_read_zero(self): r = self.client.get('/learn/courses/') self.assertEqual(r.status_code, 200) items = {x['title']: x for x in r.json()['data']} self.assertEqual(items['C06聚合课']['students_count'], 0) def test_detail_students_count_matches(self): ChapterRead.objects.create(user=self.u1, chapter=self.ch1, course=self.course) r = self.client.get(f'/learn/courses/{self.course.id}/') self.assertEqual(r.status_code, 200) self.assertEqual(r.json()['data']['students_count'], 1) class TotalMinutesTest(TestCase): def setUp(self): self.client = APIClient() self.u = FUser.objects.create_user(username='c06ma', password='x12345678') def test_sums_parsable_durations(self): course = Course.objects.create(title='C06时长课', author=self.u, status='published') Chapter.objects.create(course=course, title='C1', duration='30分钟') Chapter.objects.create(course=course, title='C2', duration='45分钟') r = self.client.get('/learn/courses/') self.assertEqual(r.status_code, 200) items = {x['title']: x for x in r.json()['data']} self.assertEqual(items['C06时长课']['total_minutes'], 75) def test_unparsable_returns_none(self): course = Course.objects.create(title='C06无时长课', author=self.u, status='published') Chapter.objects.create(course=course, title='C1', duration='') Chapter.objects.create(course=course, title='C2', duration='未知') r = self.client.get(f'/learn/courses/{course.id}/') self.assertEqual(r.status_code, 200) self.assertIsNone(r.json()['data']['total_minutes'])