
    P1i                     V   d Z ddlZddlmZmZmZ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 ddlmZ dd	lmZ dd
lmZmZmZ ddlmZmZmZmZmZmZ ddl m!Z! ddl"m#Z#  e       Z$ G d de      Z% G d de      Z& G d de      Z' G d de      Z( G d de      Z) G d de      Z*y)a7  
Comprehensive unit tests for AI conversation feature.

Tests cover:
- Standard cases: normal conversation flow, message sending, context management
- Edge cases: message limits, length limits, context thresholds, permissions
- Outlier cases: AI failures, invalid data, unauthorized access, retry functionality
    N)Mockpatch	MagicMockcall)TestCaseoverride_settings)get_user_model)timezone)datetime)	APIClient)status)ConversationMessageConversationSubject)create_conversationsend_conversation_messageprepare_conversation_promptcalculate_context_sizegenerate_conversation_summarymanage_conversation_context)Person)UserProfilec                   @    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
d	 Zy
)ConversationModelTestsz%Test Conversation and Message models.c                 6   t         j                  j                  ddd      | _        t        j                  j                  | j                         t        j                  j                  dt        ddd      t        d	d
      d| j                        | _
        yzSet up test data.
1234567890ztest@example.comtestpass123phoneemailpassworduserzTest Person        r   Mname
birth_date
birth_timegender
created_byNUserobjectscreate_userr%   r   get_or_creater   creater   r   personselfs    </home/cursorai/projects/iching/ai/tests/test_conversation.pysetUpzConversationModelTests.setUp$       LL,,$" - 
	 	))tyy)9nn++D!Q'B{yy , 
    c                    t        j                  d| j                  j                        }t        j
                  j                  | j                  |      }| j                  |j                         | j                  |j                  | j                         | j                  |j                  |       | j                  |j                         d       y)zTest creating a conversation.bazir%   subjectr   N)r   get_or_create_subjectr6   idr   r2   r5   r%   assertIsNotNoneassertEqualr@   get_message_countr8   r@   conversations      r9   test_create_conversationz/ConversationModelTests.test_create_conversation5   s    %;;FDKKNNS#++22 3 
 	\__-**DII6--w77791=r<   c                 B   t        j                  d| j                  j                        }t        j
                  j                  | j                  |d      }| j                  dt        |             | j                  t        | j                        t        |             y)z(Test conversation string representation.r>   z
Test Title)r%   r@   titleN)
r   rA   r6   rB   r   r2   r5   r%   assertInstrrF   s      r9   test_conversation_strz,ConversationModelTests.test_conversation_strA   st    %;;FDKKNNS#++22 3 

 	lC$56c$))nc,&78r<   c                 D   t        j                  d| j                  j                        }t        j
                  j                  | j                  |      }| j                  |j                  d       | j                  | j                  j                  t        |             y)z Test conversation without title.r>   r?    N)r   rA   r6   rB   r   r2   r5   r%   rD   rJ   rK   r+   rL   rF   s      r9   test_conversation_without_titlez6ConversationModelTests.test_conversation_without_titleL   sv    %;;FDKKNNS#++22 3 
 	++R0dkk&&L(9:r<   c                 "   t        j                  d| j                  j                        }t        j
                  j                  | j                  |      }t        j
                  j                  |dd      }t        j
                  j                  |dddd	
      }| j                  |j                         d       | j                  |j                  d       | j                  |j                  d       | j                  |j                  d       y)zTest creating messages.r>   r?   r%   HellorG   rolecontent	assistant	Hi there!groqllama-3.3-70b-versatilerG   rT   rU   providermodel   N)r   rA   r6   rB   r   r2   r5   r%   r   rD   rE   rT   r[   )r8   r@   rG   user_msgassistant_msgs        r9   test_message_creationz,ConversationModelTests.test_message_creationW   s    %;;FDKKNNS#++22 3 

 ??))% * 
  ..%+ / 
 	7791=/++[9//8r<   c                 ^   t        j                  d| j                  j                        }t        j
                  j                  | j                  |      }t        j
                  j                  |dd      }| j                  dt        |             | j                  dt        |             y)	z#Test message string representation.r>   r?   r%   zThis is a test messagerS   r1   zThis is a testN)r   rA   r6   rB   r   r2   r5   r%   r   rK   rL   )r8   r@   rG   msgs       r9   test_message_strz'ConversationModelTests.test_message_strr   s    %;;FDKKNNS#++22 3 
 oo$$%, % 

 	fc#h'&C1r<   c                 v   t        j                  d| j                  j                        }t        j
                  j                  | j                  |      }t        j
                  j                  |dd      }t        j
                  j                  |dd      }| j                  |j                         |       y)	zTest getting last message.r>   r?   r%   FirstrS   rV   SecondN)r   rA   r6   rB   r   r2   r5   r%   r   rD   get_last_message)r8   r@   rG   msg1msg2s        r9   test_get_last_messagez,ConversationModelTests.test_get_last_message   s    %;;FDKKNNS#++22 3 

 %%% & 
 %%% & 
 	668$?r<   c                    t        j                  d| j                  j                        }t        j
                  j                  | j                  |      }t        j
                  j                  |dd      }t        j
                  j                  |dd      }t        |j                  j                               }| j                  |d   |       | j                  |d	   |       y
)z+Test messages are ordered by creation time.r>   r?   r%   re   rS   rV   rf   r   r'   N)r   rA   r6   rB   r   r2   r5   r%   r   listmessagesallrD   )r8   r@   rG   rh   ri   rm   s         r9   test_message_orderingz,ConversationModelTests.test_message_ordering   s    %;;FDKKNNS#++22 3 

 %%% & 
 %%% & 
 --1134!d+!d+r<   N)__name__
