
    BkJiW                     v    d Z ddlmZ ddlmZ ddlmZmZmZm	Z	m
Z
 ddlmZ ddlmZ ddlmZ  G d d	e      Zy
)z5Integration tests for hook system with WalletService.    )Decimal)TestCase)WalletServiceWalletRepositoryHookTypeclear_hooksregister_hook)HookContextHookRejectionError)TestUserc                       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d Zd Zy)TestWalletServiceWithHooksz1Test WalletService operations with hooks enabled.c                 >   t         j                  j                  dd      | _        t         j                  j                  dd      | _        dddd| _        t        t         | j
                  	      | _        t        | j                  d
      | _	        t                y)zSet up test data.user1zuser1@test.com)usernameemailuser2zuser2@test.com   r   )cashcredit_balancereward_points
user_modelpoint_typesTenable_hooksN)r   objectscreater   r   r   r   
repositoryr   servicer   selfs    K/home/cursorai/projects/django-wallet-utils/tests/test_hooks_integration.pysetUpz TestWalletServiceWithHooks.setUp   s    %%,,gEU,V
%%,,gEU,V


 +((
 %T__4H 	    c                     t                y)zClean up after tests.N)r   r"   s    r$   tearDownz#TestWalletServiceWithHooks.tearDown'   s    r&   c                    g dt         dt        ffd}t        dt        j                  |dd       | j
                  j                  | j                  j                  dt        d	      d
      }| j                  |j                         | j                  |j                         | j                  |j                         | j!                  dg       y)z5Test add_point with PRE hook that allows transaction.contextreturnc                 V    j                  d       | j                  t        d      k  S )Npre_hook1000appendamountr   r*   executeds    r$   check_amountzUTestWalletServiceWithHooks.test_add_point_with_pre_hook_success.<locals>.check_amount3   s"    OOJ'>>GFO33r&   r4   addd   )name	hook_typecallback	operationpriorityr   100Test adduser_id
point_typer1   remarksr-   N)r
   boolr	   r   PREr!   	add_pointr   idr   
assertTruesuccessassertIsNotNonetransaction_idassertIsNone
error_codeassertEqual)r#   r4   resultr3   s      @r$   $test_add_point_with_pre_hook_successz?TestWalletServiceWithHooks.test_add_point_with_pre_hook_success/   s    	4+ 	4$ 	4
 	ll!	
 ''JJMM5>	 ( 
 	'V223&++,J<0r&   c                    dt         dt        fd}t        dt        j                  |d       | j
                  j                  | j                  j                  dt        d      d	
      }| j                  |j                         | j                  |j                         | j                  d|j                         | j                   j#                  | j                  j                  d      }| j%                  |t        d             y)z=Test add_point with PRE hook that rejects by returning False.r*   r+   c                 6    | j                   t        d      kD  ryy)N500FT)r1   r   r*   s    r$   reject_large_amountszeTestWalletServiceWithHooks.test_add_point_with_pre_hook_rejection_false.<locals>.reject_large_amountsN   s    ~~.r&   reject_larger5   r7   r8   r9   r:   r   600zLarge amountr>   HOOK_REJECTED_REJECT_LARGE0N)r
   rB   r	   r   rC   r!   rD   r   rE   r   assertFalserG   rJ   rI   assertInrK   r    get_user_balancerL   )r#   rS   rM   balances       r$   ,test_add_point_with_pre_hook_rejection_falsezGTestWalletServiceWithHooks.test_add_point_with_pre_hook_rejection_falseL   s    	+ 	$ 	 	ll)		
 ''JJMM5>"	 ( 
 	(&//02F4E4EF//224::==&I'#,/r&   c                    dt         dt        fd}t        dt        j                  |d       | j
                  j                  | j                  j                  dt        d      d	
      }| j                  |j                         | j                  |j                  d       | j                  |j                  d       | j                  |j                  d   d       | j                  |j                  d   d       y)zHTest add_point with PRE hook that rejects by raising HookRejectionError.r*   r+   c                 |    | j                   t        d      kD  r$t        dddt        | j                         d      y)NrQ   DAILY_LIMIT_EXCEEDED Daily transaction limit exceeded  )limit	requestedrK   messagedetailsTr1   r   r   floatrR   s    r$   check_daily_limitzfTestWalletServiceWithHooks.test_add_point_with_pre_hook_rejection_exception.<locals>.check_daily_limitk   s;    ~~.(5>&)gnn8MN 
 r&   daily_limitr5   rU   r   rV   z
