""" جزیره‌ها روی نقشه باید با بازی کردنِ درس‌ها واقعاً تمام شوند (۲۰۲۶-۰۹-۲۵). دو چیز با هم جلوی پیشرفت را گرفته بود: ۱. جزیره فقط وقتی تمام می‌شد که *همه‌ی* درس‌هایش تمام شده باشند، ولی ۵۸۵ درس هنوز سوال ندارند و اپ برایشان دکمه‌ی شروع ندارد — ۱۸۱ جزیره از ۲۶۹. ۲. فرانت با کلیک روی جزیره همیشه lessonIds[0] را باز می‌کرد، یعنی درسِ اول را بارها و بارها. """ from django.core.cache import cache from django.test import TestCase from rest_framework.test import APIClient from accounts.authentication import issue_access_token from accounts.models import User from .models import Choice, Grade, Lesson, Node, Question, Unit from .testing import record_answers class IslandProgressTests(TestCase): def setUp(self): cache.clear() grade = Grade.objects.create(title='پایه نهم', icon='g', color='#fff') unit = Unit.objects.create(grade=grade, title='فصل ۱', order=1) self.first = Node.objects.create(unit=unit, title='جزیره‌ی اول', order=1) self.second = Node.objects.create(unit=unit, title='جزیره‌ی دوم', order=2) self.a = self._lesson(self.first, 'الف', with_question=True) self.empty = self._lesson(self.first, 'بی‌سوال', with_question=False) self.b = self._lesson(self.first, 'ب', with_question=True) self._lesson(self.second, 'ج', with_question=True) self.user = User.objects.create(phone='09120000950', grade_id=grade.id) self.client = APIClient() self.client.credentials(HTTP_AUTHORIZATION=f'Bearer {issue_access_token(self.user.id)}') def tearDown(self): cache.clear() def _lesson(self, node, title, *, with_question): lesson = Lesson.objects.create(node=node, title=title, intro_text='x', mascot_animation='x') if with_question: self._question(lesson) return lesson def _question(self, lesson): question = Question.objects.create(lesson=lesson, type='multiple_choice', prompt='؟') Choice.objects.create(question=question, value='۱', is_correct=True) Choice.objects.create(question=question, value='۲', is_correct=False) def _nodes(self): units = self.client.get('/api/home').json()['units'] return {n['title']: n for n in units[0]['nodes']} def _complete(self, lesson): record_answers(self.user.id, lesson=lesson) # مثلِ اپ: اول جواب، بعد پایان response = self.client.post(f'/api/lessons/{lesson.id}/complete', {'correctCount': 1, 'totalQuestions': 1}, format='json') self.assertEqual(response.status_code, 200, response.content) def test_tapping_the_island_opens_the_next_unfinished_lesson(self): nodes = self._nodes() self.assertEqual(nodes['جزیره‌ی اول']['nextLessonId'], self.a.id) self.assertEqual(nodes['جزیره‌ی اول']['lessonIds'][0], self.a.id) self._complete(self.a) first = self._nodes()['جزیره‌ی اول'] # درسِ بی‌سوال رد می‌شود؛ lessonIds[0] همان است که فرانت باز می‌کند. self.assertEqual(first['nextLessonId'], self.b.id) self.assertEqual(first['lessonIds'][0], self.b.id) self.assertCountEqual(first['lessonIds'], [self.a.id, self.empty.id, self.b.id]) def test_a_lesson_without_questions_does_not_hold_the_island(self): self._complete(self.a) self._complete(self.b) nodes = self._nodes() self.assertEqual(nodes['جزیره‌ی اول']['status'], 'completed') self.assertEqual(nodes['جزیره‌ی دوم']['status'], 'unlocked') # همه‌ی درس‌ها تمام شده‌اند: برای مرور، درسِ اول. self.assertEqual(nodes['جزیره‌ی اول']['nextLessonId'], self.a.id) def test_progress_counts_only_lessons_that_can_be_played(self): self._complete(self.a) percent = self.client.get('/api/home').json()['stats']['progressPercent'] self.assertAlmostEqual(percent, 33.33, places=2) # ۱ از ۳ درسِ سوال‌دار def test_new_content_is_offered_but_progress_never_goes_backwards(self): self._complete(self.a) self._complete(self.b) self.assertEqual(self._nodes()['جزیره‌ی اول']['status'], 'completed') self._question(self.empty) # حالا این درس هم بازی‌شدنی است nodes = self._nodes() # نقشه‌ی کش‌شده باطل شد: درسِ تازه پیشنهاد می‌شود… self.assertEqual(nodes['جزیره‌ی اول']['nextLessonId'], self.empty.id) # …ولی جزیره‌ی تمام‌شده باز و جزیره‌ی بعدی قفل نمی‌شود. self.assertEqual(nodes['جزیره‌ی اول']['status'], 'completed') self.assertEqual(nodes['جزیره‌ی دوم']['status'], 'unlocked')