
    P1iKg                        d dl mZ d dlmZ d dlmZ d dlmZ d dlm	Z
 d dlmZ d dlmZ d dlmZ d d	lmZ  G d
 de      Zy)    )annotations)TestCase)get_user_modelreverse)timezone)settings)patch)Person)GroupRelationc                      e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
d	 Zd
 Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zy)PersonRelationsAPIExtendedTestszHExtended API tests for person relations covering all missing test cases.c           	        t               }|j                  j                  ddd      | _        | j                  j                  | j                         ddlm} t        j                  j                  dd |d	d
d
      | j                  d      | _
        | j                  j                          | j                  j                          y )N13900000000xzu@example.comphonepasswordemailr   dateownerMi     T)namegender
birth_date
created_byr   )r   objectscreate_useruserclientforce_logindatetimer   r   creater   calculate_bazisave)selfUserr   s      N/home/cursorai/projects/iching/api/tests/test_person_relations_api_extended.pysetUpz%PersonRelationsAPIExtendedTests.setUp   s    LL,,=3Ve,f			*!^^**dAq1Adii_c + 

 	

!!#

    c           	        ddl m} t        j                  j	                  dd |ddd      | j
                        }|j                          |j                          t        j                  j	                  dd |d	dd      | j
                        }|j                          |j                          d
| j
                  _        | j
                  j                  dg       |j                          ddl
m} |j                         5  	 ddd       | j
                  j                          | j                  | j
                  j                  g d       y# 1 sw Y   LxY w)z@Test that deletion of bazi.Person triggers full group recompute.r   r   p1r     r   r   r   r   r   p2  	completedgroup_relations_stateupdate_fields)transactionN)
processingidler3   )r$   r   r   r   r%   r!   r&   r'   r4   delete	django.dbr7   atomicrefresh_from_dbassertIn)r(   r   r.   r1   r7   s        r*   -test_person_deletion_triggers_group_recomputezMPersonRelationsAPIExtendedTests.test_person_deletion_triggers_group_recompute   s   !^^""cd4A.>499 # 
 	
	^^""cd4A.>499 # 
 	
	 +6		'		&=%>? 			 	*! " 			!!# 	dii557Z[ "!s   EEc           	     4   ddl m} t        j                  j	                  dd |ddd      | j
                        }|j                          |j                          d| j
                  _        | j
                  j                  d	g
       t        d      }| j                  j                  |      }| j                  |j                  d       | j                  |j                         j                  d      d       ddlm}  |d| j
                  j"                         | j                  j                  |      }| j                  |j                  d       |j                         }| j                  |j                  d      d       | j%                  d|       y)zPTest initial idle state, first API request sets processing, later returns ready.r   r   r.   r   r/   r   r0   r9   r4   r5   api:bazi-person-relations   statusr8   call_commandrecalc_bazi_relationsr!   readyresultsN)r$   r   r   r   r%   r!   r&   r'   r4   r   r"   getassertEqualstatus_codejsondjango.core.managementrE   idr>   )r(   r   r.   urlresp1rE   resp2datas           r*   5test_initial_idle_first_request_processing_then_readyzUPersonRelationsAPIExtendedTests.test_initial_idle_first_request_processing_then_ready@   s9   !^^""cd4A.>499 # 
 	
	 +1		'		&=%>?12 $**C0))(3\B 	8,499<<@ $**C0zz|(+W5i&r,   c                ~   t               }|j                  j                  | j                  j                        }d|_        t        j                         t        j                  d      z
  |_	        |j                  ddg       t        d      }| j                  j                  |      }| j                  |j                  d	       |j                         }| j                  |j                  d
      d       | j!                  d|       d|_        t        j                         t        j                  d      z
  |_	        |j                  ddg       | j                  j                  |      }| j                  |j                  d	       |j                         }| j                  |j                  d
      d       y)z+Test error state and retry after 5 minutes.rO   error   )minutesr4   group_relations_error_atr5   rA   rB   rC   retry_after_seconds   r8   N)r   r   rJ   r!   rO   r4   dj_tznow	timedeltarZ   r'   r   r"   rK   rL   rM   r>   )r(   r)   urP   resprS   rR   data2s           r*   &test_error_state_retry_after_5_minuteszFPersonRelationsAPIExtendedTests.test_error_state_retry_after_5_minutes`   sQ   LL		- #*%*YY[5??13M%M"	57QRS12{{s#))3/yy{(+W5+T2 #*%*YY[5??13M%M"	57QRS$**C0