Over limitr>   r`   ra   rc   rb   rd   g     @N)r
   rB   r	   r   rC   r!   rD   r   rE   r   rY   rG   rL   rK   error_messageerror_details)r#   rj   rM   s      r$   0test_add_point_with_pre_hook_rejection_exceptionzKTestWalletServiceWithHooks.test_add_point_with_pre_hook_rejection_exceptioni   s    	{ 	t 	 	ll&		
 ''JJMM5> 	 ( 
 	(**,BC--/QR--g6<--k:EBr&   c                     g dt         ddf fd}t        dt        j                  |d        j                  j                   j                  j                  dt        d	      d
      } j                  |j                          j                  |j                          j                  |j                          j                  dg       y)z9Test add_point with POST hook that executes successfully.r*   r+   Nc                     j                  d       | j                  j                  d      }j                  |       y )N	post_hookrI   )r0   metadatagetrH   )r*   tx_idr3   r#   s     r$   log_transactionzYTestWalletServiceWithHooks.test_add_point_with_post_hook_success.<locals>.log_transaction   s4    OOK($$(()9:E  'r&   log_txr5   rU   r   r<   r=   r>   rq   )r
   r	   r   POSTr!   rD   r   rE   r   rF   rG   rH   rI   rJ   post_hook_errorsrL   )r#   ru   rM   r3   s   `  @r$   %test_add_point_with_post_hook_successz@TestWalletServiceWithHooks.test_add_point_with_post_hook_success   s    	([ 	(T 	( 	mm$		
 ''JJMM5>	 ( 
 	'V223&112K=1r&   c                 ^   dt         ddfd}t        dt        j                  |d       | j                  j                  | j                  j                  dt        d	      d
      }| j                  |j                         | j                  |j                         | j                  |j                         | j                  t        |j                        d       | j                  |j                  d   j                   d       | j                  |j                  d   j"                  d       y)zFTest add_point with POST hook that fails - transaction still succeeds.r*   r+   Nc                     t        d      )NzPOST hook failed
ValueErrorrR   s    r$   failing_post_hookzYTestWalletServiceWithHooks.test_add_point_with_post_hook_error.<locals>.failing_post_hook   s    /00r&   failing_postr5   rU   r   r<   r=   r>      r   HOOK_EXECUTION_ERROR)r
   r	   r   rw   r!   rD   r   rE   r   rF   rG   rH   rI   rx   rL   len	hook_namerK   r#   r~   rM   s      r$   #test_add_point_with_post_hook_errorz>TestWalletServiceWithHooks.test_add_point_with_post_hook_error   s    	1{ 	1t 	1 	mm&		
 ''JJMM5>	 ( 
 	'V223 	V445V445q9003==~N003>>@VWr&   c                     g dt         dt        ffd}dt         dt        ffd}dt         dt        ffd}t        dt        j                  |dd	       t        d
t        j                  |dd	       t        dt        j                  |dd	       | j
                  j                  | j                  j                  dt        d      d      }| j                  |j                         | j                  g d       y)z>Test add_point with multiple hooks executed in priority order.r*   r+   c                 (    j                  d       y)Nlow_priorityTr0   r2   s    r$   hook_low_priorityzaTestWalletServiceWithHooks.test_add_point_with_multiple_hooks_priority.<locals>.hook_low_priority   s    OON+r&   c                 (    j                  d       y)Nhigh_priorityTr   r2   s    r$   hook_high_priorityzbTestWalletServiceWithHooks.test_add_point_with_multiple_hooks_priority.<locals>.hook_high_priority   s    OOO,r&   c                 (    j                  d       y)Nmedium_priorityTr   r2   s    r$   hook_medium_priorityzdTestWalletServiceWithHooks.test_add_point_with_multiple_hooks_priority.<locals>.hook_medium_priority   s    OO-.r&   lowr5   rb   r;   high
   mediumr6   r   r<   zTest priorityr>   )r   r   r   Nr
   rB   r	   r   rC   r!   rD   r   rE   r   rF   rG   rL   )r#   r   r   r   rM   r3   s        @r$   +test_add_point_with_multiple_hooks_priorityzFTestWalletServiceWithHooks.test_add_point_with_multiple_hooks_priority   s    	{ 	t 		 	 		+ 	$ 	
 	eX\\+<ecRfhll,>PRSh.BETWX''JJMM5>#	 ( 
 	'#WXr&   c                    | j                   j                  | j                  j                  dt	        d      d       g dt
        dt        ffd}t        dt        j                  |d	       | j                   j                  | j                  j                  dt	        d
      d      }| j                  |j                         | j                  dg       y)z8Test deduct_point with PRE hook that allows transaction.r   rQ   Initial balancer*   r+   c                 X    j                  d       | j                  | j                  k\  S )Nr-   )r0   current_balancer1   r2   s    r$   check_balancezYTestWalletServiceWithHooks.test_deduct_point_with_pre_hook_success.<locals>.check_balance   s$    OOJ'**gnn<<r&   r   deductrU   r<   Test deductr>   r-   N)r!   rD   r   rE   r   r
   rB   r	   r   rC   deduct_pointrF   rG   rL   )r#   r   rM   r3   s      @r$   'test_deduct_point_with_pre_hook_successzBTestWalletServiceWithHooks.test_deduct_point_with_pre_hook_success   s     	JJMM675>3D	
 	=; 	=4 	=
 	 ll"		
 **JJMM5>!	 + 
 	'J<0r&   c                 P   | j                   j                  | j                  j                  dt	        d      d       dt
        dt        fd}t        dt        j                  |d	       | j                   j                  | j                  j                  dt	        d
      d      }| j                  |j                         | j                  |j                  d       | j                  j!                  | j                  j                  d      }| j                  |t	        d             y)z9Test deduct_point with PRE hook that rejects transaction.r   rQ   r   r*   r+   c                 |    | j                   t        d      kD  r$t        dddt        | j                         d      y)N200AMOUNT_TOO_LARGEzDeduction amount too large   )maxrd   re   Trh   rR   s    r$   reject_large_deductionszeTestWalletServiceWithHooks.test_deduct_point_with_pre_hook_rejection.<locals>.reject_large_deductions  s;    ~~.(18$'eGNN6KL 
 r&   limit_deductionr   rU   300zLarge deductionr>   r   N)r!   rD   r   rE   r   r
   rB   r	   r   rC   r   rY   rG   rL   rK   r    r[   )r#   r   rM   r\   s       r$   )test_deduct_point_with_pre_hook_rejectionzDTestWalletServiceWithHooks.test_deduct_point_with_pre_hook_rejection  s     	JJMM675>3D	
	[ 	T 	 	"ll,		
 **JJMM5>%	 + 
 	(**,>?//224::==&I'%.1r&   c                     | j                   j                  | j                  j                  dt	        d      d      }| j                  |j                         | j                  |j                  d       | j                  |j                         y)zFTest deduct_point with insufficient balance returns TransactionResult.r   r<   Insufficientr>   INSUFFICIENT_BALANCEN)r!   r   r   rE   r   rY   rG   rL   rK   rH   rl   )r#   rM   s     r$   5test_deduct_point_insufficient_balance_returns_resultzPTestWalletServiceWithHooks.test_deduct_point_insufficient_balance_returns_result)  st     **JJMM5>"	 + 
 	(**,BCV112r&   c                    | j                   j                  | j                  j                  dt	        d      d       g dt
        ddffd}t        dt        j                  |d	
       | j                   j                  | j                  j                  dt	        d      d      }| j                  |j                         | j                  dg       y)z!Test deduct_point with POST hook.r   rQ   r   r*   r+   Nc                 (    j                  d       y )Nnotification_sentr   r2   s    r$   send_notificationzVTestWalletServiceWithHooks.test_deduct_point_with_post_hook.<locals>.send_notificationA  s    OO/0r&   notifyr   rU   r<   r   r>   r   )r!   rD   r   rE   r   r
   r	   r   rw   r   rF   rG   rL   )r#   r   rM   r3   s      @r$    test_deduct_point_with_post_hookz;TestWalletServiceWithHooks.test_deduct_point_with_post_hook8  s     	JJMM675>3D	
 	1{ 	1t 	1 	mm&		
 **JJMM5>!	 + 
 	'$7#89r&   c           	         | j                   j                  | j                  j                  dt	        d      d       g dt
        dt        ffd}t        dt        j                  |d	       | j                   j                  | j                  j                  d| j                  j                  dt	        d
      d      }| j                  |d          | j                  |j                  d             | j                  dg       y)z;Test transfer_points with PRE hook that allows transaction.r   rQ   r   r*   r+   c                 V    j                  d       | j                  t        d      k  S )Nr-   r   r/   r2   s    r$   check_transfer_limitz\TestWalletServiceWithHooks.test_transfer_with_pre_hook_success.<locals>.check_transfer_limitc  s"    OOJ'>>GEN22r&   transfer_limittransferrU   r   Test transferfrom_user_idfrom_point_type
