
    Mi                     z   d Z ddlZddlmc mZ ddlZddlZddl	m
Z
 ddlZej                  j                  d e e
e      j                   j                   j                                ddlmZmZmZmZmZ  e
d      Zde
deded	e
f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/skill_loader.py 테스트 스위트    N)Path)SkillDetailSkillSummarylist_skills
load_skill
view_skillz/home/jay/workspace/skillstmp_pathnamecontentreturnc                 `    | |z  }|j                  d       |dz  j                  |d       |S )u.   테스트용 스킬 디렉토리 생성 헬퍼T)parentsSKILL.mdzutf-8)encoding)mkdir
write_text)r	   r
   r   	skill_dirs       4/home/jay/workspace/utils/tests/test_skill_loader.pymake_skill_dirr      s7    4IOODO!''''B    c                       e Zd ZdZddZy)TestSkillSummaryu'   SkillSummary dataclass 구조 테스트Nc                    t        ddd      }|j                  }d}||k(  }|st        j                  d|fd||f      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                  }d}||k(  }|st        j                  d|fd||f      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                  }d}||k(  }|st        j                  d|fd||f      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}}y)   필수 필드 존재 확인test   설명general)r
   descriptioncategory==z,%(py2)s
{%(py2)s = %(py0)s.name
} == %(py5)sspy0py2py5assert %(py7)spy7Nz3%(py2)s
{%(py2)s = %(py0)s.description
} == %(py5)s)z0%(py2)s
{%(py2)s = %(py0)s.category
} == %(py5)s)r   r
   
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanationr   r   )selfr#   @py_assert1@py_assert4@py_assert3@py_format6@py_format8s          r   test_fields_existz"TestSkillSummary.test_fields_exist"   sW   f(YOvvvvqqv}}((}((((}((((((q(((q(((}((((((((((zz&Y&zY&&&&zY&&&&&&q&&&q&&&z&&&Y&&&&&&&r   r   N__name__
__module____qualname____doc__r9    r   r   r   r      s
    1'r   r   c                       e Zd ZdZddZy)TestSkillDetailu&   SkillDetail dataclass 구조 테스트Nc                 h   t        dddgg d      }|j                  }d}||k(  }|st        j                  d|fd||f      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                  }dg}||k(  }|st        j                  d|fd||f      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                  }g }||k(  }|st        j                  d|fd||f      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                  }d}||k(  }|st        j                  d|fd||f      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}}y)r   r   r   trigger1z/path/to/SKILL.md)r
   r   triggersrequires	full_pathr    r"   dr$   r(   r)   N)z0%(py2)s
{%(py2)s = %(py0)s.triggers
} == %(py5)s)z0%(py2)s
{%(py2)s = %(py0)s.requires
} == %(py5)s)z1%(py2)s
{%(py2)s = %(py0)s.full_path
} == %(py5)s)r   r
   r+   r,   r-   r.   r/   r0   r1   r2   rE   rF   rG   )r3   rH   r4   r5   r6   r7   r8   s          r   r9   z!TestSkillDetail.test_fields_exist-   s     \)
 vvvvqqvzz)j\)z\))))z\))))))q)))q)))z)))\)))))))zzRzRzRqqzR{{111{11111{1111111q111q111{11111111111r   r:   r;   r@   r   r   rB   rB   *   s
    02r   rB   c                       e Zd ZdZdeddfdZdeddfdZdeddfdZdeddfdZdeddfd	Z	dd
Z
ddZdeddfdZy)TestListSkillsu   list_skills() 테스트r	   r   Nc                 t   t        |dd       t        |      }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)	u   반환 타입은 listskill-au5   ---
name: skill-a
description: 설명A
---
# skill-a
5assert %(py4)s
{%(py4)s = %(py0)s(%(py1)s, %(py2)s)
}
isinstanceresultlistr%   py1r&   py4N)r   r   rN   rP   r-   r.   r+   r/   r0   r1   r2   )r3   r	   rO   r6   @py_format5s        r   test_returns_listz TestListSkills.test_returns_list?   s    x,hiX&&$''''''''z'''z''''''&'''&''''''$'''$''''''''''r   c                    t        |dd       t        |dd       |dz  j                          t        |      }|D cg c]  }|j                   }}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}||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}||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c c}w )u&   SKILL.md 있는 디렉토리만 포함rL   u+   ---
name: skill-a
description: 설명A
---
zskill-bu+   ---
name: skill-b
description: 설명B
---
zno-skillinz%(py1)s in %(py3)snamesrR   py3assert %(py5)sr'   N)not in)z%(py1)s not in %(py3)s)r   r   r   r
   r+   r,   r0   r-   r.   r/   r1   r2   )	r3   r	   rO   r#   rZ   @py_assert0@py_assert2@py_format4r7   s	            r   test_finds_skills_with_skill_mdz.TestListSkills.test_finds_skills_with_skill_mdE   s^   x,]^x,]^	J	%%'X&!'(A((!yE!!!!yE!!!y!!!!!!E!!!E!!!!!!!!yE!!!!yE!!!y!!!!!!E!!!E!!!!!!!&z&&&&z&&&z&&&&&&&&&&&&&&&& )s   Ic                    t        |dd       t        |      }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}}t        d |D              }|j                  }	d}|	|k(  }
|
st        j                  d|
fd|	|f      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}
}y)u%   name, description 올바르게 파싱my-skillu?   ---
name: my-skill
description: 내 스킬 설명
---
# 제목
   )>=)z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} >= %(py6)slenrO   r%   rR   r\   py6assert %(py8)spy8Nc              3   @   K   | ]  }|j                   d k(  s|  yw)rd   Nr
   .0r#   s     r   	<genexpr>zGTestListSkills.test_summary_has_name_and_description.<locals>.<genexpr>Y   s     ?1!&&J*>Q?   u   내 스킬 설명r    r*   skillr$   r(   r)   )r   r   rg   r+   r,   r-   r.   r/   r0   r1   r2   nextr   )r3   r	   rO   r`   @py_assert5r5   @py_format7@py_format9rr   r4   r6   r7   r8   s                r   %test_summary_has_name_and_descriptionz4TestListSkills.test_summary_has_name_and_descriptionQ   s0   jR	
 X&6{a{a{ass66{a???  7$77 $77777 $7777777u777u777 777$77777777r   c                 2   t        |dd       t        |      }t        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}}d}|j                  }	||	v }|st        j                  d|fd||	f      t        j                  |      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}x}}	y)u8   YAML frontmatter 없을 때 # 헤딩에서 설명 추출plain-skillu)   # 플레인 스킬 설명