__module____qualname____doc__r:   rH   rM   rP   r`   rc   rj   ro    r<   r9   r   r   !   s.    /
"
>	9	;962@,,r<   r   c                   b   e Zd ZdZd Zd Zd Z ed      d        Z ed      d        Z	d Z
d	 Z ed
       ed       ed      d                      Zd Z ed       ed       ed      d                      Z ed       ed       ed      d                      Z ed
       ed       ed       ed      d                             Z ed
       ed       ed       ed      d                             Z ed
       ed       ed       ed      d                             Zy)ConversationUtilityTestsz$Test conversation utility functions.c                    t         j                  j                  ddd      | _        t        j                  j                  | j                         t        j                  j                  dt        ddd      t        d	d
      d| j                        | _
        | j                  j                          | j                  j                          yr   r1   r2   r3   r%   r   r4   r   r5   r   r   r6   calculate_bazisaver7   s    r9   r:   zConversationUtilityTests.setUp       LL,,$" - 
	 	))tyy)9nn++D!Q'B{yy , 
 	""$r<   c                    t        | j                  d| j                  j                        }| j	                  |j                         | j                  |j                  | j                         | j                  |j                  j                  d       | j                  |j                  j                  | j                  j                         | j                  | j                  j                  |j                         y)z*Test create_conversation utility function.r>   r%   content_type	object_idN)r   r%   r6   rB   rC   rD   r@   r~   r   rK   r+   rJ   r8   rG   s     r9   !test_create_conversation_functionz:ConversationUtilityTests.test_create_conversation_function   s    *kknn
 	\__-**DII6--::FC--77Hdkk&&(:(:;r<   c                     t        | j                  d| j                  j                  d      }| j	                  |j
                  d       y)z+Test create_conversation with custom title.r>   zCustom Title)r%   r~   r   rJ   N)r   r%   r6   rB   rD   rJ   r   s     r9   #test_create_conversation_with_titlez<ConversationUtilityTests.test_create_conversation_with_title   s<    *kknn 	
 	++^<r<   )ai.utils.conversation.prepare_bazi_promptc                 f   d|_         t        | j                  d| j                  j                        }ddddddg}t        ||d	d
      }| j                  d|       | j                  d|       | j                  d|       | j                  d	|       |j                  | j                  d
       y)z*Test prepare_conversation_prompt function.zBaZi chart data herer>   r}   r%   rR   rT   rU   rV   zHi!zHow are you?enrG   conversation_historyuser_messagelanguager   N)return_valuer   r%   r6   rB   r   rK   assert_called_once_with)r8   mock_prepare_bazirG   historyprompts        r9    test_prepare_conversation_promptz9ConversationUtilityTests.test_prepare_conversation_prompt   s     *@&*kknn
 0 U3

 -%!('	
 	,f5gv&eV$nf-11$++1Mr<   c                     d|_         t        | j                  d| j                  j                        }d|_        |j                          t        |g dd      }| j                  d|       y)	z6Test prepare_conversation_prompt with context summary.zBaZi chart datar>   r}   zPrevious conversation summaryzNew questionr   r   N)	r   r   r%   r6   rB   context_summaryrz   r   rK   )r8   r   rG   r   s       r9   -test_prepare_conversation_prompt_with_summaryzFConversationUtilityTests.test_prepare_conversation_prompt_with_summary   sj     *;&*kknn

 (G$,%!#'	
 	5v>r<   c                     d}ddddddg}d}t        |||      }| j                  |d	       | j                  |t               y
)z%Test calculate_context_size function.a  BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data BaZi data r%   z	Message 1r   rV   z
Response 1zCurrent messagedivination_promptr   current_messager   N)r   assertGreaterassertIsInstanceint)r8   r   r   r   sizes        r9   test_calculate_context_sizez4ConversationUtilityTests.test_calculate_context_size  s[    .4 \:
 ,%/!(+
 	4#dC(r<   c                 `    d}d}t        |g d|      }| j                  |t        |             y)z)Test calculate_context_size with summary.	BaZi dataa   Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Summary Test)r   r   r   r   N)r   r   len)r8   r   summaryr   s       r9   (test_calculate_context_size_with_summaryzAConversationUtilityTests.test_calculate_context_size_with_summary$  s9    '"%/!#"#	
 	4W.r<   'ai.utils.conversation.LLMServiceFactory#ai.utils.conversation.get_ai_configc                    d|_         ddd|_         t               }d|j                  _         ||j                  _         t	        | j
                  d| j                  j                        }t        j                  j                  |dd	
      t        j                  j                  |dd
      g}t        ||d      }| j                  |d       |j                  j                          y)z,Test generate_conversation_summary function.r   rX   rY   r[   r\   z&This is a summary of the conversation.r>   r}   r%   z
Question 1rS   rV   zAnswer 1r   rG   messages_to_summarizer   N)r   r   get_completionget_servicer   r%   r6   rB   r   r2   r5   r   rD   assert_called_once)r8   r   mock_get_configmock_factorymock_servicerG   rm   r   s           r9   "test_generate_conversation_summaryz;ConversationUtilityTests.test_generate_conversation_summary1  s    
 *5&4:E^'_$ {3[##00<  -*kknn
 OO"")$ # 
 OO"") " # 
 0%"*
 	"JK##668r<   c                     t        | j                  d| j                  j                        }t	        |g d      }| j                  |d       y)z7Test generate_conversation_summary with empty messages.r>   r}   r   r   rO   N)r   r%   r6   rB   r   rD   )r8   rG   r   s      r9   (test_generate_conversation_summary_emptyzAConversationUtilityTests.test_generate_conversation_summary_emptyY  sH    *kknn
 0%"$
 	"%r<   3ai.utils.conversation.generate_conversation_summary  CONVERSATION_CONTEXT_THRESHOLDc                 "   d|_         t        | j                  d| j                  j                        }t        d      D ]1  }t        j                  j                  ||dz  dk(  rdndd	| 
       3 t        |d       |j                          y)z6Test manage_conversation_context when under threshold.zSmall BaZi datar>   r}      r]   r   r%   rV   Message rS   r   r   N)r   r   r%   r6   rB   ranger   r2   r5   r   assert_not_calledr8   r   mock_generate_summaryrG   is        r9   0test_manage_conversation_context_under_thresholdzIConversationUtilityTests.test_manage_conversation_context_under_thresholdi  s    
 *;&*kknn
 qAOO"") 1uzV{"1# #   	$L4@ 	//1r<   d   c                    ddz  |_         d|_         t        | j                  d| j                  j                        }t        d      D ]1  }t        j                  j                  ||dz  dk(  rd	nd
ddz         3 t        |d       |j                          |j                          | j                  |j                  d       y)z:Test manage_conversation_context when exceeding threshold.
BaZi data r   zSummary of old messagesr>   r}      r]   r   r%   rV   zLong message content 
   rS   r   r   N)r   r   r%   r6   rB   r   r   r2   r5   r   assert_calledrefresh_from_dbrD   r   r   s        r9   2test_manage_conversation_context_exceeds_thresholdzKConversationUtilityTests.test_manage_conversation_context_exceeds_threshold  s    
 *6)<&-F**kknn
 rAOO"") 1uzV{/25 #   	$L4@ 	++-$$&557PQr<   1ai.utils.conversation.manage_conversation_context1ai.utils.conversation.prepare_conversation_promptc                    ddd|_         d|_         t               }d|j                  _         ||j                  _         t	        | j
                  d| j                  j                        }t        |dd	
      }| j                  |       | j                  |j                  d       | j                  |j                  d       | j                  |j                  d       |j                          y)z,Test send_conversation_message success case.rX   rY   r   Full promptzAI response herer>   r}   rR   r   rG   r   r   rV   N)r   r   r   r   r   r%   r6   rB   r   rC   rD   rT   rU   r[   r   r8   mock_prepare_promptmock_manage_contextr   r   r   rG   r_   s           r9   &test_send_conversation_message_successz?ConversationUtilityTests.test_send_conversation_message_success  s     5;E^'_$+8( {3E##00<  -*kknn
 2% 
 	]+++[9..0BC//8..0r<   c                    d|_         t               }d|j                  _         ||j                  _         t	        | j
                  d| j                  j                        }t        |dddd	      }| j                  |j                  d       | j                  |j                  d       |j                  j                  d       y
)z<Test send_conversation_message with provider/model override.r   AI responser>   r}   rR   openaigpt-4or   )rG   r   r[   r\   r   N)r   r   r   r   r   r%   r6   rB   r   rD   r[   r\   change_modelassert_called_withr   s           r9   5test_send_conversation_message_with_provider_overridezNConversationUtilityTests.test_send_conversation_message_with_provider_override  s     ,9( {3@##00<  -*kknn
 2% 
 	//:,,h7!!44X>r<   c                 F   ddd|_         d|_         t               }d|j                  _         ||j                  _         t	        | j
                  d| j                  j                        }| j                  t              5  t        |dd	
       ddd       y# 1 sw Y   yxY w)z6Test send_conversation_message with empty AI response.rX   rY   r   r   rO   r>   r}   rR   r   r   N)r   r   r   r   r   r%   r6   rB   assertRaises
ValueErrorr   )r8   r   r   r   r   r   rG   s          r9   -test_send_conversation_message_empty_responsezFConversationUtilityTests.test_send_conversation_message_empty_response  s     5;E^'_$+8( {35##00<  -*kknn
 z*%)$ +**s   ?BB N)rp   rq   rr   rs   r:   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rt   r<   r9   rv   rv      s   .&<	= 67N 8N8 67? 8?*)$/ 45
