
    (<i%                        d Z ddlZddlZddlmZ ddlmZmZmZ ddl	Z	ej                  j                  d e ee      j                               ddlZddlmZmZ  G d d      Z G d d	      Z G d
 d      Z G d d      Zy)u  통합 테스트 — image_router.py + iptc_tagger.py 연동.

테스트 범위:
- _generate_gemini() 실제 API 호출 구조 (gcloud_auth + REST API mock)
- _generate_satori() subprocess 호출 구조 (node subprocess mock)
- _generate_hybrid() generate_hybrid 모듈 호출 구조 (playwright mock)
- _generate_gpt() OpenAI API 호출 구조 (openai mock)
- generate_image() + iptc_tagger 연동 (IPTC 태깅이 성공 시 호출되는지)
    N)Path)	MagicMockpatchcall)GenerationResultgenerate_imagec                   ,    e Zd ZdeddfdZdeddfdZy)TestGenerateGeminiIntegrationtmp_pathreturnNc                    t               }d|j                  _        t               }d }||j                  _        t        j                  d||d      5  dt        j                  v rt        j                  d= ddl	}ddl
}|j                  d|d	z        }ddd       |j                  j                          d
u sJ y# 1 sw Y   *xY w)uE   _generate_gemini() 호출 시 gcloud_auth.get_access_token 호출됨.
fake_tokenc                 &    |j                  d       y )Ns   fake_image_data)write_bytes)tokenpromptoutput_pathscenarios       a/home/jay/workspace/.worktrees/task-2057-dev2/tools/ai-image-gen/test_image_router_integration.pyside_effect_create_filezmTestGenerateGeminiIntegration.test_gemini_calls_gcloud_auth_get_access_token.<locals>.side_effect_create_file$   s    ##$67    sys.modulesgcloud_authgemini_pro_generateimage_routerr   N   테스트 프롬프트test.pngT)r   get_access_tokenreturn_valuegenerate_image_via_gemini_apiside_effectr   dictsysmodules	importlibr   _generate_geminiassert_called_once)selfr   mock_gcloudmock_gemini_genr   r&   _irresults           r   .test_gemini_calls_gcloud_auth_get_access_tokenzLTestGenerateGeminiIntegration.test_gemini_calls_gcloud_auth_get_access_token   s    k4@$$1#+	8 E\55AZZ&#2(
  		[
 ,KK/&))*BHzDYZF		[ 	$$779~~		[ 		[s   AB==Cc                 H   t               }t        d      |j                  _        t               }t	        j
                  d||d      5  dt        j                  v rt        j                  d= ddl}ddl	}|j                  d|dz        }ddd       d	u sJ y# 1 sw Y   xY w)
u$   gcloud_auth 예외 시 False 반환.u   인증 실패r   r   r   r   Nr   r   F)r   RuntimeErrorr   r"   r   r#   r$   r%   r&   r   r'   )r)   r   r*   r+   r&   r,   r-   s          r   )test_gemini_returns_false_on_auth_failurezGTestGenerateGeminiIntegration.test_gemini_returns_false_on_auth_failure7   s    k3?3P$$0#+ZZ&#2(
  	[ ,KK/&))*BHzDYZF	[ 	[ 	[s   ABB!)__name__
__module____qualname__r   r.   r1    r   r   r
   r
      s)    t PT 4$ 4 r   r
   c                   ,    e Zd ZdeddfdZdeddfdZy)TestGenerateSatoriIntegrationr   r   Nc                    |dz  fd}t        d      5 }||j                  _        t        d      j                  |_        t        j                  d      }ddd       j                  j                  sJ |j                  j                  }|d   r|d   d   n|d   j                  d	g       }|d   d
