
    [iI                       d Z ddlmZ ddlZddlZddlZddlZddlm	Z	 ddl
mZ ddlZ e	d      Zedz  Zedz  Z ee      ej"                  vr"ej"                  j%                  d ee             dd	Z ed
      Z ed      Zej,                  j.                  ZddZdddZd dZd dZd dZd dZd dZd dZ d!dZ!d!dZ"d dZ#d dZ$d dZ%d!dZ&d!dZ'd!dZ(y)"u%  IDS Phase 2 — magazine-ppt-ko 회귀 테스트 (G2 게이트).

self-contained: conftest 없이도 수집/실행 가능.
- 외부 API mock 차단 (정적 검사)
- 한글 100% string-match
- PPTX 생성 + 한글 추출 검증

python-pptx 미설치 시 PPTX 관련 케이스는 자동 skip.
    )annotationsN)Path)Anyz*/home/jay/workspace/skills/magazine-ppt-koscripts	templatesc                ,   t         j                  j                  | t        |  dz        }||j                  t        d|        t         j                  j                  |      }|t        j                  | <   |j                  j                  |       |S )uG   scripts/ 디렉토리의 모듈을 importlib으로 안전하게 로드.z.pyzcannot load )
	importlibutilspec_from_file_locationSCRIPTS_DIRloaderImportErrormodule_from_specsysmodulesexec_module)namespecmodules      A/home/jay/workspace/tests/design-team/test_ids_phase2_ppt_deck.py_import_moduler      s|    >>11$cl8RSD|t{{*L/00^^,,T2FCKKKKF#M    
build_deckverify_koreanc                 D    t         j                  j                  d      d uS )Npptx)r	   r
   	find_spec r   r   _has_python_pptxr   4   s    >>##F+477r   c                4   d| dddddddd	d
d
d| ddddddd| ddddddddddddd d!d"| d#d$d%d&d'd(d)d*d+d,d-d.d/d0d1d2| d3d4d5d6d7d8d9d:d;d<d=d>| d?d@dAdBdCdD| dEdFdGdHdIdJdKdLdM| dNdOdPdQdRdSdTdUdV	dW| dXdYdZd[d\d]d^d_d`da
db| dcdddedfdAdgdhdi
}||    S )ju-   layout별 샘플 변수 dict (한글 가득).u   임원 보고u   분기 실적u   매출 320억 달성uQ   전년 동기 대비 24% 성장하며 사상 최대 실적을 기록했습니다.u   신규 고객 12만명 확보u   구독 갱신율 92%u   운영 비용 8% 절감u   전략기획실u   2026년 5월01)
titleeyebrowkpi_headlineledebullet_1bullet_2bullet_3authordatepage_numberu
   피치 덱u   보험 혁신u   보험을 다시 쓰다u^   데이터 기반 맞춤 보험으로 한국인 1만 가구의 보험료를 절감했습니다.u   다음 라운드 목표u   100억 원 시리즈 A)r"   badgeheadlinesubcopy	cta_label	cta_valueu   4월 회고u   월간 회고u
   잘한 점u"   스프린트 일정 준수율 100%u!   팀 간 커뮤니케이션 개선u   버그 발생률 30% 감소u	   문제점u'   테스트 자동화 커버리지 부족u"   온콜 부담 특정 인원 집중u"   고객 응대 응답 시간 지연u   시도할 점u   TDD 도입 파일럿u   온콜 로테이션 균등화u   고객 응대 SLA 30분 목표)r"   r#   
keep_labelkeep_1keep_2keep_3problem_label	problem_1	problem_2	problem_3	try_labeltry_1try_2try_3u   주간 운영 현황u   2026년 5월 1주차u   신규 가입1240u!   전주 대비 12 퍼센트 증가u   활성 사용자48300u    전주 대비 5 퍼센트 증가u   매출u
   8.2억 원u!   전주 대비 18 퍼센트 증가u	   이탈률z2.1u"   전주 대비 0.4 포인트 감소uY   신규 캠페인 효과로 가입자가 늘었고 이탈률은 안정화 추세입니다.)r"   period