01
67#9 8 2 6#9J&  @A
67d;2 < 8 B2. @A
67c:R ; 8 BR6 45
01
>?
>?1 @ @ 2 616 45
01
>?
>?? @ @ 2 6?4 45
01
>?
>? @ @ 2 6r<   rv   c                   r   e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
d	 Z ed
      d        Zd Zd Z ed       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d Z ed
      d        Zd Zy)ConversationAPITestsz Test conversation API endpoints.c                    t               | _        t        j                  j	                  ddd      | _        t        j                  j                  | j
                         | j                  j                  | j
                         t        j                  j                  dt        ddd      t        d	d
      d| j
                        | _        | j                  j                          | j                  j                          yr   )r   clientr1   r2   r3   r%   r   r4   force_authenticater   r5   r   r   r6   ry   rz   r7   s    r9   r:   zConversationAPITests.setUp  s    kLL,,$" - 
	 	))tyy)9&&DII&6nn++D!Q'B{yy , 
 	""$r<   c                 P   d| j                   j                   d}| j                  j                  |      }| j	                  |j
                  t        j                         | j	                  |j                  d   d       | j	                  t        |j                  d         d       y)z+Test listing conversations when none exist./api/bazi/bazi//conversations/countr   resultsN)
r6   rB   r   getrD   status_coder   HTTP_200_OKdatar   r8   urlresponses      r9   test_list_conversations_emptyz2ConversationAPITests.test_list_conversations_empty  s~    /?;;??3'--v/A/ABw/3X]]956:r<   c                 P   t        j                  d| j                  j                        }t        j
                  j                  | j                  |      }t        j
                  j                  | j                  |      }d| j                  j                   d}| j                  j                  |      }| j                  |j                  t        j                         | j                  |j                  d   d       | j                  t        |j                  d         d       y)	z.Test listing conversations with existing data.r>   r?   r   r   r   r]   r   N)r   rA   r6   rB   r   r2   r5   r%   r   r   rD   r   r   r   r   r   )r8   r@   conversation1conversation2r   r   s         r9   !test_list_conversations_with_dataz6ConversationAPITests.test_list_conversations_with_data  s    %;;FDKKNNS$,,33 4 
 %,,33 4 

  /?;;??3'--v/A/ABw/3X]]956:r<   c                 d   t         j                  j                  ddd      }t        j                  j	                  dt        ddd      t        dd	      d