k(  sJ du sJ y# 1 sw Y   jxY w)uO   _generate_satori() 호출 시 subprocess.run이 'node'를 첫 인자로 호출.
output.pngc                 `    | r| d   dk(  rj                  d       t               }d|_        |S )Nr   nodes   fake_png_data)r   r   
returncode)cmdargskwargsmock_resultr   s       r   fake_subprocess_runz\TestGenerateSatoriIntegration.test_satori_calls_node_subprocess.<locals>.fake_subprocess_runU   s5    s1v'''(89#+K%&K"r   image_router.subprocess
subprocessu   카드뉴스 프롬프트Nr      r>   r;   T)
r   runr"   
__import__CalledProcessErrorr   _generate_satoricalled	call_argsget)r)   r   rA   mock_subprocessr-   rJ   r=   r   s          @r   !test_satori_calls_node_subprocessz?TestGenerateSatoriIntegration.test_satori_calls_node_subprocessQ   s    -	 ,- 	].AO+1;L1I1\1\O.!223NP[\F	] ""))))#''11	!*1il1o9Q<3C3CFB3O1v~~	] 	]s   ACCc                     |dz  }d }t        d      5 }||j                  _        t        d      j                  |_        t        j                  d|      }ddd       du sJ y# 1 sw Y   xY w)u0   subprocess.run returncode != 0 시 False 반환.r9   c                 6    t               }d|_        d|_        |S )NrD   u   node 실행 오류)r   r<   stderr)r=   r>   r?   r@   s       r   fake_subprocess_run_failzmTestGenerateSatoriIntegration.test_satori_returns_false_on_subprocess_error.<locals>.fake_subprocess_run_failm   s    #+K%&K"!5Kr   rB   rC   u   실패 프롬프트NF)r   rE   r"   rF   rG   r   rH   )r)   r   r   rQ   rL   r-   s         r   -test_satori_returns_false_on_subprocess_errorzKTestGenerateSatoriIntegration.test_satori_returns_false_on_subprocess_errori   sy    -	 ,- 	W.FO+1;L1I1\1\O.!223H+VF	W
 	W 	Ws   AA%%A.)r2   r3   r4   r   rM   rR   r5   r   r   r7   r7   P   s(    $ 4 0d t r   r7   c                       e Zd ZdeddfdZy)TestGenerateHybridIntegrationr   r   Nc                 *   t               }t        d      |j                  _        t	        j
                  dd|i      5  dt        j                  v rt        j                  d= ddl}|j                  d|dz        }ddd       d	u sJ y# 1 sw Y   xY w)
uA   bg_A.jpg가 없으면 False 반환 (generate_hybrid 모듈 mock).u5   배경 이미지를 찾을 수 없습니다: bg_A.jpgr   generate_hybridr   r   Nu   하이브리드 프롬프트r9   F)
r   FileNotFoundErrorrV   r"   r   r#   r$   r%   r   _generate_hybrid)r)   r   mock_gen_hybridr,   r-   s        r   )test_hybrid_returns_false_when_bg_missingzGTestGenerateHybridIntegration.test_hybrid_returns_false_when_bg_missing   s    #+6GC7
''3 ZZ(9?'KL 	c,KK/&))*H(UaJabF		c 	c 	cs   =B		B)r2   r3   r4   r   rZ   r5   r   r   rT   rT      s    $ 4 r   rT   c                   ,    e Zd ZdeddfdZdeddfdZy)TestIptcTaggingIntegrationr   r   Nc                 Z   t               }|dz  }||j                  _        d }t        d|      5  t        j                  dd|i      5  t        ddd	|
      }ddd       ddd       j                  du sJ |j                  j                          y# 1 sw Y   <xY w# 1 sw Y   @xY w)u   generate_image()에서 성공 후 iptc_tagger.tag_image가 호출되는지 확인.

        image_router.py 내부에서 'import iptc_tagger as _tagger' (lazy import) 방식 사용.
        sys.modules 패치로 해당 import를 가로챈다.
        zbrand_gemini.pngc                 p    ddl m} |j                  ddd      }|j                  t	        |      d       y	
Nr   )ImageRGB)
   rb   )r   r      )colorPNG)formatTPILr`   newsavestrr   r   r`   imgs       r   fake_generate_geminizlTestIptcTaggingIntegration.test_iptc_tagger_called_after_successful_generation.<locals>.fake_generate_gemini   s1    !))E8;)?CHHS%eH4r   image_router._generate_geminir"   r   iptc_taggerphotorealisticr   brandpurposer   rs   
output_dirNT)r   	tag_imager    r   r#   r   successr(   )r)   r   	mock_iptc
output_pngrn   r-   s         r   3test_iptc_tagger_called_after_successful_generationzNTestIptcTaggingIntegration.test_iptc_tagger_called_after_successful_generation   s     K	 22
+5	(	 1?ST		JJ}}i&@A		 $(/#	F			 		 ~~%%%..0		 		 		 		s#   B!
BB!B	B!!B*c                 .   t               }t        d      |j                  _        d }t	        d|      5  t	        j
                  dd|i      5  t        ddd	|
      }ddd       ddd       j                  du sJ y# 1 sw Y   "xY w# 1 sw Y   &xY w)u   IPTC 태깅 실패해도 GenerationResult.success = True.

        image_router.py가 iptc_tagger 예외를 try/except로 무시하고 success를 반환해야 한다.
        u   IPTC 태깅 실패c                 p    ddl m} |j                  ddd      }|j                  t	        |      d       y	r_   rg   rl   s       r   rn   ziTestIptcTaggingIntegration.test_iptc_tagging_failure_does_not_affect_result.<locals>.fake_generate_gemini   s1    !))E8;)?CHHS%eH4r   ro   rp   r   rq   rr   u   태깅 실패 테스트rs   rt   NT)r   r0   rw   r"   r   r#   r   rx   )r)   r   ry   rn   r-   s        r   0test_iptc_tagging_failure_does_not_affect_resultzKTestIptcTaggingIntegration.test_iptc_tagging_failure_does_not_affect_result   s     K	*67K*L	'	 1?ST		JJ}}i&@A		 $(0#	F			 		 ~~%%%		 		 		 		s#   BA?B?B	BB)r2   r3   r4   r   r{   r~   r5   r   r   r\   r\      s-    11	1B&&	&r   r\   )__doc__r$   jsonpathlibr   unittest.mockr   r   r   pytestpathinsertrk   __file__parentr   r   r   r
   r7   rT   r\   r5   r   r   <module>r      so       0 0  3tH~,,- .  9, ,h( (` .=& =&r   