Files
MathApp/accounts/tests_birth_date.py
Zareian 663252a260 Remove the guest system entirely: no is_guest/device_id, no guest throttles, phone login is the only way in
accounts.0008 drops the columns and refuses to run while guest rows exist.
Docs describe the current state; tests that only proved guest behaviour are gone.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 18:20:10 +03:30

105 lines
4.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
تاریخِ تولدِ شمسی در پروفایل (۲۰۲۶-۱۰-۰۱). اپ روز/ماه/سالِ شمسی می‌فرستد؛ سرور
میلادی ذخیره می‌کند و birthYear را از آن می‌سازد. راه‌های شکستن: تاریخِ ناموجود
(۳۰ اسفندِ غیرکبیسه)، ارقامِ فارسی، سنِ خارج از بازه، و جدا افتادنِ سال از تاریخ.
"""
from datetime import date
from django.core.cache import cache
from django.test import SimpleTestCase, TestCase
from rest_framework.test import APIClient
from accounts import jalali
from accounts.authentication import issue_access_token
from accounts.models import Profile, User
class JalaliConversionTests(SimpleTestCase):
KNOWN = [
((1405, 1, 1), date(2026, 3, 21)),
((1403, 12, 30), date(2025, 3, 20)), # اسفندِ کبیسه
((1404, 12, 29), date(2026, 3, 20)), # آخرین روزِ سالِ غیرکبیسه
((1385, 4, 12), date(2006, 7, 3)),
((1367, 10, 11), date(1989, 1, 1)),
]
def test_known_dates_both_ways(self):
for jalali_date, gregorian in self.KNOWN:
self.assertEqual(jalali.to_gregorian(*jalali_date), gregorian)
self.assertEqual(jalali.from_gregorian(gregorian), jalali_date)
def test_thirtieth_of_esfand_exists_only_in_leap_years(self):
self.assertTrue(jalali.is_leap(1403))
self.assertFalse(jalali.is_leap(1404))
with self.assertRaises(ValueError):
jalali.to_gregorian(1404, 12, 30)
def test_every_day_of_a_century_round_trips(self):
start = date(1940, 1, 1).toordinal()
for offset in range(0, 36600, 7):
day = date.fromordinal(start + offset)
self.assertEqual(jalali.to_gregorian(*jalali.from_gregorian(day)), day)
def test_persian_digits_and_slashes_are_accepted(self):
self.assertEqual(jalali.parse('۱۳۸۵/۰۴/۱۲'), date(2006, 7, 3))
class ProfileBirthDateApiTests(TestCase):
def setUp(self):
cache.clear()
self.user = User.objects.create(phone='09000000053')
self.client = APIClient()
self.client.credentials(HTTP_AUTHORIZATION=f'Bearer {issue_access_token(self.user.id)}')
def patch(self, body):
return self.client.patch('/api/user/profile', body, format='json')
def test_date_is_stored_and_returned_in_jalali_with_its_year(self):
response = self.patch({'birthDate': '1385-04-12'})
self.assertEqual(response.status_code, 200, response.content)
self.assertEqual(response.json()['birthDate'], '1385-04-12')
self.assertEqual(response.json()['birthYear'], 1385)
self.assertEqual(Profile.objects.get(user=self.user).birth_date, date(2006, 7, 3))
self.assertEqual(self.client.get('/api/user/profile').json()['birthDate'], '1385-04-12')
def test_adults_are_accepted(self):
self.assertEqual(self.patch({'birthDate': '1360-01-15'}).status_code, 200)
def test_impossible_dates_are_rejected(self):
for bad in ('1404-12-30', '1385-13-01', '1385-07-31', '1385-4', 'دیروز'):
self.assertEqual(self.patch({'birthDate': bad}).status_code, 400, bad)
def test_future_and_too_young_or_old_are_rejected(self):
for bad in ('1410-01-01', '1403-01-01', '1300-01-01'):
self.assertEqual(self.patch({'birthDate': bad}).status_code, 400, bad)
def test_date_and_year_together_are_ambiguous(self):
self.assertEqual(self.patch({'birthDate': '1385-04-12', 'birthYear': 1390}).status_code, 400)
def test_a_different_year_alone_clears_the_old_date(self):
self.patch({'birthDate': '1385-04-12'})
data = self.patch({'birthYear': 1388}).json()
self.assertEqual((data['birthYear'], data['birthDate']), (1388, None))
def test_null_clears_the_date(self):
self.patch({'birthDate': '1385-04-12'})
data = self.patch({'birthDate': None}).json()
self.assertEqual((data['birthYear'], data['birthDate']), (None, None))
def test_parent_phone_is_gone(self):
self.assertNotIn('parentPhone', self.client.get('/api/user/profile').json())
class PublicIdTests(TestCase):
def test_profile_shows_a_six_digit_code_that_maps_back_to_the_user(self):
from accounts.public_id import decode
user = User.objects.create(phone='09000000054')
client = APIClient()
client.credentials(HTTP_AUTHORIZATION=f'Bearer {issue_access_token(user.id)}')
code = client.get('/api/user/profile').json()['publicId']
self.assertRegex(code, r'^User\d{6}$')
self.assertEqual(decode(code), user.id)
self.assertEqual(decode(code[4:]), user.id)
self.assertIsNone(decode('User12'))