8,l;r,   c                (   t               }|j                  j                  | j                  j                        }d|_        t        j                         t        j                  d      z
  |_	        |j                  ddg       t        d      5 }t        j                  t        d	d
      5  ddlm}  |d       |j!                          |j"                  }| j%                  d
|j&                  d          | j)                  |j&                  d   d       | j%                  d| j                  j                   |j&                  d          | j%                  d|j&                  d          ddd       ddd       y# 1 sw Y   xY w# 1 sw Y   yxY w)zDTest that email is sent to admin (TECH_CONTACT) when timeout occurs.rV   r8   X  secondsr4   group_relations_started_atr5   @main.management.commands.scan_group_relations_timeouts.send_mailTECH_CONTACTadmin@example.comr   rD   scan_group_relations_timeoutsrecipient_listsubjectzBaZi group relations timeoutzUser messagezexceeded timeoutN)r   r   rJ   r!   rO   r4   r]   r^   r_   rh   r'   r
   objectr	   rN   rE   assert_called_once	call_argsr>   kwargsrK   r(   r)   r`   mock_send_mailrE   rr   s         r*   #test_email_sent_to_admin_on_timeoutzCPersonRelationsAPIExtendedTests.test_email_sent_to_admin_on_timeout{   sA    LL		-".',yy{U__S5Q'Q$	57STU UVZhh8KL?<= 113*44	193C3CDT3UV  !1!1)!<>\]diill^4i6F6Fy6QR0)2B2B92MN M WVLL WVs%   F-B>E<+F<F	FFc                J   t               }|j                  j                  | j                  j                        }d|_        t        j                         t        j                  d      z
  |_	        |j                  ddg       t        d      5 }t        j                  t        d	d
      5  t        j                  t        dd
      5  ddlm}  |d       |j!                          d
d
d
       d
d
d
       d
d
d
       y
# 1 sw Y   xY w# 1 sw Y   xY w# 1 sw Y   y
xY w)zNTest that management command doesn't send email when no contact is configured.rV   r8   re   rf   r4   rh   r5   ri   rj   NCONTACT_EMAILr   rD   rl   )r   r   rJ   r!   rO   r4   r]   r^   r_   rh   r'   r
   rp   r	   rN   rE   assert_not_calledr(   r)   r`   ru   rE   s        r*   6test_management_command_email_not_sent_when_no_contactzVPersonRelationsAPIExtendedTests.test_management_command_email_not_sent_when_no_contact   s    LL		-".',yy{U__S5Q'Q$	57STU UVZhh=\\(OTBC !@A #446 C > WVBB >= WVs<   D-D	D(D0DD
DD	DD"c                   t               }|j                  j                  | j                  j                        }d|_        t        j                         t        j                  d      z
  |_	        |j                  ddg       t        d      5 }t        j                  t        d	d
      5  t        j                  t        dd      5  ddlm}  |d       |j!                          |j"                  }| j%                  d|j&                  d          d
d
d
       d
d
d
       d
d
d
       y
# 1 sw Y   xY w# 1 sw Y   xY w# 1 sw Y   y
xY w)z9Test that management command falls back to CONTACT_EMAIL.rV   r8   re   rf   r4   rh   r5   ri   rj   Nrx   zfallback@example.comr   rD   rl   rm   )r   r   rJ   r!   rO   r4   r]   r^   r_   rh   r'   r
   rp   r	   rN   rE   rq   rr   r>   rs   rt   s         r*   7test_management_command_email_fallback_to_contact_emailzWPersonRelationsAPIExtendedTests.test_management_command_email_fallback_to_contact_email   s    LL		-".',yy{U__S5Q'Q$	57STU UVZhh=\\(O=STC !@A #557 . 8 8IMM"8):J:JK[:\] U > WVTT >= WVs=   E-D8	A
