
    i&                    l   d Z ddlm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  ee      j!                         j"                  d   ZddZ edd      Z ed	d
      Z ej,                  dej.                        Zd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) u>  tests/regression/test_dashboard_report_hardening_2487.py — task-2487 회귀 테스트 (Group C).

dashboard/helpers.py의 prefix 제거 정규식과 report_parser.py의 task_id 추출이
V2 패턴(retry/phase suffix)을 올바르게 처리하는지 검증한다.

헤임달(개발2팀 테스터) 작성 / task-2487.
    )annotationsN)Path   c                <   t         |z  }t        j                  j                  | t	        |            }||j
                  t        d|       t        j                  j                  |      }|t        j                  | <   |j
                  j                  |       |S )Nzcannot load spec for )	WORKSPACE	importlibutilspec_from_file_locationstrloaderImportErrormodule_from_specsysmodulesexec_module)mod_namefile_rel	file_pathspecmodules        f/home/jay/workspace/.worktrees/task-2487-dev2/tests/regression/test_dashboard_report_hardening_2487.py_load_moduler      s    H$I>>11(C	NKD|t{{*1)=>>^^,,T2F"CKKKKF#M    helpers_2487_dashzdashboard/helpers.pyreport_parser_2487report_parser.pyuO   ^(?:task-\d+(?:_\d+\.\d+)?(?:_[a-z])?(?:\+\d+)?|Task\s+\d+[\.\d]*)\s*[:：]?\s*c                J    t         j                  d|       j                         S )N )_DASH_PREFIX_REsubstrip)titles    r   _strip_prefixr#   0   s    r5)//11r   c                    t        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  }t        j                  d|       dz   d	|iz  }t        t        j                  |            d
x}}y
)u9   'task-1234+1: 제목' → '제목' (retry suffix 제거).u   task-1234+1: 제목   제목==z%(py0)s == %(py3)sresultpy0py3   expected '제목', got 
>assert %(py5)spy5N
r#   
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_saferepr_format_assertmsgAssertionError_format_explanationr)   @py_assert2@py_assert1@py_format4@py_format6s        r   !test_dashboard_prefix_strip_retryr?   9   sv    01FC6XCCC6XCCCCCC6CCC6CCCXCCC!8
CCCCCCCr   c                    t        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  }t        j                  d|       dz   d	|iz  }t        t        j                  |            d
x}}y
)u;   'task-1234_1.2: 제목' → '제목' (phase suffix 제거).u   task-1234_1.2: 제목r%   r&   r(   r)   r*   r-   r.   r/   Nr0   r:   s        r   !test_dashboard_prefix_strip_phaserA   ?   sv    23FC6XCCC6XCCCCCC6CCC6CCCXCCC!8
CCCCCCCr   c                    t        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  }t        j                  d|       dz   d	|iz  }t        t        j                  |            d
x}}y
)u_   'task-1234_1.2_a+3: 긴 제목 텍스트' → '긴 제목 텍스트' (전체 V2 suffix 제거).u'   task-1234_1.2_a+3: 긴 제목 텍스트u   긴 제목 텍스트r&   r(   r)   r*   got r.   r/   Nr0   r:   s        r   0test_dashboard_prefix_strip_phase_parallel_retryrD   E   sx    DEF+>6++>>>6+>>>>>>6>>>6>>>+>>>tF:->>>>>>>r   c                    t        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  }t        j                  d|       dz   d	|iz  }t        t        j                  |            d
x}}y
)uQ   'task-1234: 기본 제목' → '기본 제목' (base ID만 있을 때도 제거).u   task-1234: 기본 제목u   기본 제목r&   r(   r)   r*   rC   r.   r/   Nr0   r:   s        r   %test_dashboard_prefix_strip_base_onlyrF   K   su    56F$76_$7776_77777767776777_777VJ&7777777r   c                    t        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  }t        j                  d|       dz   d	|iz  }t        t        j                  |            d
x}}y
)uL   콜론 없는 'task-1234_1.2 제목' → '제목' (공백 구분도 처리).u   task-1234_1.2 제목r%   r&   r(   r)   r*   rC   r.   r/   Nr0   r:   s        r   $test_dashboard_prefix_strip_no_colonrH   Q   su    12F06X0006X00000060006000X000fZ0000000r   c                    t        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  }t        j                  d|       dz   d|iz  }t        t        j                  |            d	x}}y	)
u7   task ID 없는 순수 제목은 변경되지 않는다.u   순수한 제목 텍스트r&   r(   r)   r*   rC   r.   r/   Nr0   r:   s        r   'test_dashboard_prefix_strip_plain_titlerJ   W   sx    78F1D611DDD61DDDDDD6DDD6DDD1DDDT&3DDDDDDDr   c                    t         dz  dz  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  }t        j                  d
      dz   d|iz  }t        t        j                  |            dx}}y)uJ   dashboard/helpers.py 소스에 V2 phase(_\d+\.\d+) 패턴이 존재한다.	dashboard