to_user_idto_point_typer1   rA   rG   errorr-   N)r!   rD   r   rE   r   r
   rB   r	   r   rC   transfer_pointsr   rF   rJ   rs   rL   )r#   r   rM   r3   s      @r$   #test_transfer_with_pre_hook_successz>TestWalletServiceWithHooks.test_transfer_with_pre_hook_successZ  s     	JJMM675>3D	
 	3+ 	3$ 	3
 	!ll) 		
 --"zz}} 5># . 
 	y)*&**W-.J<0r&   c           	         | j                   j                  | j                  j                  dt	        d      d       dt
        dt        fd}t        dt        j                  |d	       | j                   j                  | j                  j                  d| j                  j                  dt	        d
      d      }| j                  |d          | j                  |d   d   d       | j                  j                  | j                  j                  d      }| j                  j                  | j                  j                  d      }| j                  |t	        d             | j                  |t	        d             y)z<Test transfer_points with PRE hook that rejects transaction.r   rQ   r   r*   r+   c                 T    | j                   t        d      kD  rt        ddddi      y)N400SUSPICIOUS_TRANSFERz%Transfer amount flagged as suspiciousmax_safei  re   T)r1   r   r   rR   s    r$   block_suspicious_transferzcTestWalletServiceWithHooks.test_transfer_with_pre_hook_rejection.<locals>.block_suspicious_transfer  s2    ~~.(4C'- 
 r&   fraud_checkr   rU   450zSuspicious transferr   rG   r   coder   rX   N)r!   rD   r   rE   r   r
   rB   r	   r   rC   r   r   rY   rL   r    r[   )r#   r   rM   balance1balance2s        r$   %test_transfer_with_pre_hook_rejectionz@TestWalletServiceWithHooks.test_transfer_with_pre_hook_rejection|  s-    	JJMM675>3D	
	{ 	t 	 	ll. 		
 --"zz}} 5>) . 
 		*+02GH??33DJJMM6J??33DJJMM6J75>273<0r&   c           	           j                   j                   j                  j                  dt	        d      d       g dt
        ddf fd}t        dt        j                  |d	
        j                   j                   j                  j                  d j                  j                  dt	        d      d      } j                  |d           j                  dg       y)z$Test transfer_points with POST hook.r   rQ   r   r*   r+   Nc                     j                  d       j                  | j                  d       j                  | j                  j                  j
                         y )Nloggedr   )r0   rL   r:   r   r   rE   )r*   r3   r#   s    r$   log_transferzMTestWalletServiceWithHooks.test_transfer_with_post_hook.<locals>.log_transfer  sC    OOH%W..