본문 내용
c              3   @   K   | ]  }|j                   d k(  s|  yw)ry   Nrm   rn   s     r   rp   zFTestListSkills.test_description_fallback_to_heading.<locals>.<genexpr>`   s     CA166]+BaCrq   N)is not)z%(py0)s is not %(py3)srr   r%   r\   r]   r'   u   플레인 스킬 설명rW   )z3%(py1)s in %(py5)s
{%(py5)s = %(py3)s.description
}rR   r\   r'   r(   r)   )r   r   rs   r+   r,   r-   r.   r/   r0   r1   r2   r   )r3   r	   rO   rr   r`   r4   ra   r7   r_   r5   r8   s              r   $test_description_fallback_to_headingz3TestListSkills.test_description_fallback_to_heading\   s    x0^_X&CCTJ  uD    uD      u   u   D       (=E,=,==(,=====(,====(======E===E===,========r   c                 f   t        |      }g }||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)u!   빈 디렉토리는 빈 리스트r    z%(py0)s == %(py3)srO   r|   r]   r'   N	r   r+   r,   r-   r.   r/   r0   r1   r2   )r3   r	   rO   r`   r4   ra   r7   s          r   !test_empty_dir_returns_empty_listz0TestListSkills.test_empty_dir_returns_empty_listd   sd    X&v|vvvr   c                 f   t        d      }g }||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)	u1   존재하지 않는 디렉토리는 빈 리스트z/nonexistent/skills/dirr    r   rO   r|   r]   r'   Nr   )r3   rO   r`   r4   ra   r7   s         r   'test_nonexistent_dir_returns_empty_listz6TestListSkills.test_nonexistent_dir_returns_empty_listi   se    67v|vvvr   c           	         t         j                         st        j                  d       t	        t               }t        |      }d}||kD  }|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}}|D ]x  }|j                  }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t        j                  |      dt        j                         v st        j                  t               rt        j                  t               ndt        j                  |      dz  }t        t        j                  |            d
x}}|j                  }t        |      }d}||kD  }	|	s
t        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                  |      t        j                  |      dz  }dd|iz  }
t        t        j                  |
            d
x}x}x}	}{ y
)u.   실제 스킬 디렉토리에서 로드 성공u   스킬 디렉토리 없음r   >z/%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} > %(py6)srg   rO   rh   rj   rk   NzOassert %(py6)s
{%(py6)s = %(py0)s(%(py3)s
{%(py3)s = %(py1)s.name
}, %(py4)s)
}rN   r#   str)r%   rR   r\   rS   ri   )zI%(py5)s
{%(py5)s = %(py0)s(%(py3)s
{%(py3)s = %(py1)s.name
})
} > %(py8)sr%   rR   r\   r'   rk   assert %(py10)spy10)	SKILL_DIRexistspytestskipr   rg   r+   r,   r-   r.   r/   r0   r1   r2   r
   rN   r   )r3   rO   r`   rt   r5   ru   rv   r#   @py_assert7@py_assert6@py_format11s              r   test_real_skills_dirz#TestListSkills.test_real_skills_dirn   s   !KK45Y'6{Q{Q{Qss66{Q 	#Aff*:fc********:***:******a***a***f******c***c**********vv"3v;"";?""";""""""3"""3""""""q"""q"""v""";""""""""""	#r   c                    t        |dd       t        |      }|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)	u*   반환 항목이 SkillSummary 인스턴스s1z#---
