
    wi0U                     V   d Z ddlZddlmc mZ ddlZddlZddl	Z	ddl
mZ ddlmZmZ ddlZej                   j#                  d e ee      j(                  j(                  j(                               ej*                  d        Zej*                  d        Zej*                  d        Zej*                  d        Z G d	 d
      Z G d d      Z G d d      Z G d d      Z G d d      Z G d d      Z G d d      Z  G d d      Z! G d d      Z" G d d      Z# G d d      Z$y)u   
utils/meta_ads_client.py 테스트 스위트

테스트 대상: MetaAdsClient 클래스
전략: 모든 외부 API 호출(facebook_business SDK, requests)을 mock으로 대체
    N)Path)	MagicMockpatchc               #      K   ddddd} t        j                  t        j                  | d      5  |  ddd       y# 1 sw Y   yxY ww)	u4   4개의 필수 환경변수를 세팅하는 fixture.test_app_idtest_app_secret
test_token
act_123456)META_APP_IDMETA_APP_SECRETMETA_ACCESS_TOKENMETA_AD_ACCOUNT_IDFclearN)r   dictosenviron)envs    7/home/jay/workspace/utils/tests/test_meta_ads_client.pymock_envr      sJ      %,)*	C 
BJJ5	1 	  s   .A
>	A
AA
c               #   T   K   t        d      5 } |  ddd       y# 1 sw Y   yxY ww)u7   FacebookAdsApi.init을 mock으로 대체하는 fixture.z)utils.meta_ads_client.FacebookAdsApi.initN)r   )	mock_inits    r   mock_api_initr   &   s,      
:	; y  s   (	(%(c               #   z   K   t        d      5 } t               }|| _        | |f ddd       y# 1 sw Y   yxY ww)u7   AdAccount 클래스를 mock으로 대체하는 fixture.utils.meta_ads_client.AdAccountN)r   r   return_value)mock_clsmock_instances     r   mock_ad_accountr   -   sA      
0	1 &X! -%%& & &s   ;/	;8;c                 x    t        d      5  ddlm}  |       }ddd       |\  }}|_        |S # 1 sw Y   xY w)u   
    MetaAdsClient 인스턴스를 반환하는 통합 fixture.
    load_env_keys와 FacebookAdsApi.init, AdAccount를 모두 mock 처리한다.
    #utils.meta_ads_client.load_env_keysr   MetaAdsClientN)r   utils.meta_ads_clientr#   _account)r   r   r   r#   instance_mock_ad_account_instances          r   clientr)   6   sF     
4	5 #7 ?#
 #2A0HO# #s   09c                       e Zd ZdZd Zd Zy)TestInitu"   MetaAdsClient.__init__() 테스트c           
      P   t        d      5  t        d      5 }ddlm}  |       }|j                          |j                  }|\  }}t        |      t        |j                               z   }	g }
d}||	v }|}|s/|j                  }d} ||      }d}||k(  }|}|s|d   }d}||k(  }|}|st        j                  d|fd||	f      t        j                  |      d	t        j                         v st        j                  |	      rt        j                  |	      nd	d
z  }dd|iz  }|
j                  |       |s)t        j                  dfdf      dt        j                         v st        j                  |      rt        j                  |      ndt        j                        t        j                        t        j                  |      t        j                  |      dz  }dd|iz  }|
j                  |       |s_t        j                  dfdf      t        j                  |      t        j                  |      dz  }dd|iz  }|
j                  |       t        j                  |
d      i z  }dd|iz  }t!        t        j"                  |            dx}x}
x}x}x}x}x}x}x}x}x}}|j                          |j                  d   d   }d}||v }|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd |iz  }t!        t        j"                  |            dx}}ddd       ddd       y# 1 sw Y   xY w# 1 sw Y   yxY w)!u_   환경변수 4개 모두 설정 시 정상 초기화되고 FacebookAdsApi.init이 호출된다.r!   r   r   r"   r   app_idin)z%(py3)s in %(py5)sall_args)py3py5z%(py7)spy7==)zO%(py15)s
{%(py15)s = %(py11)s
{%(py11)s = %(py9)s.get
}(%(py13)s)
} == %(py18)skwargs)py9py11py13py15py18z%(py20)spy20)z%(py23)s == %(py26)s)py23py26z%(py28)spy28   zassert %(py31)spy31Nr
   z%(py1)s in %(py3)scall_argpy1r1   assert %(py5)sr2   )r   r$   r#   assert_called_once	call_argslistvaluesget
