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>
105 lines
4.7 KiB
Python
105 lines
4.7 KiB
Python
"""
|
||
تاریخِ تولدِ شمسی در پروفایل (۲۰۲۶-۱۰-۰۱). اپ روز/ماه/سالِ شمسی میفرستد؛ سرور
|
||
میلادی ذخیره میکند و 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'))
|