;W//?r&   r   r   rU   r   r   r   rG   r   )r!   rD   r   rE   r   r
   r	   r   rw   r   r   rF   rL   )r#   r   rM   r3   s   `  @r$   test_transfer_with_post_hookz7TestWalletServiceWithHooks.test_transfer_with_post_hook  s     	JJMM675>3D	
 	@+ 	@$ 	@ 	mm! 		
 --"zz}} 5># . 
 	y)*H:.r&   c           	      .   | j                   j                  | j                  j                  dt	        d      d       dt
        ddfd}t        dt        j                  |d	
       | j                   j                  | j                  j                  d| j                  j                  dt	        d      d      }| j                  |d          | j                  d|       | j                  t        |d         d       | j                  |d   d   d   d       y)zGTest transfer_points with POST hook error - transaction still succeeds.r   rQ   r   r*   r+   Nc                     t        d      )NzFailed to send notificationr|   rR   s    r$   r~   zXTestWalletServiceWithHooks.test_transfer_with_post_hook_error.<locals>.failing_post_hook  s    :;;r&   notify_failedr   rU   r   r   r   rG   warningsr   r   hook)r!   rD   r   rE   r   r
   r	   r   rw   r   r   rF   rZ   rL   r   r   s      r$   "test_transfer_with_post_hook_errorz=TestWalletServiceWithHooks.test_transfer_with_post_hook_error  s     	JJMM675>3D	
	<{ 	<t 	< 	 mm& 		
 --"zz}} 5># . 
 	y)* 	j&)VJ/0!4
