Ë
    *^:ià3  ã                  ó²   — d Z ddlmZ ddlmZ ddlmZmZ ddlm	Z	 ddl
mZ ddlmZmZ  ed¬	«       G d
„ de«      «       Z G d„ de«      Z G d„ de«      Zy)z4Tests for Telegram authentication and webhook flows.é    )Úannotations)Úpatch)ÚTestCaseÚoverride_settings)Úreverse)ÚUser)ÚTelegramDataValidationErrorÚgenerate_signed_init_dataútest-bot-token)ÚTELEGRAM_BOT_TOKENc                  óÞ   — e Zd Zdd„Z ed«      d„ «       Zd„ Z ed«      d„ «       Z ed«      d„ «       Z ed«      d„ «       Z	 ed«      d„ «       Z
 ed«      d	„ «       Z ed«      d
„ «       Zy)ÚAuthenticateTelegramTestsc                ó¨   — | j                   j                  t        d«      |d¬«      }| j                  |j                  d«       |j                  «       S )Nútelegram-authúapplication/json©ÚdataÚcontent_typeéÈ   )ÚclientÚpostr   ÚassertEqualÚstatus_codeÚjson©ÚselfÚpayloadÚresponses      úT/home/cursorai/projects/telegram-earn/backend/apps/users/tests/test_telegram_auth.pyÚ
_post_authz$AuthenticateTelegramTests._post_auth   sM   € Ø—;‘;×#Ñ#Ü�OÓ$ØØ+ð $ó 
ˆð
 	×Ñ˜×-Ñ-¨sÔ3Ø�}‰}‹Ðó    z,apps.users.views.validate_telegram_init_datac                ó*  — dddddddœ|_         | j                  dd	i«      }| j                  d
|«       | j                  d|«       t        j                  j                  d¬«      }| j                  |j                  d«       | j                  |j                  d«       | j                  |j                  d«       | j                  |j                  d«       | j                  |j                  d«       | j                  |d   d   |j                  «       y)z5Creates a new user and returns JWTs and profile data.i90  ÚaliceÚAliceÚTesterÚenzhttps://img.test/alice.jpg)ÚidÚusernameÚ
first_nameÚ	last_nameÚlanguage_codeÚ	photo_urlÚ	init_datazsigned-init-dataÚaccessÚrefresh©Útelegram_user_idÚuserÚreferral_codeN)Úreturn_valuer    ÚassertInr   ÚobjectsÚgetr   r(   r)   r*   r+   r,   r3   ©r   Úmock_validateÚbodyr2   s       r   Ú$test_creates_user_and_returns_tokensz>AuthenticateTelegramTests.test_creates_user_and_returns_tokens   sï   € ð ØØ!Ø!Ø!Ø5ñ&
ˆÔ"ð �‰ Ð-?Ð@ÓAˆà�‰�h Ô%Ø�‰�i Ô&Ü�|‰|×Ñ°ÐÓ7ˆØ×Ñ˜Ÿ™¨Ô0Ø×Ñ˜Ÿ™¨'Ô2Ø×Ñ˜Ÿ™¨Ô2Ø×Ñ˜×+Ñ+¨TÔ2Ø×Ñ˜Ÿ™Ð)EÔFØ×Ñ˜˜f™ oÑ6¸×8JÑ8JÕKr!   c                óÐ   — | j                   j                  t        d«      i d¬«      }| j                  |j                  d«       | j                  d|j                  «       d   «       y)zinit_data must be provided.r   r   r   é�  zinit_data is requiredÚerrorN)r   r   r   r   r   r5   r   ©r   r   s     r   Útest_rejects_missing_init_dataz8AuthenticateTelegramTests.test_rejects_missing_init_data1   s[   € à—;‘;×#Ñ#Ü�OÓ$ØØ+ð $ó 
ˆð 	×Ñ˜×-Ñ-¨sÔ3Ø�‰Ð-¨x¯}©}«¸wÑ/GÕHr!   c                óô   — t        d«      |_        | j                  j                  t	        d«      ddid¬«      }| j                  |j                  d«       | j                  d|j                  «       d   «       y	)
z@Invalid init data returns 401 with the validation error message.zbad signaturer   r-   Úinvalidr   r   i‘  r>   N)	r	   Úside_effectr   r   r   r   r   r5   r   ©r   r9   r   s      r   Ú(test_rejects_invalid_init_data_signaturezBAuthenticateTelegramTests.test_rejects_invalid_init_data_signature<   so   € ô %@ÀÓ$PˆÔ!à—;‘;×#Ñ#Ü�OÓ$Ø˜yÐ)Ø+ð $ó 
ˆð 	×Ñ˜×-Ñ-¨sÔ3Ø�‰�o x§}¡}£°wÑ'?Õ@r!   c                óæ   — ddi|_         | j                  j                  t        d«      ddid¬«      }| j	                  |j
                  d«       | j                  d	|j                  «       d
   «       y)z8Validation output without an id is treated as bad input.r(   Únoidr   r-   Úsignedr   r   r=   zInvalid user datar>   N)r4   r   r   r   r   r   r5   r   rD   s      r   Útest_rejects_missing_user_idz6AuthenticateTelegramTests.test_rejects_missing_user_idJ   so   € ð '1°&Ð%9ˆÔ"à—;‘;×#Ñ#Ü�OÓ$Ø˜xÐ(Ø+ð $ó 