|      }d|j                   d}| j                  j                  |      }| j                  |j                  t        j                         y)z5Test listing conversations for another user's person.
9999999999other@example.comr   r    Other Personr&   r'   r(   r   r)   r*   r   r   N)r1   r2   r3   r   r5   r   r   rB   r   r   rD   r   r   HTTP_404_NOT_FOUNDr8   
other_userother_personr   r   s        r9   "test_list_conversations_other_userz7ConversationAPITests.test_list_conversations_other_user.  s    \\--%" . 


 ~~,,D!Q'B{! - 
  0@;;??3'--v/H/HIr<   c                    t        j                  d| j                  j                        }t        j
                  j                  | j                  |      }t        j
                  j                  |dd       t        j
                  j                  |dd       d| j                  j                   d	|j                   d
}| j                  j                  |      }| j                  |j                  t        j                         | j                  t        |j                   d         d       | j                  |j                   d   d   d   d       y)z!Test getting conversation detail.r>   r?   r%   rR   rS   rV   rW   r   r   /rm   r]   r   rU   N)r   rA   r6   rB   r   r2   r5   r%   r   r   r   rD   r   r   r   r   r   r8   r@   rG   r   r   s        r9   test_get_conversation_detailz1ConversationAPITests.test_get_conversation_detailB  s   %;;FDKKNNS#++22 3 

 	% 	 	
 	% 	 	
  /|>OqQ;;??3'--v/A/ABX]]:67;z215i@'Jr<   c                     d| j                   j                   d}| j                  j                  |      }| j	                  |j
                  t        j                         y)z'Test getting non-existent conversation.r   z/conversations/999/N)r6   rB   r   r   rD   r   r   r   r   s      r9   test_get_conversation_not_foundz4ConversationAPITests.test_get_conversation_not_found]  sH    //BC;;??3'--v/H/HIr<   c                 `   d| j                   j                   d}| j                  j                  |      }| j	                  |j
                  t        j                         | j                  d|j                         | j	                  |j                  d   | j                   j                         y)z!Test creating a new conversation.r   /conversations/create/rB   	person_idN)
r6   rB   r   postrD   r   r   HTTP_201_CREATEDrK   r   r   s      r9   rH   z-ConversationAPITests.test_create_conversationd  s}    //EF;;##C(--v/F/FGdHMM*{3T[[^^Dr<   c                 d   t         j                  j                  ddd      }t        j                  j	                  dt        ddd      t        dd	      d
|      }d|j                   d}| j                  j                  |      }| j                  |j                  t        j                         y)z3Test creating conversation for unauthorized person.r   r   r   r    r   r&   r'   r(   r   r)   r*   r   r  N)r1   r2   r3   r   r5   r   r   rB   r   r  rD   r   r   r   r   s        r9   ,test_create_conversation_unauthorized_personzAConversationAPITests.test_create_conversation_unauthorized_personm  s    \\--%" . 


 ~~,,D!Q'B{! - 
  00FG;;##C(--v/H/HIr<   #api.views.send_conversation_messagec                 8   t        j                  d| j                  j                        }t        j
                  j                  | j                  |      fd}||_        d| j                  j                   dj                   d}| j                  j                  |ddd	      }| j                  |j                  t        j                         | j                  d
|j                          | j                  d|j                          |j#                          y)z$Test sending a message successfully.r>   r?   c                      t         j                  j                  d|d         }t         j                  j                  dddd      S )	Nr%   r   rS   rV   r   rX   rY   rZ   r   r2   r5   argskwargsr^   rG   s      r9   mock_send_side_effectzMConversationAPITests.test_send_message_success.<locals>.mock_send_side_effect  sW    --)~. . H ??))) %/ *  r<   r   r   /send/rR   r   messager   r   assistant_messageN)r   rA   r6   rB   r   r2   r5   r%   side_effectr   r  rD   r   r   r   rK   r   r   )r8   mock_send_messager@   r  r   r   rG   s         @r9   test_send_message_successz.ConversationAPITests.test_send_message_success  s     &;;FDKKNNS#++22 3 
	  )>%/|>OvV;;##C*
 
 	--v/A/ABnhmm4)8==9,,.r<   c                    t        j                  d| j                  j                        }t        j
                  j                  | j                  |      }d| j                  j                   d|j                   d}| j                  j                  |ddd      }| j                  |j                  t        j                         y	)
zTest sending empty message.r>   r?   r   r   r     r   r  Nr   rA   r6   rB   r   r2   r5   r%   r   r  rD   r   r   HTTP_400_BAD_REQUESTr   s        r9   test_send_message_emptyz,ConversationAPITests.test_send_message_empty  s    %;;FDKKNNS#++22 3 

  /|>OvV;;##C*
 
 	--v/J/JKr<   c                    t        j                  d| j                  j                        }t        j
                  j                  | j                  |      }d}d| j                  j                   d|j                   d}| j                  j                  ||dd      }| j                  |j                  t        j                         y	)
z,Test sending message exceeding length limit.r>   r?     aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaar   r   r  r   r  Nr  )r8   r@   rG   long_messager   r   s         r9   test_send_message_too_longz/ConversationAPITests.test_send_message_too_long  s    %;;FDKKNNS#++22 3 

 "/|>OvV;;##C#*
 
 	--v/J/JKr<      CONVERSATION_MAX_MESSAGESc                 j   t        j                  d| j                  j                        }t        j
                  j                  | j                  |      }t        d      D ]1  }t        j
                  j                  ||dz  dk(  rdndd| 	       3 d
| j                  j                   d|j                   d}| j                  j                  |ddd      }| j                  |j                  t        j                         | j!                  d|j"                  d          |j%                          y)z+Test sending message when limit is reached.r>   r?   r!  r]   r   r%   rV   r   rS   r   r   r  zShould failr   r  zmaximum message limiterrorN)r   rA   r6   rB   r   r2   r5   r%   r   r   r   r  rD   r   r   r  rK   r   r   )r8   r  r@   rG   r   r   r   s          r9   test_send_message_limit_reachedz4ConversationAPITests.test_send_message_limit_reached  s    &;;FDKKNNS#++22 3 
 qAOO"") 1uzV{"1# #    /|>OvV;;##C$*
 
 	--v/J/JK-x}}W/EF++-r<   c                    t        j                  d| j                  j                        }t        j
                  j                  | j                  |      }d| j                  j                  _	        | j                  j                  j                          d| j                  j                   d|j                   d}| j                  j                  |ddd	d
      }| j                  |j                  t        j                          y)z0Test provider/model override without permission.r>   r?   Fr   r   r  rR   r   r   r  r[   r\   N)r   rA   r6   rB   r   r2   r5   r%   profilecan_regenerate_airz   r   r  rD   r   r   HTTP_403_FORBIDDENr   s        r9   6test_send_message_provider_override_without_permissionzKConversationAPITests.test_send_message_provider_override_without_permission  s    %;;FDKKNNS#++22 3 
 /4		+		 /|>OvV;;##C *
  	--v/H/HIr<   c                    t        j                  d| j                  j                        }t        j
                  j                  | j                  |      d| j                  j                  _	        | j                  j                  j                          fd}||_        d| j                  j                   dj                   d}| j                  j                  |dd	d
d      }| j                  |j                  t         j"                         |j%                          |j&                  r|j&                  d   ni }|rC| j                  |j)                  d      d	       | j                  |j)                  d      d
       yy)z-Test provider/model override with permission.r>   r?   Tc                      t         j                  j                  d|d          t         j                  j                  dddd      S )	Nr%   r   rS   rV   r   r   r   rZ   r  r  r  rG   s     r9   r  zgConversationAPITests.test_send_message_provider_override_with_permission.<locals>.mock_send_side_effect  sU    OO"")~. #  ??))) %! *  r<   r   r   r  rR   r   r   r(  r'   r[   r\   N)r   rA   r6   rB   r   r2   r5   r%   r)  r*  rz   r  r   r  rD   r   r   r   r   	call_argsr   r8   r  r@   r  r   r   call_kwargsrG   s          @r9   3test_send_message_provider_override_with_permissionzHConversationAPITests.test_send_message_provider_override_with_permission  sD    &;;FDKKNNS#++22 3 
 /3		+		 	  )>%/|>OvV;;##C *
  	--v/A/AB,,.8I8S8S'11!4Y[[__Z8(C[__W5x@ r<   c                    t        j                  d| j                  j                        }t        j
                  j                  | j                  |      fd}||_        d| j                  j                   dj                   d}| j                  j                  |ddd	      }| j                  |j                  t        j                         | j                  d
|j                          | j                  d|j                   d
          | j                  |j                   d
   d   d       | j                  d|j                   d
          | j                  |j                   d
   d   d       | j#                  |j                   d          | j                  d|j                          | j                  d|j                          |j                   d
   d   }| j%                  |       | j'                  |t(               y)z@Test handling AI service failure returns failed message with ID.r>   r?   c                      t         j                  j                  d|d   d      }d|_        d|_        |j                          t        d      Nr%   r   pendingrG   rT   rU   r   failedAI service errorr   r2   r5   r   error_messagerz   	Exceptionr  s      r9   r  zPConversationAPITests.test_send_message_ai_failure.<locals>.mock_send_side_effect2  sS    --)~. 	 . H 'HO%7H"MMO.//r<   r   r   r  rR   r   r  r   rB   r   r9  r<  rU   r  r%  detailN)r   rA   r6   rB   r   r2   r5   r%   r  r   r  rD   r   r   HTTP_500_INTERNAL_SERVER_ERRORrK   r   assertIsNonerC   r   r   )r8   r  r@   r  r   r   
message_idrG   s          @r9   test_send_message_ai_failurez1ConversationAPITests.test_send_message_ai_failure)  s    &;;FDKKNNS#++22 3 

	0 )>%/|>OvV;;##C*
  	--v/T/TUnhmm4dHMM.9:~6x@(Kox}}^'DE~6yA7K(--(;<=gx}}-h. ]]>248
Z(j#.r<   c                   	 t        j                  d| j                  j                        }t        j
                  j                  | j                  |      	t        j
                  j                  	ddddt        j                         t        j                  d      z
  	      }t        j
                  j                  	dd
ddt        j                         t        j                  d      z
  	      }	fd}||_        d| j                  j                   d	j                   d}| j                  j                  |ddd      }| j                  |j                   t"        j$                         | j'                  d|j(                         | j'                  d|j(                  d          | j                  |j(                  d   d   d       | j                  |j(                  d   d   d       | j                  |j(                  d   d   d       |j(                  d   d   }| j+                  ||j                         | j+                  ||j                         y)zQTest that send message API returns the latest failed message when multiple exist.r>   r?   r%   zFirst failed messager9  zError 1r   )minutes)rG   rT   rU   r   r<  
created_atzSecond failed messagezError 2r   c                      t         j                  j                  d|d   d      }d|_        d|_        |j                          t        d      )Nr%   r   r7  r8  r9  Latest errorzLatest AI service errorr;  r  s      r9   r  zpConversationAPITests.test_send_message_api_returns_latest_failed_message_on_error.<locals>.mock_send_side_effectu  sS    --)~. 	 . H 'HO%3H"MMO566r<   r   r   r  zLatest test messager   r  r   rB   rU   r   r<  rG  N)r   rA   r6   rB   r   r2   r5   r%   r   r
   now	timedeltar  r   r  rD   r   r   r?  rK   r   assertNotEqual)
r8   r  r@   failed_msg1failed_msg2r  r   r   returned_idrG   s
            @r9   <test_send_message_api_returns_latest_failed_message_on_errorzQConversationAPITests.test_send_message_api_returns_latest_failed_message_on_errorY  s    &;;FDKKNNS#++22 3 
 oo,,%*#||~(:(:2(FF - 
 oo,,%+#||~(:(:1(EE - 
	7 )>%/|>OvV;;##C,*
  	--v/T/TUnhmm4dHMM.9:~6yACXY~6x@(K~6GX mmN3D9K8K8r<   c                    t        j                  d| j                  j                        }t        j
                  j                  | j                  |      }t        d      |_	        d| j                  j                   d|j                   d}| j                  j                  |ddd	      }| j                  |j                  t        j                         | j!                  d
|j"                         | j!                  d|j"                         y)zDTest API error response when no failed message is found (edge case).r>   r?   zError before message creationr   r   r  zTest messager   r  r%  r>  N)r   rA   r6   rB   r   r2   r5   r%   r=  r  r   r  rD   r   r   r?  rK   r   )r8   r  r@   rG   r   r   s         r9   8test_send_message_api_error_when_no_failed_message_foundzMConversationAPITests.test_send_message_api_error_when_no_failed_message_found  s     &;;FDKKNNS#++22 3 
 )22Q(R%/|>OvV;;##C%*
  	--v/T/TUgx}}-h.r<   c                    t        j                  d| j                  j                        }t        j
                  j                  | j                  |      fd|_        d| j                  j                   dj                   d}| j                  j                  |ddd	      }| j                  |j                  t        j                         | j                  d
|j                          |j                   d
   d   }t"        j
                  j%                  |      }| j                  |j                  |       | j                  |j                  d       | j                  |j&                  d       | j                  |j(                  d       | j                  |j*                  j                  j                         y)zHTest that returned failed message ID matches the actual database record.r>   r?   c                      t         j                  j                  d|d   d      }d|_        d|_        |j                          |j                  _        t        d      r6  )	r   r2   r5   r   r<  rz   rB   created_message_idr=  )r  r  r^   rG   r  s      r9   r  zlConversationAPITests.test_send_message_api_failed_message_id_matches_database.<locals>.mock_send_side_effect  s`    --)~. 	 . H 'HO%7H"MMO7?{{!4.//r<   r   r   r  z Test message for ID verificationr   r  r   rB   rB   r9  r:  N)r   rA   r6   rB   r   r2   r5   r%   r  r   r  rD   r   r   r?  rK   r   r   r   rU   r<  rG   )	r8   r  r@   r   r   returned_message_id