kpi1_label
kpi1_value
kpi1_delta
kpi2_label
kpi2_value
kpi2_delta
kpi3_label
kpi3_value
kpi3_delta
kpi4_label
kpi4_value
kpi4_deltacommentu   하반기 로드맵u   프로젝트 일정u:   단계별 마일스톤과 책임자를 정리했습니다.u   7월u0   베타 기능 출시 및 초기 사용자 모집u   8월u0   결제 시스템 통합 및 가격 정책 확정u   9월u,   정식 런칭 및 마케팅 캠페인 가동u   10월u0   리텐션 분석 및 다음 분기 계획 수립)r"   r#   r%   when_1what_1when_2what_2when_3what_3when_4what_4u   보험 혁신 보고서u   2026년 상반기 사업 전략u   사내 발표u   전략기획실 김지훈u   2026년 5월 3일)r"   subtitler#   	presenterr*   u   오늘 다룰 내용u   목차u2   다섯 가지 핵심 주제로 구성했습니다.u   현황과 시장 분석u   핵심 전략 방향u   주요 실행 과제u   성과 측정 지표u   질의응답 및 토론)r"   r#   r%   item_1item_2item_3item_4item_5u   신규 시장 진입 전략u   전략 방향uR   30대 직장인을 핵심 타겟으로 모바일 전용 상품을 출시합니다.u2   월 만원대 마이크로 보험 라인업 출시u2   카카오 친구톡 기반 고객 응대 자동화u1   직장인 커뮤니티와 제휴 마케팅 진행u   타겟 고객u   320만u$   30대 직장인 잠재 고객 규모)	r"   r#   r%   r&   r'   r(   visual_labelvisual_valuevisual_captionu   정리하며u   요약u   데이터 기반 의사결정uF   주간 단위 KPI 검토를 정례화하여 빠르게 대응합니다.u   고객 경험 우선uK   응대 시간을 30분 이내로 단축하고 만족도를 측정합니다.u   팀 단위 실행u9   월간 회고를 통해 조직 학습을 누적합니다.u   다음 액션u?   다음 주까지 실행 계획서를 정리해 공유합니다.)
r"   r#   point1_titlepoint1_descpoint2_titlepoint2_descpoint3_titlepoint3_descaction_labelaction_copyu   질의응답 세션u   질문해 주세요uh   오늘 발표에 대한 의견과 추가 논의가 필요한 부분을 자유롭게 말씀해 주세요.u	   마무리u	   연락처zjihoon@example.com)r"   r-   r.   r#   contact_labelcontact_namecontact_email
	executivepitchretrostatusplanintroagendacontentsummaryqar   )layoutsuffixbases      r   _sample_varsrx   8   s    %VH-&2g7.1'"
 "&*$1w21
 #6(+&&:93(B==(+45
" ,F84,) =,!<"&=%>r
$ +6(3,PHHDH
 /vh79&4'
 ,F84H/,,,/	
 36(;&hLLK+$D

 $F8,;c2h/V+\
 +6(3- B"(71
Wt'Dj <r   c                   g d}|D cg c]  }t        |       }}t        j                  ||d| dz        }t        |j                        dk(  sJ |j                  D ]C  }|j                         s
J d|        |j                         j                  dkD  r;J d|         |j                  j                         sJ yc c}w )	uE   1. linear 스타일 PPT 10장 — 매거진 5 + 덱 5 = 10장 빌드.rj   linearlayout_namesvariables_listbrand
output_dir
   zslide html not generated: d   zslide html too small: N)	rx   r   buildlen