ˆð 	×Ñ˜×-Ñ-¨sÔ3Ø�‰Ð)¨8¯=©=«?¸7Ñ+CÕDr!   c                ól  — t         j                  j                  dddd¬«      }dddd	œ|_        | j	                  d
|j
                  dœ«      }t         j                  j                  d¬«      }| j                  |j                  |j                  «       | j                  |d   d   |j                  «       y)z.Links referrer by referral_code when provided.é   ÚreferrerÚRefÚrefcode1234©r1   r(   r)   r3   iÎV  ÚbobÚBob)r'   r(   r)   rH   ©r-   Ústart_paramr0   r2   Úreferred_byN)
r   r6   Úcreate_userr4   r    r3   r7   r   Úreferred_by_idr'   )r   r9   rL   r:   Únew_users        r   Ú.test_assigns_referral_when_start_param_presentzHAuthenticateTelegramTests.test_assigns_referral_when_start_param_presentX   s¬   € ô —<‘<×+Ñ+ØØØØ'ð	 ,ó 
ˆð ØØñ&
ˆÔ"ð �‰Ø"°8×3IÑ3IÑJó
ˆô —<‘<×#Ñ#°UÐ#Ó;ˆØ×Ñ˜×0Ñ0°(·+±+Ô>Ø×Ñ˜˜f™ mÑ4°h·k±kÕBr!   c                óÔ  — t         j                  j                  ddd¬«      }t         j                  j                  dddd¬	«      }t         j                  j                  d
dd|¬«      }d
ddœ|_        | j	                  d|j
                  dœ«      }|j                  «        | j                  |j                  |j                  «       | j                  |d   d   |j                  «       y)zDExisting referred_by is preserved even if a new start_param arrives.é
   Úref1ÚRef1)r1   r(   r)   é   Úref2ÚRef2Ú	OTHERCODErO   iœ­  ÚexistingÚExisting)r1   r(   r)   rT   ©r'   r(   rH   rR   r2   rT   N)