name: s1
description: desc
---
rM   rN   itemr   rQ   N)r   r   rN   r   r-   r.   r+   r/   r0   r1   r2   )r3   r	   rO   r   r6   rT   s         r   $test_returns_skill_summary_instancesz3TestListSkills.test_returns_skill_summary_instancesx   s    x'PQX& 	2DdL11111111:111:111111d111d111111L111L1111111111	2r   r:   )r<   r=   r>   r?   r   rU   rb   rw   r~   r   r   r   r   r@   r   r   rJ   rJ   <   s    !($ (4 (
' 
' 
'	8d 	8t 	8>T >d >$ 4 

#2T 2d 2r   rJ   c                   h    e Zd ZdZdeddfdZdeddfdZdeddfdZdeddfdZdeddfd	Z	dd
Z
y)TestViewSkillu   view_skill() 테스트r	   r   Nc                 z   d}t        |d|       t        |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)	u   SkillDetail 반환uZ   ---
name: my-skill
description: 설명
triggers:
  - trigger1
  - trigger2
---
# my-skill
rd   rM   rN   detailr   rQ   N)r   r   rN   r   r-   r.   r+   r/   r0   r1   r2   )r3   r	   r   r   r6   rT   s         r   test_returns_skill_detailz'TestViewSkill.test_returns_skill_detail   s    G 	 	xW5Hj1&+........z...z......&...&......+...+..........r   c                 V   d}t        |d|       t        |d      }d}|j                  }||v }|st        j                  d|fd||f      t        j
                  |      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}x}}d}|j                  }||v }|st        j                  d|fd||f      t        j
                  |      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}x}}y
)u#   YAML frontmatter의 triggers 파싱uH   ---
name: t-skill
description: 설명
triggers:
  - ship
  - deploy