D,D8E,D51D88E	=EEc                b   t               }|j                  j                  | j                  j                        }d|_        t        j                         t        j                  d      z
  |_	        |j                  ddg       t        d      5 }t        d	      |_        t        j                  t        d
d      5  ddlm}  |d       |j%                          | j'                  |j
                  d       |j)                          ddd       ddd       y# 1 sw Y   xY w# 1 sw Y   yxY w)zATest that management command handles email exceptions gracefully.rV   r8   re   rf   r4   rh   r5   ri   zSMTP server downrj   rk   r   rD   rl   rW   N)r   r   rJ   r!   rO   r4   r]   r^   r_   rh   r'   r
   	Exceptionside_effectrp   r	   rN   rE   r=   rK   rq   rz   s        r*   0test_management_command_email_exception_handlingzPPersonRelationsAPIExtendedTests.test_management_command_email_exception_handling   s    LL		-".',yy{U__S5Q'Q$	57STU UVZh)23E)FN&h8KL?<= !!#  !8!8'B 113 M WVLL WVs%   ,D%=ADD%D"	D%%D.c           	     0   ddl m} t        j                  j	                  dd |ddd      | j
                        }|j                          |j                          d| j
                  _        t        j                         | j
                  _        | j
                  j                  d	d
g       t        d      }| j                  j                  |      }| j                  j                  |      }| j                  j                  |      }| j                  |j!                         j                  d      d       | j                  |j!                         j                  d      d       | j                  |j!                         j                  d      d       y)z=Test that no second job is spawned while state is processing.r   r   testr     r   r0   r8   r4   rh   r5   rA   rC   N)r$   r   r   r   r%   r!   r&   r'   r4   r]   r^   rh   r   r"   rJ   rK   rM   )r(   r   prP   rQ   rR   resp3s          r*   test_concurrent_job_preventionz>PersonRelationsAPIExtendedTests.test_concurrent_job_prevention   s*   !NN!!T1a0@TYY " 
 	
	 +7		'/4yy{		,		&=?[%\]12 $$$))(3\B))(3\B))(3\Br,   c           	     r   ddl m} t        j                  j	                  dd |ddd      | j
                        }|j                          |j                          d| j
                  _        | j
                  j                  d	g
       t               }|j                  j                  | j
                  j                        j                  d       ddlm}  |d| j
                  j                         | j
                  j                          | j!                  | j
                  j                  d       y)zUTest that finishing job uses conditional completion and doesn't overwrite idle state.r   r   r   r   r   r   r0   r8   r4   r5   rV   r9   )r4   rD   rF   rG   N)r$   r   r   r   r%   r!   r&   r'   r4   r   filterrO   updaterN   rE   r=   rK   )r(   r   r   r)   rE   s        r*   .test_conditional_completion_prevents_overwritezNPersonRelationsAPIExtendedTests.test_conditional_completion_prevents_overwrite   s    ! NN!!T1a0@TYY " 
 	
	 +7		'		&=%>? tyy||,33&3Q 	8,499<<@ 			!!#88&Ar,   c           	     N   ddl m} t        j                  j	                  dd |ddd      | j
                        }|j                          |j                          t        j                  j	                  dd |d	dd      | j
                        }|j                          |j                          t        j                  j	                  | j
                  ||d
       | j                  t        j                  j                  | j
                        j                         d       t        j                  j                  | j
                        j                          | j                  t        j                  j                  | j
                        j                         d       y)z;Test that deleting all persons removes all group relations.r   r   r.   r   r/   r   r0   r1   r2   sanhe