@pytest_ar_call_reprcompare	_saferepr@py_builtinslocals_should_repr_global_nameappend_format_boolopAssertionError_format_explanation) selfr   r   mock_ad_account_clsr#   r)   init_kwargsargsr6   r0   @py_assert1@py_assert2@py_assert4@py_assert0@py_assert10@py_assert12@py_assert14@py_assert17@py_assert16@py_assert22@py_assert25@py_assert24@py_format6@py_format8@py_format19@py_format21@py_format27@py_format29@py_format30@py_format32rC   @py_format4s                                    r   test_init_successzTestInit.test_init_successN   s^    78	,34	,8K;"_F ,,.'11K 'LD&DzD$99Hq=q=H,q

q8q
80Dqq0D0UqY]^_Y`qdqqY`dqYqqqqq=Hqqq=qqqqqqHqqqHqqqqqqqq0Dqqqqqqqqqqqq
qqq8qqq0DqqqqqqqqqqY`dqqqqY`qqqdqqqqqqqqqqqqqqqq  224*44Q7:H+<8++++<8+++<++++++8+++8+++++++)	, 	, 	, 	, 	, 	,s#   NM'N?NN	NN%c           	      |   t        j                  t        j                  i d      5  t        d      5  t        d      5  ddlm} t        j                  t        t        f      5   |        dd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   *xY w# 1 sw Y   yxY w)u:   필수 환경변수 누락 시 ValueError가 발생한다.Tr   r!   z$utils.meta_ads_client.FacebookAdsApir   r"   N)
r   r   r   r   r$   r#   pytestraises
ValueErrorKeyError)rV   r#   s     r   test_init_missing_envzTestInit.test_init_missing_envf   s     JJrzz2T2	 78	  89	 
 <
H56   	  	  	  	    	  	  	  	  	  	 sQ   B2B&&B%B	-B5B&=B2BBB#B&&B/	+B22B;N)__name__
__module____qualname____doc__ro   ru        r   r+   r+   K   s    ,,0 r{   r+   c                       e Zd ZdZd Zy)TestExchangeLongLivedTokenu   exchange_token() 테스트c                 r   t               }dddd|j                  _        t               |_        t	        d|      5 }|j                         }ddd       t        t              }|sdd	t        j                         v st        j                  t              rt        j                  t              nd	d
t        j                         v st        j                  |      rt        j                  |      nd
dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      dz  }t        t        j                  |            d}d}	||	k(  }
|
st        j                  d|
fd||	f      d
t        j                         v st        j                  |      rt        j                  |      nd
t        j                  |	      dz  }dd|iz  }t        t        j                  |            dx}
}	j!                          y# 1 sw Y   xY w)u   
        requests.get을 mock하여 새 장기 토큰을 받고,
        반환값이 토큰 문자열인지 확인한다.
        FacebookAdsApi.init 재호출은 exchange_token 내부에서 일어나지 않는다.
        long_token_xxxbeareri O )access_token