helpers.pyutf-8encoding	_\d+\.\d+inz%(py1)s in %(py3)ssrcpy1r,   uV   dashboard/helpers.py prefix 제거 정규식에 V2 언더스코어 phase 토큰 없음r.   r/   Nr   	read_textr1   r2   r6   r3   r4   r5   r7   r8   r9   rU   @py_assert0r;   r=   r>   s        r   ,test_dashboard_helpers_source_has_v2_patternr\   b   s    {"\1
<
<g
<
NC <3  <3                  	a    r   c                    t         dz  dz  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  }t        j                  d
      dz   d|iz  }t        t        j                  |            dx}}y)uE   dashboard/helpers.py 소스에 V2 retry(+\d+) 패턴이 존재한다.rL   rM   rN   rO   \+\d+rR   rT   rU   rV   uL   dashboard/helpers.py prefix 제거 정규식에 V2 retry(+\d+) 토큰 없음r.   r/   NrX   rZ   s        r   /test_dashboard_helpers_source_has_retry_patternr_   j   s    {"\1
<
<g
<
NC 8s?  8s                  	X    r   c                 X   ddl } ddl}d}| j                  dddd      5 }|j                  |       |j                  }ddd       	 t
        j                        }|d	   }d
}||k(  }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }	t        j                  d|d	         dz   d|	iz  }
t        t        j                  |
            dx}x}}|j                  |       y# 1 sw Y   xY w# |j                         w xY w)uD   보고서 H1 '# task-1234 완료 보고서' 에서 task-1234 추출.r   Nu$   # task-1234 완료 보고서

내용w.mdFrN   modesuffixdeleterP   task_idz	task-1234r&   z%(py1)s == %(py4)srW   py4rC   
>assert %(py6)spy6tempfileosNamedTemporaryFilewritenamerpparse_reportr1   r2   r6   r7   r8   r9   unlinkrn   ro   contentftmpr)   r[   @py_assert3r;   @py_format5@py_format7s              r   *test_report_parser_task_id_from_title_baser}   w   s    6G		$	$#eET[	$	\ `a	ff%i MKM K/MMM KMMM MMMKMMM4y8I7L1MMMMMMMM
		#  			#   D
B1D 
DD)c                 X   ddl } ddl}d}| j                  dddd      5 }|j                  |       |j                  }ddd       	 t
        j                        }|d	   }d
}||k(  }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }	t        j                  d|d	         dz   d|	iz  }
t        t        j                  |
            dx}x}}|j                  |       y# 1 sw Y   xY w# |j                         w xY w)uL   보고서 H1 '# task-1234_1.2 완료 보고서' 에서 task-1234_1.2 추출.r   Nu(   # task-1234_1.2 완료 보고서

내용ra   rb   FrN   rc   rg   task-1234_1.2r&   rh   ri   rC   rk   rl   rm   rv   s              r   +test_report_parser_task_id_from_title_phaser      s    :G		$	$#eET[	$	\ `a	ff%i QOQ O3QQQ OQQQ QQQOQQQtF9<M;P5QQQQQQQQ
		#  			#r~   c                 X   ddl } ddl}d}| j                  dddd      5 }|j                  |       |j                  }ddd       	 t
        j                        }|d	   }d
}||k(  }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }	t        j                  d|d	         dz   d|	iz  }
t        t        j                  |
            dx}x}}|j                  |       y# 1 sw Y   xY w# |j                         w xY w)uH   보고서 H1 '# task-1234+1 완료 보고서' 에서 task-1234+1 추출.r   Nu&   # task-1234+1 완료 보고서

내용ra   rb   FrN   rc   rg   task-1234+1r&   rh   ri   rC   rk   rl   rm   rv   s              r   +test_report_parser_task_id_from_title_retryr      s    8G		$	$#eET[	$	\ `a	ff%i OMO M1OOO MOOO OOOMOOOT&:K9N3OOOOOOOO
		#  			#r~   c                 X   ddl } ddl}d}| j                  dddd      5 }|j                  |       |j                  }ddd       	 t
        j                        }|d	   }d
}||k(  }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }	t        j                  d|d	         dz   d|	iz  }
t        t        j                  |
            dx}x}}|j                  |       y# 1 sw Y   xY w# |j                         w xY w)uC   보고서 H1 '# task-1234_1.2_a+3' 에서 task-1234_1.2_a+3 추출.r   Nu   # task-1234_1.2_a+3

내용ra   rb   FrN   rc   rg   ztask-1234_1.2_a+3r&   rh   ri   rC   rk   rl   rm   rv   s              r   -test_report_parser_task_id_from_title_full_v2r      s    -G		$	$#eET[	$	\ `a	ff%i U$7U $77UUU $7UUU UUU$7UUU4y@Q?T9UUUUUUUU
		#  			#r~   c                 X   ddl } ddl}d}| j                  dddd      5 }|j                  |       |j                  }ddd       	 t
        j                        }|d	   }d
}||k(  }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }	t        j                  d|d	         dz   d|	iz  }
t        t        j                  |
            dx}x}}|j                  |       y# 1 sw Y   xY w# |j                         w xY w)u@   '**작업 ID**: task-1234_1.2' 메타 필드에서 V2 ID 추출.r   Nu:   # 완료 보고서