db_messagerG   r  s	          @@r9   8test_send_message_api_failed_message_id_matches_databasezMConversationAPITests.test_send_message_api_failed_message_id_matches_database  sn    &;;FDKKNNS#++22 3 

	0" )>%/|>OvV;;##C9*
  	--v/T/TUnhmm4&mmN;DA __((,?(@
(;<**H5++-OP113EF0033\__Er<   c                    t        j                  d| j                  j                        }t        j
                  j                  | j                  |      t        j
                  j                  dd      }fd}||_	        d| j                  j                   dj                   d	}| j                  j                  |      }| j                  |j                  t        j                         |j!                          |j"                  r|j"                  d
   ni }|r"| j                  |j%                  d      d       yy)z%Test retrying a message successfully.r>   r?   r%   rR   rS   c                  L    t         j                  j                  dddd      S )NrV   zRetry responserX   rY   rZ   r  r/  s     r9   r  zNConversationAPITests.test_retry_message_success.<locals>.mock_send_side_effect  s.    ??))) (/ *  r<   r   r   /retry/r'   r   N)r   rA   r6   rB   r   r2   r5   r%   r   r  r   r  rD   r   r   r   r   r0  r   )	r8   r  r@   r^   r  r   r   r2  rG   s	           @r9   test_retry_message_successz/ConversationAPITests.test_retry_message_success  s    &;;FDKKNNS#++22 3 

 ??))% * 
	 )>%/|>OwW;;##C(--v/A/AB,,.8I8S8S'11!4Y[[__^<gF r<   c                    t        j                  d| j                  j                        }t        j
                  j                  | j                  |      }t        j
                  j                  |dd       d| j                  j                   d|j                   d}| j                  j                  |      }| j                  |j                  t        j                         y	)