owner_userperson1person2relation_type)r   )r   N)r$   r   r   r   r%   r!   r&   r'   r   rK   r   countr:   )r(   r   r.   r1   s       r*   6test_group_relation_table_integrity_delete_all_personszVPersonRelationsAPIExtendedTests.test_group_relation_table_integrity_delete_all_persons  sG   ! ^^""cd4A.>499 # 
 	
	^^""cd4A.>499 # 
 	
	 	$$yy"b 	% 	

 	..555KQQSUVW 	3::< 	..555KQQSUVWr,   c           	        ddl m} t        j                  j	                  dd |ddd      | j
                        }|j                          |j                          t        j                  j	                  dd |d	dd      | j
                        }|j                          |j                          t        j                  j	                  d
d |ddd      | j
                        }|j                          |j                          t        j                  j	                  | j
                  ||d      }t        j                  j	                  | j
                  ||d      }|j                          | j                  t        j                  j                  |j                  |j                  g      j                         d       | j                  t        j                  j                  |j                        j                                | j                  t        j                  j                  |j                        j                                y)z<Test that deleting one person removes related group records.r   r   r.   r   r/   r   r0   r1   r2   p3r   r   r   sanxing)id__inrV   N)r$   r   r   r   r%   r!   r&   r'   r   r:   rK   r   rO   r   
assertTrueexists)r(   r   r.   r1   r   gr1gr2s          r*   /test_group_relation_integrity_delete_one_personzOPersonRelationsAPIExtendedTests.test_group_relation_integrity_delete_one_person%  s   ! ^^""cd4A.>499 # 
 	
	^^""cd4A.>499 # 
 	
	^^""cd4A.>499 # 
 	
	 ##**yy"b + 
 ##**yy"b	 + 

 			 	..55cffcff=M5NTTVXYZ 	---7>>@A---7>>@Ar,   c           	        ddl m}  |ddd      | j                  _        | j                  j	                          | j                  j                          t        j                  j                  dd |ddd      | j                  	      }|j	                          |j                          t        j                  j                  d
d |ddd      | j                  	      }|j	                          |j                          ddl
m}  |d| j                  j                  d       t        j                  j                  | j                  d      }| j                  |j!                         d       |j#                         }|j$                  j                  |j&                  j                  h}|j                  |j                  h}| j                  ||       y)uK   Test that adding a new person that forms valid 三合 creates group record.r   r     r   rX   r.   r      r0   r1      rD   rF   Tr!   forcer   r   r   Nr$   r   r   r   r&   r'   r   r   r%   r!   rN   rE   rO   r   r   rK   r   firstr   r   )	r(   r   r.   r1   rE   sanhe_relationsrelation
person_idsexpected_idss	            r*   )test_new_person_creates_valid_group_sanhezIPersonRelationsAPIExtendedTests.test_new_person_creates_valid_group_sanheN  sv   ! !%T1a 0



!!#

 ^^""cd4B.?DII # 
 	
	 ^^""cd4A.>499 # 
 	
	 	8,499<<tL (//66yy 7 
 	..0!4"((*&&))8+;+;+>+>?
ruu~\2r,   c           	        ddl m}  |ddd      | j                  _        | j                  j	                          | j                  j                          t        j                  j                  dd |ddd      | j                  	      }|j	                          |j                          t        j                  j                  d
d |ddd      | j                  	      }|j	                          |j                          ddl
m}  |d| j                  j                  d       t        j                  j                  | j                  d      }| j                  |j!                         d       |j#                         }|j$                  j                  |j&                  j                  h}|j                  |j                  h}| j                  ||       y)uK   Test that adding a new person that forms valid 三刑 creates group record.r   r   r   r   r\   r.   r   	   r0   r1   r   rD   rF   Tr   r   r   Nr   )	r(   r   r.   r1   rE   sanxing_relationsr   r   r   s	            r*   +test_new_person_creates_valid_group_sanxingzKPersonRelationsAPIExtendedTests.test_new_person_creates_valid_group_sanxingw  sx   !
 !%T1a 0



!!#

 ^^""cd4A.>499 # 
 	
	 ^^""cd4B.?DII # 
 	
	 	8,499<<tL *1188yy	 9 
 	*002A6$**,&&))8+;+;+>+>?