r   r6   rU   r4   r    r3   Úrefresh_from_dbr   rV   r'   )r   r9   Úoriginal_referrerÚother_referrerr2   r:   s         r   Ú)test_does_not_overwrite_existing_referralzCAuthenticateTelegramTests.test_does_not_overwrite_existing_referralo   sâ   € ô !ŸL™L×4Ñ4Ø¨&¸Vð 5ó 
Ðô Ÿ™×1Ñ1Ø¨&¸VÐS^ð 2ó 
ˆô �|‰|×'Ñ'Ø"ØØ!Ø)ð	 (ó 
ˆð -2¸zÑ%JˆÔ"à�‰¨XÀn×FbÑFbÑcÓdˆà×ÑÔØ×Ñ˜×,Ñ,Ð.?×.BÑ.BÔCØ×Ñ˜˜f™ mÑ4Ð6G×6JÑ6JÕKr!   c                óä   — dddœ|_         | j                  dddœ«      }t        j                  j	                  d¬«      }| j                  |j                  «       | j                  |d   d	   «       y
)z8Unknown referral codes are ignored without failing auth.iÙ  Únolinkrc   rH   ÚDOESNOTEXISTrR   r0   r2   rT   N)r4   r    r   r6   r7   ÚassertIsNonerV   r8   s       r   Ú"test_ignores_invalid_referral_codez<AuthenticateTelegramTests.test_ignores_invalid_referral_code†   sf   € ð -2¸xÑ%HˆÔ"à�‰¨XÀnÑUÓVˆä�|‰|×Ñ°ÐÓ7ˆØ×Ñ˜$×-Ñ-Ô.Ø×Ñ˜$˜v™, }Ñ5Õ6r!   c                óŒ  — t         j                  j                  ddddd¬«      }ddddd	d
œ|_        | j	                  ddi«       |j                  «        | j                  |j                  d«       | j                  |j                  d«       | j                  |j                  d«       | j                  |j                  d	«       y)z5Existing user gets profile fields refreshed on login.i5‚  ÚoldnameÚOldN)r1   r(   r)   r*   r+   ÚnewnameÚNewÚNamer'   )r'   r(   r)   r*   r+   r-   rH   )r   r6   rU   r4   r    rd   r   r(   r)   r*   r+   )r   r9   r2   s      r   Ú$test_updates_existing_profile_fieldsz>AuthenticateTelegramTests.test_updates_existing_profile_fields‘   s¸   € ô �|‰|×'Ñ'Ø"ØØØØð (ó 
ˆð Ø!ØØØ!ñ&
ˆÔ"ð 	�‰˜ hÐ/Ô0à×ÑÔØ×Ñ˜Ÿ™¨	Ô2Ø×Ñ˜Ÿ™¨%Ô0Ø×Ñ˜Ÿ™¨Ô0Ø×Ñ˜×+Ñ+¨TÕ2r!   N)r   ÚdictÚreturnrt   )Ú__name__Ú
__module__Ú__qualname__r    r   r;   r@   rE   rI   rX   rg   rl   rs   © r!   r   r   r      sÍ   „ óñ Ð9Ó:ñLó ;ðLò.	Iñ Ð9Ó:ñAó ;ðAñ Ð9Ó:ñEó ;ðEñ Ð9Ó:ñCó ;ðCñ, Ð9Ó:ñLó ;ðLñ, Ð9Ó:ñ7ó ;ð7ñ Ð9Ó:ñ3ó ;ñ3r!   r   c                  ó(  — e Zd Z eddd¬«       ed«      d„ «       «       Z ed¬«      d„ «       Z ed¬«      d	„ «       Z eddd¬«       ed«      d
„ «       «       Z eddd¬«       ed«      d„ «       «       Z	 eddd¬«       ed«      d„ «       «       Z
y)ÚTelegramWebhookTestsr   úsecret-tokenúhttps://example.com/app)r   ÚTELEGRAM_WEBHOOK_SECRETÚTELEGRAM_WEBAPP_URLz&apps.users.views.send_telegram_messagec                ó„  — d|_         dddiddœi}| j                  j                  t        d«      |dd	¬
«      }| j	                  |j
                  d«       |j                  «        |j                  \  }}| j	                  |d   d«       | j                  d|«       |d   d   d   d   d   d   }| j	                  |d«       y)z<Webhook responds with a WebApp button including start param.TÚmessager'   iÍ� z/start ABCDEF©ÚchatÚtextútelegram-webhookr   r|   ©r   r   Ú$HTTP_X_TELEGRAM_BOT_API_SECRET_TOKENr   Úchat_idÚreply_markupÚkeyboardr   Úweb_appÚurlz'https://example.com/app?startapp=ABCDEFN)	r4   r   r   r   r   r   Úassert_called_onceÚ	call_argsr5   ©r   Ú	mock_sendr   r   ÚargsÚkwargsÚ