z'Test retry when no user message exists.r>   r?   rV   zOnly assistantrS   r   r   rZ  N)r   rA   r6   rB   r   r2   r5   r%   r   r   r  rD   r   r   r  r   s        r9   "test_retry_message_no_user_messagez7ConversationAPITests.test_retry_message_no_user_message  s    %;;FDKKNNS#++22 3 
 	%$ 	 	
  /|>OwW;;##C(--v/J/JKr<   c           	         t        j                  d| j                  j                        }t        j
                  j                  | j                  |      t        j
                  j                  dd       t        j
                  j                  dddd	d
di       fd}||_	        d| j                  j                   dj                   d}| j                  j                  |      }| j                  |j                  t        j                         |j                   r|j                   d   ni }|r"| j                  |j#                  d
      d       yy)z:Test retry preserves language from last assistant message.r>   r?   r%   rR   rS   rV   ResponserX   rY   r   r   )rG   rT   rU   r[   r\   metac                  H    t         j                  j                  dd      S )NrV   RetryrS   r  r/  s     r9   r  zYConversationAPITests.test_retry_message_preserves_language.<locals>.mock_send_side_effect2  s(    ??)))  *  r<   r   r   rZ  r'   N)r   rA   r6   rB   r   r2   r5   r%   r   r  r   r  rD   r   r   r   r0  r   r1  s          @r9   %test_retry_message_preserves_languagez:ConversationAPITests.test_retry_message_preserves_language  s5    &;;FDKKNNS#++22 3 

 	% 	 	
 	%+d# 	 	
	 )>%/|>OwW;;##C(--v/A/AB8I8S8S'11!4Y[[__Z8$? r<   c                     | j                   j                          d| j                  j                   d}| j                   j	                  |      }| j                  |j                  t        j                         y)z&Test unauthorized access to endpoints.r   r   N)	r   logoutr6   rB   r   rD   r   r   HTTP_401_UNAUTHORIZEDr   s      r9   test_unauthorized_accessz-ConversationAPITests.test_unauthorized_accessD  sW    /?;;??3'--v/K/KLr<   N)rp   rq   rr   rs   r:   r   r   r   r   r  rH   r  r   r  r  r   r   r&  r,  r3  rB  rN  rP  rW  r[  r]  rc  rg  rt   r<   r9   r   r     sV   *,;;&J(K6JEJ( 01$/ 2$/LL L$ 3
01. 2 4.4J* 01+A 2+AZ 01-/ 2-/^ 01<9 2<9| 01/ 2/2 01,F 2,F\ 01"G 2"GHL( 01'@ 2'@RMr<   r   c                   :    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
y	)
ConversationSerializerTestszTest conversation serializers.c                 6   t         j                  j                  ddd      | _        t        j                  j                  | j                         t        j                  j                  dt        ddd      t        d	d
      d| j                        | _
        yr   r0   r7   s    r9   r:   z!ConversationSerializerTests.setUpQ  r;   r<   c                     ddl m}  |ddd      }| j                  |j                                | j	                  |j
                  d   d       | j	                  |j
                  d   d       y	)
z+Test SendMessageSerializer with valid data.r   SendMessageSerializerrR   r   r  r   r  r   Napi.serializersrm  
assertTrueis_validrD   validated_datar8   rm  
serializers      r9   "test_send_message_serializer_validz>ConversationSerializerTests.test_send_message_serializer_validb  sg    9*1
 

 	
++-.229=wG22:>Er<   c                     ddl m}  |ddd      }| j                  |j                                | j	                  d|j
                         y)	z.Test SendMessageSerializer with empty message.r   rl  r  r   r  rn  r  Nrp  rm  assertFalserr  rK   errorsrt  s      r9   "test_send_message_serializer_emptyz>ConversationSerializerTests.test_send_message_serializer_emptyo  sG    9*1
 

 	,,./i!2!23r<   c                     ddl m}  |ddd      }| j                  |j                                | j	                  d|j
                         y)	z1Test SendMessageSerializer with message too long.r   rl  r  r   r  rn  r  Nrx  rt  s      r9   %test_send_message_serializer_too_longzAConversationSerializerTests.test_send_message_serializer_too_long{  sG    9*!1
 

 	,,./i!2!23r<   c                     ddl m}  |ddd      }| j                  |j                                | j	                  |j
                  d   d       y	)
z-Test SendMessageSerializer strips whitespace.r   rl  z	  Hello  r   r  rn  r  rR   Nro  rt  s      r9   .test_send_message_serializer_strips_whitespacezJConversationSerializerTests.test_send_message_serializer_strips_whitespace  sL    9*"1
 

 	
++-.229=wGr<   c                 6   ddl m} t        j                  d| j                  j
                        }t        j                  j                  | j                  |      }t        j                  j                  |dd       t        j                  j                  |dd	        ||      }|j                  }| j                  |d
   |j
                         | j                  |d   | j                  j
                         | j                  t        |d         d       y)zTest ConversationSerializer.r   )ConversationSerializerr>   r?   r%   rR   rS   rV   rW   rB   r  rm   r]   N)rp  r  r   rA   r6   rB   r   r2   r5   r%   r   r   rD   r   )r8   r  r@   rG   ru  r   s         r9   test_conversation_serializerz8ConversationSerializerTests.test_conversation_serializer  s    :%;;FDKKNNS#++22 3 

 	% 	 	
 	% 	 	
 ,L9
d\__5k*DKKNN;T*-.2r<   c                    ddl m} t        j                  d| j                  j
                        }t        j                  j                  | j                  |      }t        j                  j                  |dd        ||      }|j                  }| j                  |d   |j
                         | j                  |d	   | j                  j
                         | j                  |d
   d       | j                  d|       y)z Test ConversationListSerializer.r   )ConversationListSerializerr>   r?   r%   rR   rS   rB   r  message_countr'   last_messageN)rp  r  r   rA   r6   rB   r   r2   r5   r%   r   r   rD   rK   )r8   r  r@   rG   ru  r   s         r9   !test_conversation_list_serializerz=ConversationSerializerTests.test_conversation_list_serializer  s    >%;;FDKKNNS#++22 3 

 	% 	 	
 0=
d\__5k*DKKNN;o.2nd+r<   N)rp   rq   rr   rs   r:   rv  r{  r}  r  r  r  rt   r<   r9   ri  ri  N  s*    (
"F
4
4
H3:,r<   ri  c                       e Zd ZdZd Zd Zd Z ed      d        Z ed      d        Z	 e
d	      d
        Zd Zd Zd Zy)ConversationEdgeCaseTestsz(Test edge cases and boundary conditions.c                    t         j                  j                  ddd      | _        t        j                  j                  | j                         t        j                  j                  dt        ddd      t        d	d
      d| j                        | _
        | j                  j                          | j                  j                          yr   rx   r7   s    r9   r:   zConversationEdgeCaseTests.setUp  r{   r<   c                 j    ddl m} d} ||dd      }| j                  |j                                y)z*Test message with exactly 2000 characters.r   rl    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaar   r  rn  N)rp  rm  rq  rr  r8   rm  r  ru  s       r9   test_message_exactly_2000_charsz9ConversationEdgeCaseTests.test_message_exactly_2000_chars  s6    9*1
 

 	