ruu~\2r,   c           	        ddl m} t        j                  j	                  dd |ddd      | j
                        }dddd	i| j                  _        | j                  j                  d
g       dddd	i|_        |j                  d
g       ddl	m
}  |d| j
                  j                  d       t        d      }| j                  j                  |      }| j                  |j                   d       |j#                         }d}|j                  dg       D ]$  }|j                  d      |j                  k(  s"|} n | j%                  |       | j'                  d|       | j'                  d|       |d   | j)                  |d   t*               |d   | j)                  |d   t*               | j-                  d|       | j-                  d|       y)zKTest that pairwise listing/detail return only arrays, no counts in payload.r   r   test_personr   r   r   r0   daygodearthbazi_resultr5   rD   rF   Tr   zapi:bazi-listrB   NrI   rO   relation_goodrelation_badrelation_good_countrelation_bad_count)r$   r   r   r   r%   r!   r   r   r'   rN   rE   rO   r   r"   rJ   rK   rL   rM   assertIsNotNoner>   assertIsInstancelistassertNotIn)	r(   r   r   rE   rP   ra   rS   person_dataresults	            r*   -test_pairwise_data_shape_no_counts_in_payloadzMPersonRelationsAPIExtendedTests.test_pairwise_data_shape_no_counts_in_payload  s   !NN!!stD!Q7GTXT]T] " 
 #(Q)?!@



}o6A 67	m_- 	8,499<<tL o&{{s#))3/yy{ hhy"-Fzz$144'$ .
 	[)o{3nk2 '3!!+o">E~&2!!+n"=tD 	.<-{;r,   c           	        ddl m} t        j                  j	                  dd |ddd      | j
                        }|j                          |j                          | j                  j                          | j                  j                          dd	l	m
}  |d
| j
                  j                  d       ddlm}  |dd|j                  i      }| j                  j                  | j
                         | j                  j!                  |      }| j#                  |j$                  d       |j'                         }|j!                  dg       |j!                  dg       z   }|D ]  }	| j)                  d|	       | j)                  d|	       | j)                  |	d   ddg       |	d   dk(  r| j)                  d|	       | j+                  |	d   t,               | j)                  |	d   g d       |	d   dk(  r*| j)                  d|	       | j)                  |	d   g d       | j/                  d|	       |	d   dk(  s| j)                  d|	       | j+                  |	d   t,                y)z7Test that each reason item conforms to expected schema.r   r   r   r   r   r      r0   rD   rF   Tr   r   zapi:bazi-detailpk)rs   rB   r   r   tbyrscr   r         rX      r   5e)r   r   r   r   rX   iN)r$   r   r   r   r%   r!   r&   r'   r   rN   rE   rO   django.urlsr   r"   r#   rJ   rK   rL   rM   r>   r   intr   )
r(   r   r   rE   r   rP   ra   rS   all_reasonsreasons
             r*   test_reason_schema_conformancez>PersonRelationsAPIExtendedTests.test_reason_schema_conformance  s   ! NN!!stD!R7HUYU^U^ " 
 	
	 	

!!#

 	8,499<<tL 	('qtt= 			*{{s#))3/yy{hh3dhh~r6RR!FMM#v&MM$'MM&+Sz2c{c!c6*%%fSk37fSk+=> #;!#MM$/MM&,@$$T62#c6*%%fSk37- "r,   c           
        ddl m} g d}|D ]  \  }}}t        j                  j	                  d| d |ddd      | j
                        }|d	k(  r#d
dddi| j                  _        d
dddi|_        n"d
d|di| j                  _        d
d|di|_        | j                  j                  dg       |j                  dg        ddl	m
}  |d| j
                  j                  d       d}| j                  j                  |      }	|	j                         }