+A.v6Hr&   c                     g dt         dt        ffd}dt         dt        f fd}t        dt        j                  |dd       t        d	t        j                  |dd
        j
                  j                   j                  j                  dt        d      d      } j                  |j                          j                  dd	g       y)z,Test that hooks can share data via metadata.r*   r+   c                 F    d| j                   d<   j                  d       y)Nprocessed_by_hook1
hook1_datahook1T)rr   r0   r2   s    r$   r   zQTestWalletServiceWithHooks.test_hooks_can_communicate_via_metadata.<locals>.hook1  s"    -AG\*OOG$r&   c                     | j                   j                  d      }j                  |d       j                  d       y)Nr   r   hook2T)rr   rs   rL   r0   )r*   datar3   r#   s     r$   r   zQTestWalletServiceWithHooks.test_hooks_can_communicate_via_metadata.<locals>.hook2  s9    ##''5DT#78OOG$r&   r   r5   r   r   r      r   r<   zTest metadataNr   )r#   r   r   rM   r3   s   `   @r$   'test_hooks_can_communicate_via_metadatazBTestWalletServiceWithHooks.test_hooks_can_communicate_via_metadata  s    	; 	4 	
	; 	4 	 	gx||UEBGgx||UEBG''JJMM675>?
 	'GW#56r&   c           	          g dt         dt        ffd}t        dt        j                  |d       | j
                  j                  | j                  j                  dt        d      d	       | j
                  j                  | j                  j                  dt        d
      d       | j
                  j                  | j                  j                  | j                  j                  ddt        d      d      }| j                  g d       y)z5Test that global hooks ('*') apply to all operations.r*   r+   c                 <    j                  | j                         y)NT)r0   r:   r2   s    r$   global_hookzZTestWalletServiceWithHooks.test_global_hook_applies_to_all_operations.<locals>.global_hook  s    OOG--.r&   global*rU   r   r<   r=   50r   20r   )r   r   r   r   r1   rA   )r5   r   r   N)r
   rB   r	   r   rC   r!   rD   r   rE   r   r   r   r   rL   )r#   r   rM   r3   s      @r$   *test_global_hook_applies_to_all_operationszETestWalletServiceWithHooks.test_global_hook_applies_to_all_operations  s    	 	 	 	ll 		
 	JJMM675>:	

 	!!JJMM674=-	

 --zz}}" 4=# . 
 	#@Ar&   c                 ^   t        t        | j                        }t        |d      }dt        dt
        fd}t        dt        j                  |d       |j                  | j                  j                  d	t        d
      d      }| j                  |t               | j                  |d       y)zJTest that with hooks disabled, service returns int (backwards compatible).r   Fr   r*   r+   c                     t        d      )NzThis should not be called)	ExceptionrR   s    r$   should_not_runzjTestWalletServiceWithHooks.test_service_with_hooks_disabled_returns_transaction_id.<locals>.should_not_run>  s    788r&   unusedr5   r   r<   Testr   N)r   r   r   r   r
   rB   r	   r   rC   rD   r   rE   r   assertIsInstanceintassertGreater)r#   repo_no_hooksservice_no_hooksr   rM   s        r$   7test_service_with_hooks_disabled_returns_transaction_idzRTestWalletServiceWithHooks.test_service_with_hooks_disabled_returns_transaction_id4  s     )((
 )UK	9K 	9D 	9 	hneD!++JJMM675>6

 	fc*61%r&   c                 2   | j                   j                  | j                  j                  dt	        d      d      }|j                         }| j                  |d          | j                  |d          | j                  d|       | j                  d|       y)	z3Test TransactionResult.to_dict() for API responses.r   r<   r   rG   rI   r   r   N)	r!   rD   r   rE   r   to_dictrF   rH   assertNotIn)r#   rM   result_dicts      r$   %test_to_dict_method_for_api_responsesz@TestWalletServiceWithHooks.test_to_dict_method_for_api_responsesK  s~    ''JJMM675>6
 nn&I./[)9:;+.[1r&   c                    dt         dt        fd}t        dt        j                  |d       | j
                  j                  | j                  j                  dt        d      d      }|j                         }| j                  |d	          | j                  |d
          | j                  |d   d   d       | j                  |d   d   d       | j                  |d   d   d   d       y)z6Test TransactionResult.to_dict() with rejection error.r*   r+   c                 "    t        ddddi      )N