token_type
expires_in"utils.meta_ads_client.requests.getr   N5assert %(py4)s
{%(py4)s = %(py0)s(%(py1)s, %(py2)s)
}
isinstanceresultstrpy0rE   py2py4r4   z%(py0)s == %(py3)sr   r1   rF   r2   )r   jsonr   raise_for_statusr   exchange_tokenr   r   rO   rP   rL   rQ   rN   rT   rU   rM   rG   )rV   r)   r   r   mock_responsemock_getr   @py_assert3@py_format5r[   rZ   rn   rf   s                r   test_exchange_long_lived_tokenz9TestExchangeLongLivedToken.test_exchange_long_lived_token|   sU    ","!+
'
 *3&7mT 	-X`**,F	- &#&&&&&&&&z&&&z&&&&&&&&&&&&&&&&&#&&&#&&&&&&&&&&))v)))))v)))))))v)))v))))))))))) 	##%	- 	-s   H,,H6N)rv   rw   rx   ry   r   rz   r{   r   r}   r}   y   s
    $&r{   r}   c                       e Zd ZdZd Zy)TestGetTokenInfou   check_token() 테스트c                    dddddddgdi}t               }||j                  _        t               |_        t	        d	|
      5  |j                         }ddd       t        t              }|sddt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      dz  }t        t        j                  |            d}|j                  }d} ||      }d}	||	u }
|
st        j                   d|
fd||	f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      t        j                  |	      dz  }dd|iz  }t        t        j                  |            dx}x}x}x}
}	|j                  }d} ||      }d}	||	k(  }
|
st        j                   d|
fd||	f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      t        j                  |	      dz  }dd|iz  }t        t        j                  |            dx}x}x}x}
}	y# 1 sw Y   &xY w)uH   requests.get mock으로 토큰 정보 dict를 올바르게 반환한다.dataTiIr   999ads_readads_management)is_valid
expires_atr-   user_idscopesr   r   Nr   r   r   r   r   r   is)zI%(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.get
}(%(py4)s)
} is %(py9)s)r   r   r   py6r7   zassert %(py11)sr8   r   r4   )zI%(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.get
}(%(py4)s)
} == %(py9)s)r   r   r   r   r   check_tokenr   r   rO   rP   rL   rQ   rN   rT   rU   rK   rM   )rV   r)   expected_datar   r   r   r   rZ   @py_assert5@py_assert8@py_assert7@py_format10@py_format12s                r   test_get_token_infoz$TestGetTokenInfo.test_get_token_info   s.     (' %'78
 "*7')2&7mT 	*'')F	* &$''''''''z'''z''''''&'''&''''''$'''$''''''''''zz-*-z*%--%----%------v---v---z---*---%----------zz5,5z,'5:5':5555':555555v555v555z555,555'555:55555555	* 	*s   M99NN)rv   rw   rx   ry   r   rz   r{   r   r   r      s
    !6r{   r   c                       e Zd ZdZd Zy)TestGetAccountInfou   get_account_info() 테스트c                    ddddd}||j                   j                  _        |j                         }d}||u}|st	        j
                  d|fd||f      d	t        j                         v st	        j                  |      rt	        j                  |      nd	t	        j                  |      d
z  }dd|iz  }t        t	        j                  |            dx}}|j                   j                  j                          y)uH   AdAccount.api_get mock으로 계정 필드를 올바르게 반환한다.r
   zTest Ad AccountKRWr@   )idnamecurrencyaccount_statusNis notz%(py0)s is not %(py3)sr   r   rF   r2   )r%   api_getr   get_account_inforL   rM   rO   rP   rQ   rN   rT   rU   rG   )rV   r)   expectedr   r[   rZ   rn   rf   s           r   test_get_account_infoz(TestGetAccountInfo.test_get_account_info   s     %	
 08,((*!!vT!!!!vT!!!!!!v!!!v!!!T!!!!!!!224r{   N)rv   rw   rx   ry   r   rz   r{   r   r   r      s
    &5r{   r   c                       e Zd ZdZd Zy)TestListCampaignsu   list_campaigns() 테스트c                    t               }t        d       |_        t               }t        d       |_        ||g|j                  j                  _        |j                         }d}||u}|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}}t        |      }d}	||	k(  }
|
st        j                  d|
fd||	f      dt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |	      dz  }dd|iz  }t        t        j                  |            dx}x}
}	|j                  j                  j                          y)uG   AdAccount.get_campaigns mock으로 캠페인 리스트를 반환한다.c                     ddd|    S )Ncamp_001z
Campaign 1r   r   rz   ks    r   <lambda>z7TestListCampaigns.test_list_campaigns.<locals>.<lambda>       ZamFnopFq r{   )side_effectc                     ddd|    S )Ncamp_002z
Campaign 2r   rz   r   s    r   r   z7TestListCampaigns.test_list_campaigns.<locals>.<lambda>   r   r{   Nr   r   r   r   rF   r2      r4   z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)slenr   rE   r1   r   assert %(py8)spy8)r   __getitem__r%   get_campaignsr   list_campaignsrL   rM   rO   rP   rQ   rN   rT   rU   r   rG   )rV   r)   mock_campaign_1mock_campaign_2r   r[   rZ   rn   rf   r   r\   @py_format7@py_format9s                r   test_list_campaignsz%TestListCampaigns.test_list_campaigns   sL   #+&/<q&r##+&/<q&r#6E5W%%2&&(!!vT!!!!vT!!!!!!v!!!v!!!T!!!!!!!6{a{a{ass66{a%%88:r{   N)rv   rw   rx   ry   r   rz   r{   r   r   r      s
    $;r{   r   c                       e Zd ZdZd Zd Zy)TestCreateCampaignu   create_campaign() 테스트c                    t               }dddd|j                  _        ||j                  j                  _        |j	                  dd      }|j                  j                  j                          |j                  j                  j                  \  }}t        |      t        |      z   }d}||v }|st        j                  d|fd||f      t        j                  |      d	t        j                         v st        j                  |      rt        j                  |      nd	d
z  }	dd|	iz  }
t        t        j                  |
            dx}}y)uh   account.create_campaign mock으로 캠페인을 생성하고 기본 status가 PAUSED임을 확인한다.camp_new_001zNew CampaignPAUSEDr   r   statusOUTCOME_AWARENESSr   	objectiver.   rB   all_args_strrD   rF   r2   N)r   export_all_datar   r%   create_campaignrG   rH   r   rL   rM   rN   rO   rP   rQ   rT   rU   )rV   r)   mock_campaignr   rH   call_kwargsr   r]   r[   rn   rf   s              r   test_create_campaignz'TestCreateCampaign.test_create_campaign   s    ! "6
%%2
 8E''4'') ( 
 	''::< "(!@!@!J!J	;9~K(88'x<''''x<'''x''''''<'''<'''''''r{   c                 \   t               }dddd|j                  _        ||j                  j                  _        |j	                  dd       |j                  j                  j
                  \  }}t        |      t        |      z   }d}||v }|st        j                  d|fd||f      t        j                  |      d	t        j                         v st        j                  |      rt        j                  |      nd	d
z  }dd|iz  }	t        t        j                  |	            dx}}y)u<   status 파라미터 미지정 시 기본값이 PAUSED이다.camp_new_002zTest Campaignr   r   OUTCOME_TRAFFICr   r.   rB   r   rD   rF   r2   N)r   r   r   r%   r   rH   r   rL   rM   rN   rO   rP   rQ   rT   rU   )
rV   r)   r   rH   r   r   r]   r[   rn   rf   s
             r   *test_create_campaign_default_status_pausedz=TestCreateCampaign.test_create_campaign_default_status_paused  s    ! #6
%%2
 8E''4O?PQ "(!@!@!J!J	;9~K(88'x<''''x<'''x''''''<'''<'''''''r{   N)rv   rw   rx   ry   r   r   rz   r{   r   r   r      s    %(.(r{   r   c                       e Zd ZdZd Zy)TestUpdateCampaignu   update_campaign() 테스트c                     t        d      5 }t               }||_        ||j                  _        |j	                  ddd      }|j                  j                          ddd       y# 1 sw Y   yxY w)uF   Campaign.api_update mock으로 캠페인 업데이트를 수행한다.utils.meta_ads_client.Campaignr   zUpdated CampaignACTIVE)campaign_idr   r   N)r   r   r   
api_updateupdate_campaignrG   )rV   r)   mock_campaign_clsr   r   s        r   test_update_campaignz'TestUpdateCampaign.test_update_campaign  ss    34 	:8I%KM-:*4AM$$1++&' , F $$779	: 	: 	:s   AA&&A/N)rv   rw   rx   ry   r   rz   r{   r   r   r     s
    %:r{   r   c                       e Zd ZdZd Zy)TestDeleteCampaignu   delete_campaign() 테스트c                 *   t        d      5 }t               }||_        d|j                  _        |j	                  d      }|j                  j                          d}||u }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}}ddd       y# 1 sw Y   yxY w)uN   Campaign.api_delete mock으로 캠페인을 삭제하고 True를 반환한다.r   Tr   )r   r   )z%(py0)s is %(py3)sr   r   rF   r2   N)r   r   r   
api_deletedelete_campaignrG   rL   rM   rO   rP   rQ   rN   rT   rU   )	rV   r)   r   r   r   r[   rZ   rn   rf   s	            r   test_delete_campaignz'TestDeleteCampaign.test_delete_campaign6  s    34 		"8I%KM-:*48M$$1++
+CF$$779!!6T>!!!6T!!!!!!6!!!6!!!T!!!!!!!		" 		" 		"s   C4D		DN)rv   rw   rx   ry   r   rz   r{   r   r   r   3  s
    %"r{   r   c                       e Zd ZdZd Zd Zy)TestUploadImageu   upload_image() 테스트c                    t               }ddi|j                  _        ||j                  j                  _        t        d      5 }t               }||_        d|j                  _        d|_        t        d      |_        |j                  d      }d	d	d	       t        t              }|sd
dt        j                         v st        j                  t              rt        j                   t              nddt        j                         v st        j                  |      rt        j                   |      nddt        j                         v st        j                  t              rt        j                   t              ndt        j                   |      dz  }t#        t        j$                  |            d	}d}||k(  }	|	st        j&                  d|	fd||f      dt        j                         v st        j                  |      rt        j                   |      ndt        j                   |      dz  }
dd|
iz  }t#        t        j$                  |            d	x}	}y	# 1 sw Y   xY w)uO   AdImage mock으로 이미지를 업로드하고 hash 문자열을 반환한다.hashabc123def456utils.meta_ads_client.PathTtest_banner.png/tmp/test_banner.pngr   
image_pathNr   r   r   r   r   r4   r   r   rF   r2   )r   r   r   r%   create_ad_imager   existsr   __str__upload_imager   r   rO   rP   rL   rQ   rN   rT   rU   rM   )rV   r)   
mock_imagemock_path_clsmock_path_instancer   r   r   r[   rZ   rn   rf   s               r   test_upload_imagez!TestUploadImage.test_upload_imageL  s   [
39>2J
""/7A''4/0 	LM!*);M&59%%2&7#)2@V)W&((4J(KF	L &#&&&&&&&&z&&&z&&&&&&&&&&&&&&&&&#&&&#&&&&&&&&&&''v''''v''''''v'''v''''''''''	L 	Ls   AI  I*c                    t               }dddddii|j                  _        ||j                  j                  _        t        d      5 }t               }||_        d|j                  _        d|_        t        d	      |_        |j                  d
      }ddd       t        t              }|sddt        j                         v st        j                  t              rt        j                   t              nddt        j                         v st        j                  |      rt        j                   |      nddt        j                         v st        j                  t              rt        j                   t              ndt        j                   |      dz  }t#        t        j$                  |            d}y# 1 sw Y   +xY w)uM   upload_image는 hash 문자열만 반환한다 (중첩 응답 처리 포함).imagesr  r   zhttps://example.com/image.jpg)r   urlr  Tr  r   r  Nr   r   r   r   r   )r   r   r   r%   r  r   r  r   r  r	  r   r   rO   rP   rL   rQ   rN   rT   rU   )rV   r)   r
  r  r  r   r   r   s           r   &test_upload_image_with_nested_responsez6TestUploadImage.test_upload_image_with_nested_response_  s=   [
!*:$3

""/ 8B''4/0 	LM!*);M&59%%2&7#)2@V)W&((4J(KF	L &#&&&&&&&&z&&&z&&&&&&&&&&&&&&&&&#&&&#&&&&&&&&&&	L 	Ls   	AF??G	N)rv   rw   rx   ry   r  r  rz   r{   r   r   r   I  s    "(&'r{   r   c                       e Zd ZdZd Zd Zy)TestGetInsightsu   get_insights() 테스트c                    t               }dddddd|j                  _        t        d      5 }t               }||_        |g|j                  _        |j	                  dd	
      }ddd       d}|u}|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }	t        t        j                  |	            dx}}t        |      }d}
||
k(  }|st        j                  d|fd||
f      dt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |
      dz  }dd|iz  }t        t        j                  |            dx}x}}
j                  j                          y# 1 sw Y   xY w)uH   Campaign.get_insights mock으로 인사이트 데이터를 반환한다.10000500500008000z5.0)impressionsclicksspendreachctrr   123campaign	object_idobject_typeNr   r   r   r   rF   r2   r@   r4   r   r   r   r   r   )r   r   r   r   get_insightsrL   rM   rO   rP   rQ   rN   rT   rU   r   rG   )rV   r)   mock_insight_1r   mock_campaign_instancer   r[   rZ   rn   rf   r   r\   r   r   s                 r   test_get_insightsz!TestGetInsights.test_get_insights  s   ""7
&&3 34 	R8I%.["-C*@N?O"//<((5j(QF	R "!vT!!!!vT!!!!!!v!!!v!!!T!!!!!!!6{a{a{ass66{a++>>@	R 	Rs   7H<<Ic                 r  
 t        d      5 }t               }||_        g |j                  _        |j                  dd      }|j                  j                  \  }}t        |      t        |      z   

fddD        }t        |      }|sddt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      d	z  }	t        t        j                  |	            d
x}}d
d
d
       y
# 1 sw Y   y
xY w)uW   기본 필드(impressions, clicks, spend)를 포함하여 인사이트를 조회한다.r   r  r  r   c              3   &   K   | ]  }|v  
 y w)Nrz   ).0fieldr   s     r   	<genexpr>z@TestGetInsights.test_get_insights_with_fields.<locals>.<genexpr>  s     fu,fs   )r  r  r  r  z,assert %(py4)s
{%(py4)s = %(py0)s(%(py2)s)
}any)r   r   r   N)r   r   r   r#  rH   r   r,  rO   rP   rL   rQ   rN   rT   rU   )rV   r)   r   r%  r   rH   r   rZ   r   r   r   s             @r   test_get_insights_with_fieldsz-TestGetInsights.test_get_insights_with_fields  s    34 	g8I%.["-C*?A"//<((5j(QF%;%H%H%R%R"I{y>C,<<Lf:eff3fffffffff3fff3ffffffffffffff	g 	g 	gs   DD--D6N)rv   rw   rx   ry   r&  r-  rz   r{   r   r  r  ~  s    "A,gr{   r  c                       e Zd ZdZd Zd Zy)TestUpdateEnvTokenu   update_env_token() 테스트c                 L   d}d}t        j                  ddd      5 }|j                  |       |j                  }ddd       	 |_        |j                  |       t        |      j                         }||v }|st        j                  d	|fd
||f      dt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }	t        t        j                  |	            d}d}
|
|v}|st        j                  d|fd|
|f      t        j                  |
      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            dx}
}t!        j"                  |       y# 1 sw Y   xY w# t!        j"                         w xY w)u   
        실제 임시 파일을 사용하여 META_ACCESS_TOKEN 라인이 새 토큰으로 교체되는지 확인한다.
        export META_APP_ID=test_app_id
export META_APP_SECRET=test_app_secret
export META_ACCESS_TOKEN=old_token
export META_AD_ACCOUNT_ID=act_123456
new_long_token_xyzw.keysFmodesuffixdeleteN	new_tokenr.   z%(py0)s in %(py2)sr:  updated_contentr   r   assert %(py4)sr   	old_tokennot inz%(py1)s not in %(py3)srD   rF   r2   tempfileNamedTemporaryFilewriter   _env_keys_pathupdate_env_tokenr   	read_textrL   rM   rO   rP   rQ   rN   rT   rU   r   unlinkrV   r)   original_contentr:  tmptmp_pathr<  rZ   @py_format3r   r]   r[   rn   rf   s                 r   #test_update_env_token_replaces_linez6TestUpdateEnvToken.test_update_env_token_replaces_line  s_   
5 	 )	((c'%P 	 TWII&'xxH	 		 $,F!##i#8"8n668O////9//////9///9////////////////5;o5555;o555;555555o555o5555555IIh	  	  IIh   G?F%H ?H	H#c                 L   d}d}t        j                  ddd      5 }|j                  |       |j                  }ddd       	 |_        |j                  |       t        |      j                         }||v }|st        j                  d	|fd
||f      dt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }	t        t        j                  |	            d}d}
|
|v}|st        j                  d|fd|
|f      t        j                  |
      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            dx}
}t!        j"                  |       y# 1 sw Y   xY w# t!        j"                         w xY w)uU   실제 임시 파일을 사용하여 META_ACCESS_TOKEN 라인 교체를 검증한다.r1  r2  r3  r4  Fr5  Nr9  r.   r;  r:  r<  r=  r>  r   r?  r@  rB  rD   rF   r2   rC  rK  s                 r   (test_update_env_token_with_real_tempfilez;TestUpdateEnvToken.test_update_env_token_with_real_tempfile  s_   5 	 )	((c'%P 	 TWII&'xxH	 		 $,F!##i#8"8n668O////9//////9///9////////////////5;o5555;o555;555555o555o5555555IIh	  	  IIhrQ  N)rv   rw   rx   ry   rP  rS  rz   r{   r   r/  r/    s    & 6 r{   r/  )%ry   builtinsrO   _pytest.assertion.rewrite	assertionrewriterL   r   sysrD  pathlibr   unittest.mockr   r   rq   pathinsertr   __file__parentfixturer   r   r   r)   r+   r}   r   r   r   r   r   r   r   r  r/  rz   r{   r   <module>r`     s'    	 
   *  3tH~,,33::; < 	 	   & &  (&  & \& &B6 6@5 50; ;0)( )(b: :0" ",-' -'j&g &g\5  5 r{   