++-.r<   c                 j    ddl m} d} ||dd      }| j                  |j                                y)z/Test message with 2001 characters (over limit).r   rl  r  r   r  rn  N)rp  rm  ry  rr  r  s       r9   test_message_2001_charsz1ConversationEdgeCaseTests.test_message_2001_chars  s8    9*1
 

 	,,./r<      r"  c                 l   t        j                  d| j                  j                        }t        j
                  j                  | j                  |      }t        d      D ]1  }t        j
                  j                  ||dz  dk(  rdndd| 	       3 | j                  |j                         d       y
)z+Test conversation with exactly 25 messages.r>   r?   r  r]   r   r%   rV   r   rS   N)r   rA   r6   rB   r   r2   r5   r%   r   r   rD   rE   )r8   r@   rG   r   s       r9   test_exactly_25_messagesz2ConversationEdgeCaseTests.test_exactly_25_messages  s     &;;FDKKNNS#++22 3 
 rAOO"") 1uzV{"1# #   	7792>r<   c                 D   t        j                  d| j                  j                        }t        j
                  j                  | j                  |      }t        d      D ]1  }t        j
                  j                  ||dz  dk(  rdndd| 	       3 t               }|j                  | j                  
       d| j                  j                   d|j                   d}|j                  |ddd      }| j                  |j                  t        j                          y)z"Test that 26th message is blocked.r>   r?   r  r]   r   r%   rV   r   rS   r$   r   r   r  z26th messager   r  N)r   rA   r6   rB   r   r2   r5   r%   r   r   r   r   r  rD   r   r   r  )r8   r@   rG   r   r   r   r   s          r9   test_26_messages_blocks_newz5ConversationEdgeCaseTests.test_26_messages_blocks_new
  s     &;;FDKKNNS#++22 3 
 rAOO"") 1uzV{"1# #   !!tyy!1/|>OvV;;s%%
 
 	--v/J/JKr<   r	  c                 b   t        j                  d| j                  j                        }t        j
                  j                  | j                  |      fd}||_        t               }|j                  | j                         d| j                  j                   dj                   d}|j                  |dd	d
      }| j                  |j                  t        j                         |j                   r|j                   d   ni }|r"| j                  |j#                  d      d	       yy)z(Test conversation with Chinese language.r>   r?   c                      t         j                  j                  d|d          t         j                  j                  dd      S )Nr%   r   rS   rV   u   中文回复r  r/  s     r9   r  zNConversationEdgeCaseTests.test_chinese_language.<locals>.mock_send_side_effect0  sO    OO"")~. #  ??))) & *  r<   r$   r   r   r  u   你好zzh-hansr  r'   r   N)r   rA   r6   rB   r   r2   r5   r%   r  r   r   r  rD   r   r   r   r0  r   )	r8   r  r@   r  r   r   r   r2  rG   s	           @r9   test_chinese_languagez/ConversationEdgeCaseTests.test_chinese_language'  s    &;;FDKKNNS#++22 3 

	 )>%!!tyy!1/|>OvV;;s!%
 
 	--v/A/AB8I8S8S'11!4Y[[__Z8)D r<   c                 .   t        j                  d| j                  j                        }t        j
                  j                  | j                  |      }d}t        j
                  j                  |d|      }| j                  |j                  |       y)z"Test message with unicode content.r>   r?   u   你好 🌟 测试 émojisr%   rS   N)r   rA   r6   rB   r   r2   r5   r%   r   rD   rU   )r8   r@   rG   unicode_messagerb   s        r9   test_unicode_message_contentz6ConversationEdgeCaseTests.test_unicode_message_contentN  s    %;;FDKKNNS#++22 3 

 7oo$$%# % 
 	o6r<   c                 p   t         j                  j                  | j                  | j                        }t         j                  j                  | j                  | j                        }| j                  |j                  |j                         | j                  |j                  |j                         y)z,Test multiple conversations for same person.)r%   r6   N)r   r2   r5   r%   r6   rJ  rB   rD   )r8   r   r   s      r9   'test_multiple_conversations_same_personzAConversationEdgeCaseTests.test_multiple_conversations_same_person_  s    $,,33;; 4 
 %,,33;; 4 

 	M,,m.>.>?--}/C/CDr<   c                    t        j                  d| j                  j                        }t        j
                  j                  | j                  |      }|j                  }ddl	} |j                  d       t        j
                  j                  |dd       |j                          | j                  |j                         d	       y)
z4Test conversation updated_at changes on new message.r>   r?   r   Ng{Gz?r%   r   rS   r'   )r   rA   r6   rB   r   r2   r5   r%   
updated_atr   sleepr   r   rD   rE   )r8   r@   rG   original_updatedr   s        r9   $test_conversation_updated_at_changesz>ConversationEdgeCaseTests.test_conversation_updated_at_changesm  s    %;;FDKKNNS#++22 3 

 (22 	

4% 	 	
 	$$& 	7791=r<   N)rp   rq   rr   rs   r:   r  r  r   r  r  r   r  r  r  r  rt   r<   r9   r  r    su    2&
/
0 4? 5?$ 4L 5L8 01$E 2$EL7"E>r<   r  c                   F   e Zd ZdZd Zd Zd Z ed       ed       ed      d	                      Z	 ed
       ed       ed       ed      d                             Z
d Zd Zd Z ed
       ed       ed       ed      d                             Zd Zd Zy)ConversationOutlierTestsz'Test outlier cases and error scenarios.c                    t         j                  j                  ddd      | _        t        j                  j                  | j                         t        j                  j                  dt        ddd      t        d	d
      d| j                        | _
        | j                  j                          | j                  j                          yr   rx   r7   s    r9   r:   zConversationOutlierTests.setUp  r{   r<   c                     t               }|j                  | j                         d}|j                  |      }| j	                  |j
                  t        j                         y)z Test API with invalid person ID.r$   z#/api/bazi/bazi/99999/conversations/N)r   r   r%   r   rD   r   r   r   r8   r   r   r   s       r9   test_invalid_person_idz/ConversationOutlierTests.test_invalid_person_id  sL    !!tyy!13::c?--v/H/HIr<   c                     t               }|j                  | j                         d| j                  j                   d}|j                  |      }| j                  |j                  t        j                         y)z&Test API with invalid conversation ID.r$   r   z/conversations/99999/N)