---
zt-skillshiprW   )z0%(py1)s in %(py5)s
{%(py5)s = %(py3)s.triggers
}r   r}   r(   r)   Ndeploy)r   r   rE   r+   r,   r0   r-   r.   r/   r1   r2   )	r3   r	   r   r   r_   r5   r`   r7   r8   s	            r   %test_parses_triggers_from_frontmatterz3TestViewSkill.test_parses_triggers_from_frontmatter   s    5 	 	xG4Hi0((v((((v(((v(((((((((((((((((((*6??*x?****x?***x******6***6***?*******r   c           	         t        |dd       t        |d      }|j                  }t        |      }|j                  } |       }|sd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                  |      t        j                  |      t        j                  |      dz  }t        t        j                  |            dx}x}x}}y)u   full_path가 절대 경로z	abs-skillz'---
name: abs-skill
description: d
---
zassert %(py9)s
{%(py9)s = %(py7)s
{%(py7)s = %(py5)s
{%(py5)s = %(py0)s(%(py3)s
{%(py3)s = %(py1)s.full_path
})
}.is_absolute
}()
}r   r   )r%   rR   r\   r'   r)   py9N)r   r   rG   r   is_absoluter-   r.   r+   r/   r0   r1   r2   )r3   r	   r   r`   r5   r   @py_assert8@py_format10s           r   test_full_path_is_absolutez(TestViewSkill.test_full_path_is_absolute   s    x.[\Hk2$$3t$%3%113133333333t333t333333F333F333$333%33313333333333r   c                 x    t        j                  t              5  t        |d       ddd       y# 1 sw Y   yxY w)/   존재하지 않는 스킬은 FileNotFoundErrorznonexistent-skillN)r   raisesFileNotFoundErrorr   r3   r	   s     r   !test_raises_for_nonexistent_skillz/TestViewSkill.test_raises_for_nonexistent_skill   s/    ]],- 	6x!45	6 	6 	6   09c                    d}t        |d|       t        |d      }|j                  }d}||k(  }|st        j                  d|fd||f      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}}y
)u   description 필드 추출u;   ---
name: d-skill
description: 상세 설명 텍스트
---
zd-skillu   상세 설명 텍스트r    r*   r   r$   r(   r)   N)r   r   r   r+   r,   r-   r.   r/   r0   r1   r2   )	r3   r	   r   r   r4   r5   r6   r7   r8   s	            r   test_description_extractedz(TestViewSkill.test_description_extracted   s    SxG4Hi0!!>%>>!%>>>>>!%>>>>>>>v>>>v>>>!>>>%>>>>>>>>r   c                 4   t         dz  j                         st        j                  d       t	        t         d      }|j
                  }d}||k(  }|st        j                  d|fd||f      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                  }t        |      }d
}||kD  }	|	s
t        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                  |      t        j                  |      dz  }
dd|
iz  }t        t        j                  |            d	x}x}x}	}|j                   }|j"                  }d} ||      }|sddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      t        j                  |      dz  }
t        t        j                  |
            d	x}x}x}}y	)u   실제 retro 스킬 상세 뷰retrou   retro 스킬 없음r    r"   r   r$   r(   r)   Nr   r   )zM%(py5)s
{%(py5)s = %(py0)s(%(py3)s
{%(py3)s = %(py1)s.triggers
})
} > %(py8)srg   r   r   r   r   ziassert %(py8)s
{%(py8)s = %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.full_path
}.endswith
}(%(py6)s)
})r%   r&   rS   ri   rk   )r   r   r   r   r   r
   r+   r,   r-   r.   r/   r0   r1   r2   rE   rg   rG   endswith)r3   r   r4   r5   r6   r7   r8   r`   r   r   rv   r   rt   s                r   test_real_retro_skillz#TestViewSkill.test_real_retro_skill   s   G#++-KK-.Iw/{{%g%{g%%%%{g%%%%%%v%%%v%%%{%%%g%%%%%%%??'s?#'a'#a''''#a''''''s'''s''''''6'''6'''?'''#'''a'''''''4((44(44444444v444v444444(4444444444444r   r:   )r<   r=   r>   r?   r   r   r   r   r   r   r   r@   r   r   r   r      si     /$ /4 /	+d 	+t 	+44 4D 46$ 64 6
?4 ?D ?5r   r   c                   H    e Zd ZdZdeddfdZdeddfdZdeddfdZd	dZy)
TestLoadSkillu   load_skill() 테스트r	   r   Nc                 z   d}t        |d|       t        |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)	u
   str 반환u   # 스킬 내용

본문.
z
full-skillrM   rN   rO   r   rQ   N)r   r   rN   r   r-   r.   r+   r/   r0   r1   r2   )r3   r	   r   rO   r6   rT   s         r   test_returns_stringz!TestLoadSkill.test_returns_string   s    0xw7Hl3&#&&&&&&&&z&&&z&&&&&&&&&&&&&&&&&#&&&#&&&&&&&&&&r   c                    d}t        |d|       t        |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}}y
)u   SKILL.md 전체 내용 반환uB   ---
name: full
description: d
---
# 제목

본문 전체 내용.
fullu   본문 전체 내용rW   rY   rO   r[   r]   r'   N)
r   r   r+   r,   r0   r-   r.   r/   r1   r2   )r3   r	   r   rO   r_   r`   ra   r7   s           r   test_returns_full_contentz'TestLoadSkill.test_returns_full_content   s{    ]x1Hf-%/%////%///%////////////////r   c                 x    t        j                  t              5  t        |d       ddd       y# 1 sw Y   yxY w)r   zno-such-skillN)r   r   r   r   r   s     r   r   z/TestLoadSkill.test_raises_for_nonexistent_skill   s.    ]],- 	2x1	2 	2 	2r   c                    t         dz  j                         st        j                  d       t	        t         d      }t        |      }d}||kD  }|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}}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   실제 pdf 스킬 전체 로드pdfu   pdf 스킬 없음d   r   r   rg   r   rh   rj   rk   NPDFrW   rY   r[   r]   r'   )r   r   r   r   r   rg   r+   r,   r-   r.   r/   r0   r1   r2   )
r3   r   r`   rt   r5   ru   rv   r_   ra   r7   s
             r   test_real_pdf_skillz!TestLoadSkill.test_real_pdf_skill   s   E!))+KK+,Y.7|!c!|c!!!!|c!!!!!!s!!!s!!!!!!7!!!7!!!|!!!c!!!!!!!uuur   r:   )	r<   r=   r>   r?   r   r   r   r   r   r@   r   r   r   r      sC     'D 'T '0$ 04 02$ 24 2
 r   r   )r?   builtinsr-   _pytest.assertion.rewrite	assertionrewriter+   systempfilepathlibr   r   pathinsertr   __file__parentutils.skill_loaderr   r   r   r   r   r   r   r   rB   rJ   r   r   r@   r   r   <module>r      s    /   
    3tH~,,33::; <  -.	T  s t ' '2 2$A2 A2H15 15h   r   