button_urls          r   Ú8test_webhook_replies_with_webapp_button_and_valid_secretzMTelegramWebhookTests.test_webhook_replies_with_webapp_button_and_valid_secret­   sÜ   € ð "&ˆ	ÔàØ˜u˜Ø'ñð
ˆð —;‘;×#Ñ#ÜÐ&Ó'ØØ+Ø1?ð	 $ó 
ˆð 	×Ñ˜×-Ñ-¨sÔ3Ø×$Ñ$Ô&Ø ×*Ñ*‰ˆˆfØ×Ñ˜ 	Ñ*¨EÔ2Ø�‰�n fÔ-Ø˜NÑ+¨JÑ7¸Ñ:¸1Ñ=¸iÑHÈÑOˆ
Ø×Ñ˜Ð%NÕOr!   )r~   c                óž   — dddiddœi}| j                   j                  t        d«      |dd¬	«      }| j                  |j                  d
«       y)z9Webhook returns 403 when the secret token does not match.r�   r'   iW  ú/startr‚   r…   r   zwrong-secretr†   é“  N©r   r   r   r   r   r   s      r   Ú#test_webhook_rejects_invalid_secretz8TelegramWebhookTests.test_webhook_rejects_invalid_secretÌ   sb   € ð Ø˜t˜Ø ñð
ˆð —;‘;×#Ñ#ÜÐ&Ó'ØØ+Ø1?ð	 $ó 
ˆð 	×Ñ˜×-Ñ-¨sÕ3r!   c                ó˜   — | j                   j                  t        d«      dddiddœid¬«      }| j                  |j                  d	«       y
)z@Webhook returns 403 when secret is configured but header absent.r…   r�   r'   i®  r–   r‚   r   r   r—   Nr˜   r?   s     r   Ú*test_webhook_rejects_missing_secret_headerz?TelegramWebhookTests.test_webhook_rejects_missing_secret_headerß   sR   € ð —;‘;×#Ñ#ÜÐ&Ó'Ø t¨T l¸HÑEÐFØ+ð $ó 
ˆð 	×Ñ˜×-Ñ-¨sÕ3r!   c                ó`  — d|_         dddiddœi}| j                  j                  t        d«      |dd	¬
«      }| j	                  |j
                  d«       |j                  «        |j                  \  }}| j	                  |d   d«       |d   d   d   d   d   d   }| j	                  |d«       y)zANon-/start messages still reply without appending startapp param.Tr�   r'   iç  Úhellor‚   r…   r   r|   r†   r   rˆ   r‰   rŠ   r   r‹   rŒ   r}   N)r4   r   r   r   r   r   r�   rŽ   r�   s          r   Ú&test_webhook_handles_non_start_messagez;TelegramWebhookTests.test_webhook_handles_non_start_messageê   sÆ   € ð "&ˆ	ÔØ¨¨c {¸GÑDÐEˆà—;‘;×#Ñ#ÜÐ&Ó'ØØ+Ø1?ð	 $ó 
ˆð 	×Ñ˜×-Ñ-¨sÔ3Ø×$Ñ$Ô&Ø ×*Ñ*‰ˆˆfØ×Ñ˜ 	Ñ*¨CÔ0Ø˜NÑ+¨JÑ7¸Ñ:¸1Ñ=¸iÑHÈÑOˆ
Ø×Ñ˜Ð%>Õ?r!   c                ó$  — d|_         dddddiidœi}| j                  j                  t        d«      |d	d
¬«      }| j	                  |j
                  d«       |j                  j                  d   d   d   d   d   d   }| j	                  |d«       y)z)Callback queries use data as start param.TÚcallback_queryÚCALLBACKCODErƒ   r'   i	  )r   r�   r…   r   r|   r†   r   r‰   rŠ   r   r‹   rŒ   z-https://example.com/app?startapp=CALLBACKCODEN)r4   r   r   r   r   r   rŽ   r’   )r   r�   r   r   r“   s        r   Ú"test_webhook_handles_callback_dataz7TelegramWebhookTests.test_webhook_handles_callback_data  s±   € ð "&ˆ	ÔàØ&Ø" T¨3 KÐ0ñð
ˆð —;‘;×#Ñ#ÜÐ&Ó'ØØ+Ø1?ð	 $ó 
ˆð 	×Ñ˜×-Ñ-¨sÔ3Ø×(Ñ(×/Ñ/°Ñ?À
ÑKÈAÑNÈqÑQÐR[Ñ\Ð]bÑcˆ
Ø×Ñ˜Ð%TÕUr!   c                ó  — d|_         | j                  j                  t        d«      di idd¬«      }| j	                  |j
                  d«       | j	                  |j                  «       ddi«       |j                  «        y	)
z:Gracefully ack when chat info is missing to avoid retries.Tr…   r�   r   r|   r†   r   ÚokN)r4   r   r   r   r   r   r   Úassert_not_called)r   r�   r   s      r   Ú6test_webhook_acknowledges_missing_chat_without_sendingzKTelegramWebhookTests.test_webhook_acknowledges_missing_chat_without_sending  sy   € ð "&ˆ	Ôà—;‘;×#Ñ#ÜÐ&Ó'Ø˜R�Ø+Ø1?ð	 $ó 
ˆð 	×Ñ˜×-Ñ-¨sÔ3Ø×Ñ˜Ÿ™›¨4°¨,Ô7Ø×#Ñ#Õ%r!   N)rv   rw   rx   r   r   r”   r™   r›   rž   r¢   r¦   ry   r!   r   r{   r{   ¬   s   „ ÙØ+Ø .Ø5ôñ
 Ð3Ó4ñPó 5óðPñ2 ¨~Ô>ñ4ó ?ð4ñ$ ¨~Ô>ñ4ó ?ð4ñ Ø+Ø .Ø5ôñ
 Ð3Ó4ñ@ó 5óð@ñ& Ø+Ø .Ø5ôñ
 Ð3Ó4ñVó 5óðVñ* Ø+Ø .Ø5ôñ
 Ð3Ó4ñ&ó 5óñ&r!   r{   c                  óP   — e Zd Z eddd¬«      d„ «       Z eddd¬«      d„ «       Zy)ÚDevAuthenticateTelegramTestsTúdev-bot-token)ÚDEBUGÚENABLE_DEV_TELEGRAM_AUTHr   c                óÂ  — t        ddddœdd¬«      }| j                  j                  t        d«      d	|d	   id
¬«      }| j	                  |j
                  d«       |j                  «       }| j	                  |d   d   d«       | j                  d|«       | j	                  |d   d   |d   «       | j	                  |d   d   |d   «       | j                  d|d   «       y)zCDev endpoint returns debug info and authenticates signed init_data.iŸ† ÚDevÚdevuser)r'   r)   r(   r©   z	dev-query)r2   Ú	bot_tokenÚquery_idútelegram-auth-devr-   r   r   r   r2   r1   ÚdebugÚprovided_hashÚhashÚcalculated_hashÚdata_check_stringN)r
   r   r   r   r   r   r   r5   )r   rH   r   r:   s       r   Ú8test_dev_auth_validates_signed_payload_and_returns_debugzUDevAuthenticateTelegramTests.test_dev_auth_validates_signed_payload_and_returns_debug5  së   € ô +Ø¨UÀ	ÑJØ%Ø ô
ˆð —;‘;×#Ñ#ÜÐ'Ó(Ø˜v kÑ2Ð3Ø+ð $ó 
ˆð 	×Ñ˜×-Ñ-¨sÔ3Ø�}‰}‹ˆØ×Ñ˜˜f™Ð&8Ñ9¸5ÔAØ�‰�g˜tÔ$Ø×Ñ˜˜g™ Ñ7¸À¹ÔHØ×Ñ˜˜g™Ð'8Ñ9¸6À&¹>ÔJØ�‰Ð)¨4°©=Õ9r!   Fc                óŽ   — | j                   j                  t        d«      ddid¬«      }| j                  |j                  d«       y)z,Dev endpoint returns 404 outside DEBUG mode.r±   r-   Úanythingr   r   i”  Nr˜   r?   s     r   Ú%test_dev_auth_disabled_when_not_debugzBDevAuthenticateTelegramTests.test_dev_auth_disabled_when_not_debugP  sI   € ð —;‘;×#Ñ#ÜÐ'Ó(Ø˜zÐ*Ø+ð $ó 
ˆð 	×Ñ˜×-Ñ-¨sÕ3r!   N)rv   rw   rx   r   r·   rº   ry   r!   r   r¨   r¨   4  sD   „ ÙØØ!%Ø*ôñ
:óð
:ñ, ØØ!%Ø*ôñ
4óñ
4r!   r¨   N)Ú__doc__Ú
__future__r   Úunittest.mockr   Údjango.testr   r   Údjango.urlsr   Úapps.users.modelsr   Úutils.telegramr	   r
   r   r{   r¨   ry   r!   r   Ú<module>rÂ      sZ   ðÙ :å "å ç 3Ý å "ß Qñ Ð&6Ô7ôZ3 ó Z3ó 8ðZ3ôzE&˜8ô E&ôP)4 8õ )4r!   