TEST_ERRORTest rejectionkeyvaluere   r   rR   s    r$   reject_hookzQTestWalletServiceWithHooks.test_to_dict_with_rejection_error.<locals>.reject_hookZ  s    $'(( r&   rejectr5   r   r<   r   rG   rI   r   r   r   rf   r   rg   r  r  N)r
   rB   r	   r   rC   r!   rD   r   rE   r   r   rY   rJ   rL   )r#   r  rM   r   s       r$   !test_to_dict_with_rejection_errorz<TestWalletServiceWithHooks.test_to_dict_with_rejection_errorX  s    	 	 	 	hk5A''JJMM675>6
 nn&Y/0+&678W-f5|DW-i8:JKW-i8?Ir&   c                    dt         ddfd}t        dt        j                  |d       | j                  j                  | j                  j                  dt        d      d	      }|j                         }| j                  |d
          | j                  |d          | j                  d|       | j                  t        |d         d       | j                  |d   d   d   d       | j                  |d   d   d   d       y)z9Test TransactionResult.to_dict() with POST hook warnings.r*   r+   Nc                     t        d      )NzPOST failedr|   rR   s    r$   r   zUTestWalletServiceWithHooks.test_to_dict_with_post_hook_warnings.<locals>.failing_postq  s    ]++r&   failr5   r   r<   r   rG   rI   r   r   r   r   r   r   )r
   r	   r   rw   r!   rD   r   rE   r   r   rF   rH   rZ   rL   r   )r#   r   rM   r   s       r$   $test_to_dict_with_post_hook_warningsz?TestWalletServiceWithHooks.test_to_dict_with_post_hook_warningso  s    	,+ 	,$ 	, 	fhmm\5A''JJMM675>6
 nn&I./[)9:;j+.[45q9Z03F;VDZ03F;=STr&   N)__name__
__module____qualname____doc__r%   r(   rN   r]   rn   ry   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r	   r&   r$   r   r      s    ;$1:0:C>2:X:YH1>"2H3:D 1D'1R /D IL7<#BR&.2J.Ur&   r   N)r  decimalr   django.testr   wallet_utilsr   r   r   r   r	   wallet_utils.hooksr
   wallet_utils.exceptionsr   tests.modelsr   r   r  r&   r$   <module>r     s3    ;     + 6 !o	U o	Ur&   