html_pathsexistsstatst_sizemanifest_path)tmp_pathr|   r   r}   resultps         r   *test_scenario_1_linear_style_ppt_10_slidesr      s    L 6BBTl4(BNB !%h&	  F v  !R''' Dxxz;7s;;zvvx#%C)?s'CC%D &&((( Cs   Cc                    g d}|D cg c]  }t        |       }}t        j                  ||d| dz        }t        |j                        dk(  sJ yc c}w )u7   2. supabase 스타일 덱 7장 — 덱 5 + 매거진 2.)rp   rq   rr   rs   rt   rk   rn   supabaser{      Nrx   r   r   r   r   r   r|   r   r}   r   s        r   ,test_scenario_2_supabase_style_deck_7_slidesr      sk    L 6BBTl4(BNB!%j(	  F v  !Q&&& C   Ac                    g d}|D cg c]  }t        |       }}t        j                  ||d| dz        }t        |j                        dk(  sJ yc c}w )uR   3. apple 미니멀 덱 3종 — 디자인 토큰 fallback 또는 design-md 사용.)rp   rr   rt   appler{      Nr   r   s        r   +test_scenario_3_apple_minimal_deck_3_slidesr      sf    -L5ABTl4(BNB!%g%	  F v  !Q&&& Cr   c                P   g d}|D cg c]  }t        |       }}t        j                  ||d| dz        }t        j	                  |j
                  |j                        }|d   du s
J d|        |d   D ]&  }|d   r	J d	|d
    d|j                  d               yc c}w )uO   4. 한글 100% — manifest의 모든 한글이 HTML에 string-match로 존재.)rk   rl   rm   rp   rt   r   koreanr{   passTzkorean string-match failed: resultszslide filez
 missing: missingN)rx   r   r   r   verify_htmlr   r   get)r   r|   r   r}   r   reportslides          r   (test_scenario_4_korean_100_percent_matchr      s    AL5ABTl4(BNB!%h&	  F &&v';';V=N=NOF&>T!J%A&#JJ!	" WV}VuV}oZ		)@T?UVV}W Cs   B#c                   t               st        j                  d       t        d      }g d}|D cg c]  }t	        |       }}t
        j                  ||d| dz        }| dz  dz  }|j                  |j                  |j                  |      }|j                         sJ |j                         j                  dkD  sJ d	d
l}|j                  t        |            }	t!        |	j"                        dk(  sJ y
c c}w )uY   5. PPTX export — html_to_pptx 호출 후 .pptx 파일 존재 + 슬라이드 수 일치.python-pptx not installedhtml_to_pptx)rk   rp   rt   r   r   r{   	deck.pptxi   r   Nr   )r   pytestskipr   rx   r   r   compile_pptxr   r   r   r   r   r   Presentationstrr   slides)
r   r   r|   r   r}   r   pptx_out	pptx_path_pptxpresentations
             r   test_scenario_5_pptx_exportr   
  s    /0!.1L/L5ABTl4(BNB!%f$	  F & ;.H))6//I >>##d***%%c)n5L|""#q(((% Cs   C<c                   t               st        j                  d       t        d      }ddg}|D cg c]  }t	        |       }}t
        j                  ||d| dz        }| dz  dz  }|j                  |j                  |j                  |       t        j                  |j                  |      }|d	   d
u s
J d|        |d   dk(  sJ yc c}w )uN   6. PPTX 텍스트 검증 — python-pptx로 다시 읽어 한글 string-match.r   r   rl   rq   Npptx2r{   r   r   Tzpptx korean missing: slide_count   )r   r   r   r   rx   r   r   r   r   r   r   verify_pptx_text)r   r   r|   r   r}   r   r   r   s           r   &test_scenario_6_pptx_korean_extractionr   )  s    /0!.1LX&L5ABTl4(BNB!%g%	  F '!K/Hf//1E1ExP++F,@,@(KF&>T!C%:6(#CC!- A%%% Cs   Cc                    d} t        t        j                  d            }|sJ d       g }|D ]  }|j                  d      }| D ]}  }dt	        j
                  |       ddt	        j
                  |       d	g}|D ]D  }t	        j                  ||t        j                        s)|j                  t        |      |f       F   |r
J d
|        y)uO   7. 외부 API mock 차단 — openai/anthropic/google.generativeai import 0건.)openai	anthropiczgoogle.generativeaigenai*.pyzscripts/*.py not foundutf-8encoding^\s*import\s+z	(\s|$|\.)^\s*from\s+z(\.|\s+import\s+)zforbidden imports found: N)
listr   rglob	read_textreescapesearch	MULTILINEappendr   )forbidden_modulespy_files	offenderspathtextmodpatternspats           r   +test_scenario_7_no_external_api_sdk_importsr   C  s    OK%%f-.H---8')I 
7~~w~/$ 	7C !3 0	:ryy~..?@H   799S$5$$c$i%567	7
7 A5i[AA=yr   c                     d} t        t        j                  d            }g }|D ]<  }|j                  d      }| D ]#  }||v s|j	                  t        |      |f       % > |r
J d|        y)uV   8. 직접 URL 차단 — api.openai.com / api.anthropic.com / generativelanguage 0건.)zapi.openai.comzapi.anthropic.comz!generativelanguage.googleapis.comr   r   r   zforbidden URLs found: N)r   r   r   r   r   r   )forbidden_urlsr   r   r   r   urls         r   $test_scenario_8_no_external_api_urlsr   \  s    N
 K%%f-.H')I 3~~w~/! 	3Cd{  #d)S!12	33
 >29+>>=yr   c                    t         j                         }|D cg c]  }t        |       }}t         j                  ||d| dz        }t        j                  |j                        }|d   du s
J d|        yc c}w )u`   9. 폰트 fallback 차단 — 모든 슬라이드 HTML body의 font-family가 Pretendard 시작.r   fontr{   r   Tzfont stack check failed: N)r   list_layoutsrx   r   r   verify_font_stack_in_htmlr   )r   r|   r   r}   r   r   s         r   +test_scenario_9_font_stack_pretendard_firstr   p  s    **,L5ABTl4(BNB!%f$	  F 44V5F5FGF&>T!G%>vh#GG! Cs   A:c                    dg}t        d      g}t        j                  ||d| dz        }d|j                  v sJ |j                  d   j                  d      }d	|v sJ d
|v sJ d|v sJ y)uI   10. design-md inject — 디자인 토큰이 HTML/CSS에 반영되는지.rk   r   tokensr{   primaryr   r   r   z--color-primary:
PretendardzNoto Sans KRN)rx   r   r   r   r   r   r   r|   r}   r   htmls        r   !test_scenario_10_design_md_injectr     s    =L";/0N!%h&	  F %%%Q))7);D%%%4T!!!r   c                    dg}t        d      g}t        j                  ||d| dz        }|j                  d   j	                         sJ |j                  d   j                  d      }d|v sJ y	)
uV   11. fallback 토큰 — 잘못된 brand 입력 시 fallback_tokens()로 정상 빌드.rp   z$this-brand-definitely-does-not-existfallbackr{   r   r   r   r   N)rx   r   r   r   r   r   r   s        r   .test_scenario_11_fallback_tokens_invalid_brandr     s    9L"7+,N!%4j(	  F Q&&(((Q))7);D4r   c                    t         dz  } | j                         sJ | j                  dd      5 }t        j                  |      }ddd       j                  di       }h d}t        |j                               |k(  s$J dt        |j                               |z          |j                         D ]  \  }}t         |d	   z  }|j                         sJ d
| d|        |j                  dd      5 }t        j                  |      }ddd       dv s
J d|        d|v s
J d|        |d   D ]  }	|	|d   v rJ d|	 d|          y# 1 sw Y   xY w# 1 sw Y   SxY w)uH   12. registry.json 무결성 — 10종 모두 존재 + vars 스키마 OK.zregistry.jsonrr   r   Nlayouts>
   rt   ro   rp   rl   rm   rq   rn   rr   rs   rk   zmissing/extra layouts: schemazschema missing for z: varszvars missing in schema korean_slotszkorean_slots missing in zslot z not in vars for )	TEMPLATES_DIRr   openjsonloadr   setkeysitems)
registry_pathfregistryr   expectedr   metaschema_pathr   slots
             r   #test_scenario_12_registry_integrityr     s   !O3M!!!			C'		2  a99Q< ll9b)GH w||~(*f.Ec',,.FY\dFdEe,ff* mmo 	Q
d#d8n4!!#P':4&;-%PP#cG4 	"YYq\F	"A#:4&!AA'J+CD6)JJ'>* 	QD6&>)PU4&8I$+PP)	Q	Q   	" 	"s   E5EEE&	c                     t         dz  } | j                         sJ | j                  d      }|j                  d      sJ d|v sJ d|v sJ y)u6   SKILL.md에 name/description frontmatter가 있는지.zSKILL.mdr   r   z---zname: magazine-ppt-kozdescription:N)
SKILL_ROOTr   r   
startswith)skill_mdr   s     r   !test_skill_md_frontmatter_presentr     s]    J&H??w/D??5!!!"d***T!!!r   c                     d} t        t        j                  d            }g }|D ]  }|j                  d      }| D ]  }t	        j
                  dt	        j                  |       |t        j                        r|j                  t        |      |f       t	        j
                  dt	        j                  |       d|t        j                        s|j                  t        |      |f         |r
J d|        y	)
uA   urlopen / requests / httpx import 0건 (IDS §0.5 보강 검사).)zurllib.requestrequestshttpxaiohttpr   r   r   r   r   z	\s+importzhttp client imports found: N)
r   r   r   r   r   r   r   r   r   r   )	forbiddenr   r   r   r   r   s         r   test_no_http_client_importsr    s    BIK%%f-.H')I 3~~w~/ 	3CyyM"))C.)9:D",,O  #d)S!12yyK		#'7yA4V  #d)S!12		33 C7	{CC=yr   )r   r   returnr   )r  bool) )ru   r   rv   r   r  zdict[str, str])r   r   r  None)r  r	  ))__doc__
__future__r   importlib.utilr	   r   r   r   pathlibr   typingr   r   r   r   r   r   r   insertr   r   r   markdesign_team
pytestmarkr   rx   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r   r   r   <module>r     s    #   	 
    >?
9$[({388#HHOOAs;'( L)
/ [[$$
8wz)4'*'"W*)>&4B2?(H"". (Q:"Dr   