r   r   r%   r6   rB   r   rD   r   r   r   r  s       r9   test_invalid_conversation_idz5ConversationOutlierTests.test_invalid_conversation_id  s_    !!tyy!1//DE::c?--v/H/HIr<   r   r   r   r   c                    ddz  |_         t        d      |_        t        j                  d| j
                  j                        }t        j                  j                  | j                  |      }t        d      D ]1  }t        j                  j                  ||dz  dk(  rd	nd
ddz         3 	 t        |d       |j                          | j!                  |j"                         y# t        $ r | j                  d       Y Hw xY w)z)Test handling summary generation failure.zLarge BaZi data r   zSummary generation failedr>   r?   r   r]   r   r%   rV   zLong message r   rS   r   r   zEmanage_conversation_context should handle summary failures gracefullyN)r   r=  r  r   rA   r6   rB   r   r2   r5   r%   r   r   r   failr   ry  r   )r8   r   r   r@   rG   r   s         r9   test_summary_generation_failurez8ConversationOutlierTests.test_summary_generation_failure  s    
 *<d)B&,56Q,R)%;;FDKKNNS#++22 3 
 rAOO"") 1uzV{'2- #  	_'tD
 	$$&556  	_II]^	_s   0C) )DDr   r   r   r   c                    ddd|_         t        d      |_        t               }d|j                  _         ||j
                  _         t        j                  d| j                  j                        }t        j                  j                  | j                  |      }t        d      5 }d	|_         	 t        |d
d       ddd       y# t        $ r
}	Y d}	~	d}	~	ww xY w# 1 sw Y   yxY w)z)Test handling prompt preparation failure.rX   rY   r   zPrompt preparation failedr   r>   r?   r   r   r   r   r   N)r   r=  r  r   r   r   r   rA   r6   rB   r   r2   r5   r%   r   r   )
r8   r   r   r   r   r   r@   rG   mock_bazi_promptes
             r9   test_prompt_preparation_failurez8ConversationOutlierTests.test_prompt_preparation_failure  s     5;E^'_$*34O*P' {3@##00<  -%;;FDKKNNS#++22 3 
 >?CS,7))!-!'! @?   @?s*   'C0C	CCCCC&c                    t        j                  d| j                  j                        }t        j
                  j                  | j                  |      }|j                  }| j                  j                          | j                  t        j
                  j                  |      j                                |j                          | j                  |j                                y)z2Test conversation behavior when person is deleted.r>   r?   rT  N)r   rA   r6   rB   r   r2   r5   r%   deleterq  filterexistsr   r@  get_subject_objectr8   r@   rG   conversation_ids       r9   %test_conversation_with_deleted_personz>ConversationOutlierTests.test_conversation_with_deleted_person  s    %;;FDKKNNS#++22 3 

 '// 	 	,,333GNNPQ$$&,99;<r<   c                    t        j                  d| j                  j                        }t        j
                  j                  | j                  |      }t        j
                  j                  |dd      }|j                  }|j                          | j                  t        j
                  j                  |      j                                y)z3Test message behavior when conversation is deleted.r>   r?   r%   r   rS   rT  N)r   rA   r6   rB   r   r2   r5   r%   r   r  ry  r  r  )r8   r@   rG   rb   msg_ids        r9   &test_message_with_deleted_conversationz?ConversationOutlierTests.test_message_with_deleted_conversation  s    %;;FDKKNNS#++22 3 

 oo$$% % 
  	 	//6/:AACDr<   c                 t   t        j                  d| j                  j                        }t        j
                  j                  | j                  |      }|j                  }| j                  j                          | j                  t        j
                  j                  |      j                                y)z0Test conversation behavior when user is deleted.r>   r?   rT  N)r   rA   r6   rB   r   r2   r5   r%   r  ry  r  r  r  s       r9   #test_conversation_with_deleted_userz<ConversationOutlierTests.test_conversation_with_deleted_user  s    %;;FDKKNNS#++22 3 

 '// 			 	--444HOOQRr<   c                    ddd|_         d|_         t               }t        d      |j                  _        ||j
                  _         t        j                  d| j                  j                        }t        j                  j                  | j                  |      }| j                  t              5  t        |dd	
       ddd       y# 1 sw Y   yxY w)z"Test handling LLM service failure.rX   rY   r   PromptzLLM service errorr>   r?   r   r   r   N)r   r   r=  r   r  r   r   rA   r6   rB   r   r2   r5   r%   r   r   )r8   r   r   r   r   r   r@   rG   s           r9   test_llm_service_failurez1ConversationOutlierTests.test_llm_service_failure-  s     5;E^'_$+3( {2;<O2P##/0<  -%;;FDKKNNS#++22 3 

 y)%)# *))s   1C		Cc                    t        j                  d| j                  j                        }t        j
                  j                  | j                  |      }|j                         }t        d      D ]1  }t        j
                  j                  ||dz  dk(  rdndd| 	       3 |j                         }| j                  ||dz          y
)z5Test handling concurrent message sending (simulated).r>   r?   r   r]   r   r%   rV   r   rS   N)r   rA   r6   rB   r   r2   r5   r%   rE   r   r   rD   )r8   r@   rG   initial_countr   final_counts         r9   test_concurrent_message_sendingz8ConversationOutlierTests.test_concurrent_message_sendingG  s    %;;FDKKNNS#++22 3 
 %668 qAOO"") 1uzV{"1# #   #446ma&78r<   c                    t        j                  d| j                  j                        }t        j
                  j                  | j                  |      }t        d      5 }ddz  |_	        t        |j                  g d      }| j                  |d       | j                  |t               d	d	d	       y	# 1 sw Y   y	xY w)
z$Test handling very long BaZi prompt.r>   r?   r   r   i'  r   r   r   N)r   rA   r6   rB   r   r2   r5   r%   r   r   r   r   r   r   )r8   r@   rG   	mock_bazir   s        r9   test_very_long_bazi_promptz3ConversationOutlierTests.test_very_long_bazi_prompt]  s    %;;FDKKNNS#++22 3 

 >?9%1E%9I")"+"8"8%' &D tQ'!!$, @??s   !AB55B>N)rp   rq   rr   rs   r:   r  r  r   r   r  r  r  r  r  r  r  r  rt   r<   r9   r  r    s    1&JJ @A
67c:7 ; 8 B7: 45
01
>?
>? @ @ 2 6<=&E,S  45
01
>?
>? @ @ 2 6,9,-r<   r  )+rs   jsonunittest.mockr   r   r   r   django.testr   r   django.contrib.authr	   django.utilsr
   datetimer   r   rest_framework.testr   rest_frameworkr   	ai.modelsr   r   r   ai.utils.conversationr   r   r   r   r   r   bazi.modelsr   accounts.modelsr   r1   r   rv   r   ri  r  r  rt   r<   r9   <module>r     s     6 6 3 . !  ) ! @ @   'L,X L,^Fx FR
R	M8 R	Mjx,( x,v|> |>~h-x h-r<   