- **작업 ID**: task-1234_1.2

내용ra   rb   FrN   rc   rg   r   r&   rh   ri   rC   rk   rl   rm   rv   s              r   *test_report_parser_task_id_from_meta_fieldr      s    NG		$	$#eET[	$	\ `a	ff%i QOQ O3QQQ OQQQ QQQOQQQtF9<M;P5QQQQQQQQ
		#  			#r~   c                    ddl } ddl}d}| j                         }|j                  j	                  |d      }t        |dd      5 }|j                  |       ddd       	 t        j                  |      }|d   }d	}||k(  }	|	st        j                  d
|	fd||f      t        j                  |      t        j                  |      dz  }
t        j                  d|d         dz   d|
iz  }t        t        j                  |            dx}x}	}|j                  |       |j!                  |       y# 1 sw Y   xY w# |j                  |       |j!                  |       w xY w)u>   파일명 'task-1234+1.md' 에서 basename으로 V2 ID 추출.r   Nu   # 완료 보고서

내용ztask-1234+1.mdra   rN   rO   rg   r   r&   rh   ri   rC   rk   rl   )rn   ro   mkdtemppathjoinopenrq   rs   rt   r1   r2   r6   r7   r8   r9   ru   rmdir)rn   ro   rw   tmp_dirry   rx   r)   r[   rz   r;   r{   r|   s               r   +test_report_parser_task_id_from_basename_v2r      s
   ,G G
'',,w 0
1C	c3	) Q	%i OMO M1OOO MOOO OOOMOOOT&:K9N3OOOOOOOO
		#
  			#
s   D4 B1E  4D= $E$c                 b   ddl } ddl}d}| j                  dddd      5 }|j                  |       |j                  }ddd       	 t
        j                        }|d	   rd
}|d	   }||v }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }	t        j                  d|d	   d      dz   d|	iz  }
t        t        j                  |
            dx}x}}|j                  |       y# 1 sw Y   xY w# |j                         w xY w)uH   'task/task-1234_1.2-dev2' 형식 merge_branch를 보고서에서 추출.r   NuD   # 보고서

머지 판단: 필요

branch: task/task-1234_1.2-dev2
ra   rb   FrN   rc   merge_branchz_1.2rR   z%(py1)s in %(py4)sri   merge_branch u   에 phase suffix 없음rk   rl   rm   rv   s              r   (test_report_parser_merge_branch_v2_phaser      s   YG		$	$#eET[	$	\ `a	ff%.! VN3 633  63  I   I 4     ~ 699PQ     			#  			#   DB6D DD.c                 b   ddl } ddl}d}| j                  dddd      5 }|j                  |       |j                  }ddd       	 t
        j                        }|d	   rd
}|d	   }||v }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }	t        j                  d|d	   d      dz   d|	iz  }
t        t        j                  |
            dx}x}}|j                  |       y# 1 sw Y   xY w# |j                         w xY w)uF   'task/task-1234+1-dev3' 형식 merge_branch를 보고서에서 추출.r   NuB   # 보고서

머지 판단: 필요

branch: task/task-1234+1-dev3
ra   rb   FrN   rc   r   z+1rR   r   ri   r   u   에 retry suffix 없음rk   rl   rm   rv   s              r   (test_report_parser_merge_branch_v2_retryr      s   WG		$	$#eET[	$	\ `a	ff%.! 6.1 411  41  I   I 2     ~ 699PQ     			#  			#r   c                 "   t         dz  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  }t        j                  d	      d
z   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  }t        j                  d      d
z   d|iz  }t        t        j                  |            dx}}y)uL   report_parser.py 소스의 H1 추출 정규식이 V2 suffix를 포함한다.r   rN   rO   rQ   rR   rT   rU   rV   u7   report_parser.py H1 정규식에 V2 phase 패턴 없음r.   r/   Nr^   u7   report_parser.py H1 정규식에 V2 retry 패턴 없음rX   rZ   s        r   .test_report_parser_source_has_v2_title_patternr      s    ))
4
4g
4
FCY<3YYY<3YYY<YYYYYY3YYY3YYYY YYYYYYYU8s?UUU8sUUU8UUUUUUsUUUsUUUUUUUUUUUr   )r   r   r   r   )r"   r   returnr   )+__doc__
__future__r   builtinsr3   _pytest.assertion.rewrite	assertionrewriter1   importlib.utilr   rer   pathlibr   __file__resolveparentsr   r   helpersrs   compile
IGNORECASEr   r#   r?   rA   rD   rF   rH   rJ   r\   r_   r}   r   r   r   r   r   r   r   r    r   r   <module>r      s    #     	 
 N""$,,Q/	 *,B
C &(:; "**VMM2DD?81E.$$Vr   