|
j                  dg       D ]X  }|j                  dd      r|j                  dg       D ].  }|j                  d      dk(  s| j                  |d   g d       0 Z y)z;Test that integer c mapping is consistent across endpoints.r   r   ))r   r   r   )r   r   r   )r   r\   r   test_r   r   r   r0   r   r   r   r   r   r5   rD   rF   Tr   
/api/bazi/rI   r   Fr   r   r   r   r   N)r$   r   r   r   r%   r!   r   r   r'   rN   rE   rO   r"   rJ   rM   r>   )r(   r   relationshipsowner_eperson_comboexpected_coder   rE   rP   ra   rS   r   r   s                r*   #test_relationship_codes_consistencyzCPersonRelationsAPIExtendedTests.test_relationship_codes_consistency  sq   !
 5B0G\=%%]O,ST$PQSTEUbfbkbk & A !*/Q1G)H

&!&A(> ?*/W1M)N

&!&L(I JJJOO=/O:FF-F1 5B  	8,499<<tL {{s#yy{hhy"-F::gu-$jj"=Fzz##-fSk3EF > .r,   c           	        ddl m} t        j                  j	                  dd |ddd      | j
                        }|j                          |j                          d| j
                  _        | j
                  j                  d	g
       d|_	        |j                          | j
                  j                          | j                  | j
                  j                  d       y)zATest that edits to non-pillar fields don't trigger recomputation.r   r   original_namer   r   r   r0   r3   r4   r5   new_nameN)r$   r   r   r   r%   r!   r&   r'   r4   r   r=   rK   )r(   r   r   s      r*   %test_non_pillar_field_edits_no_recalczEPersonRelationsAPIExtendedTests.test_non_pillar_field_edits_no_recalc,  s    !NN!! dAq9IVZV_V_ " 
 	
	 +6		'		&=%>? 	 			!!#88+Fr,   c           	     d   ddl m} t               }|j                  j	                  ddd      }t
        j                  j                  dd |d	d
d
      |      }|j                          |j                          d}| j                  j                  |      }|j                         }|j                  dg       D cg c]  }|d   	 }	}| j                  |j                  |	       d|j                   d}| j                  j                  |      }| j                  |j                  d       yc c}w )z-Test that User A cannot access User B's data.r   r   13900000001r   zu2@example.comr   user2_personr   r   r   r0   r   rI   rO   /i  N)r$   r   r   r   r    r   r%   r&   r'   r"   rJ   rM   r   rO   rK   rL   )
r(   r   r)   user2r1   rP   ra   rS   r   r   s
             r*   test_user_isolationz3PersonRelationsAPIExtendedTests.test_user_isolationB  s   ! ((}sRb(c ^^""T1a8HUZ # 
 	
	 {{s#yy{'+xx	2'>?'>!ag'>
?
+ 255'#{{s#))3/ @s   ;D-c           	     4   ddl m} | j                  j                          t        j
                  j                  dd |ddd      | j                        }|j                          |j                          ddl
m}  |d	| j                  j                  d
       |j                          | j                  |j                         | j                  |j                          | j#                  |j$                  d       | j#                  |j&                  d       y)zCTest that without owner record, no relationship data is calculated.r   r   regular_personr   r   r   r0   rD   rF   Tr   N)r$   r   r   r:   r   r   r%   r!   r&   r'   rN   rE   rO   r=   assertIsNoner   r   rK   r   r   )r(   r   r   rE   s       r*   )test_no_owner_record_no_relationship_datazIPersonRelationsAPIExtendedTests.test_no_owner_record_no_relationship_data^  s    !

 NN!!!#$tQ:JW[W`W` " 
 	
	 	8,499<<tL 	
!//*!..)..2--q1r,   N)__name__
__module____qualname____doc__r+   r?   rT   rc   rv   r{   r}   r   r   r   r   r   r   r   r   r   r   r   r   r    r,   r*   r   r      sz    R \D'@<6O27$^(4.C4B6X>'BR'3R&3P*<X78r&GPG,082r,   r   N)
__future__r   django.testr   django.contrib.authr   r   r   django.utilsr   r]   django.confr	   unittest.mockr
   bazi.modelsr   bazi.models_groupr   r   r   r,   r*   <module>r      s.    "   .  *     +f	2h f	2r,   