
    9bj                       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
mZ ddlZ ed      Z ee      e	j                  vr"e	j                  j!                  d ee             ddlmZmZ  G d d      Z ej*                         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$ddZ%y)u   task-2410: 3문서 API 테스트.

dashboard.routes_get 의 handle_get_three_docs_list / handle_get_three_docs_doc
핸들러가 type 화이트리스트, path traversal, 정상 조회 시나리오를
올바르게 처리하는지 검증한다.
    )annotationsN)Pathz/home/jay/workspace)handle_get_three_docs_dochandle_get_three_docs_listc                      e Zd ZddZy)_FakeLoaderc                     y N )selfs    O/home/jay/workspace/.worktrees/task-2696-dev7/tests/dev7/test_three_docs_api.py
reload_allz_FakeLoader.reload_all   s        N)returnNone)__name__
__module____qualname__r   r   r   r   r   r      s    r   r   c                     t               S r
   )r   r   r   r   loaderr      s
    =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  }dd|iz  }t        t        j                  |            d x}}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 }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   }h d}t        |      }	||	k  }|st        j                  d|fd||	f      t        j                  |      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z  }dd|iz  }t        t        j                  |            d x}x}}	|d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd |iz  }t        t        j                  |            d x}x}}y )!Nz/api/three-docs?type=system   ==z%(py0)s == %(py3)scodepy0py3assert %(py5)spy55assert %(py4)s
{%(py4)s = %(py0)s(%(py1)s, %(py2)s)
}
isinstancedatalistr   py1py2py4r   )>)z/%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} > %(py6)slenr   r'   r   py6assert %(py8)spy8>   idtypetitlehas_plan
updated_athas_checklisthas_context_notes)<=)z0%(py1)s <= %(py6)s
{%(py6)s = %(py3)s(%(py4)s)
}setitem)r'   r   r)   r-   r1   systemz%(py1)s == %(py4)sr'   r)   assert %(py6)sr-   )r   
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanationr#   r%   r+   r8   )r   r   r$   @py_assert2@py_assert1@py_format4@py_format6@py_assert3@py_format5@py_assert5@py_assert4@py_format7@py_format9r9   @py_assert0s                  r   test_list_system_returns_arrayrQ   &   sn   +,I6RJD$43;43443dD!!!!!!!!:!!!:!!!!!!d!!!d!!!!!!D!!!D!!!!!!!!!!t9q9q=9q33tt9q7Dbofijnfoobfooooobfooooboooooofiooofioooooojnooojnooofoooooooo<#8#<8####<8###<###8#######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  }dd|iz  }t        t        j                  |            d x}}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 }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}
}	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}}y )Nz/api/three-docs?type=projectr   r   r   r   r   r    r!   r"   r#   r$   r%   r&      >=z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} >= %(py6)sr+   r,   r.   r/   c              3  ,   K   | ]  }|d    dk(    yw)r1   projectNr   .0r9   s     r   	<genexpr>z2test_list_project_returns_array.<locals>.<genexpr>6   s     :TtF|y(:   ,assert %(py4)s
{%(py4)s = %(py0)s(%(py2)s)
}allr   r(   r)   )r   r>   r?   r@   rA   rB   rC   rD   rE   r#   r%   r+   r^   )r   r   r$   rF   rG   rH   rI   rJ   rK   rL   rM   rN   rO   s                r   test_list_project_returns_arrayr`   0   s   +,JFSJD$43;43443dD!!!!!!!!:!!!:!!!!!!d!!!d!!!!!!D!!!D!!!!!!!!!!t99>933tt9:T::3:::::::::3:::3::::::::::::::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  }dd|iz  }t        t        j                  |            d x}}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 }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}
}	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}}t        ||dd        D ]  \  }}|d   }|d   }||k\  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d x}x}} y )Nz/api/three-docs?type=taskr   r   r   r   r   r    r!   r"   r#   r$   r%   r&   rS   rT   rV   r+   r,   r.   r/   c              3  ,   K   | ]  }|d    dk(    yw)r1   taskNr   rY   s     r   r[   z6test_list_task_returns_array_sorted.<locals>.<genexpr>>   s     7$tF|v%7r\   r]   r^   r_   r4   )z%(py1)s >= %(py4)sr<   r=   r-   )r   r>   r?   r@   rA   rB   rC   rD   rE   r#   r%   r+   r^   zip)r   r   r$   rF   rG   rH   rI   rJ   rK   rL   rM   rN   rO   prevcurrrP   s                   r   #test_list_task_returns_array_sortedrg   9   sW   +,GPJD$43;43443dD!!!!!!!!:!!!:!!!!!!d!!!d!!!!!!D!!!D!!!!!!!!!!t99>933tt97$7737777777773777377777777777777$QR) 8
dL!7T,%77!%77777!%7777!777%777777778r   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  }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 )Nz/api/three-docs?type=evil  r   r   r   r   r    r!   errorinz%(py1)s in %(py3)sr$   r'   r   	r   r>   r?   r@   rA   rB   rC   rD   rE   r   r   r$   rF   rG   rH   rI   rP   s           r   "test_list_invalid_type_returns_400rq   D   s    +,GPJD$43;434437d?7d7ddr   c                n   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  }dd|iz  }t        t        j                  |            d x}}y )	Nz/api/three-docsri   r   r   r   r   r    r!   ro   r   r   _rF   rG   rH   rI   s          r   "test_list_missing_type_returns_400ru   J   sk    ():FCGD!43;43443r   c                n   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  }dd|iz  }t        t        j                  |            d x}}y )	Nz)/api/three-docs/system/..%2F..%2Fetc/planri   r   r   r   r   r    r!   	r   r>   r?   r@   rA   rB   rC   rD   rE   rs   s          r   test_doc_path_traversal_blockedrx   R   sl    '(SU[\GD!43;43443r   c                n   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  }dd|iz  }t        t        j                  |            d x}}y )	Nz&/api/three-docs/project/ins%2Furo/planri   r   r   r   r   r    r!   rw   rs   s          r   !test_doc_topic_with_slash_blockedrz   W   sl    '(PRXYGD!43;43443r   c                n   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  }dd|iz  }t        t        j                  |            d x}}y )	Nz/api/three-docs/evil/topic/planri   r   r   r   r   r    r!   rw   rs   s          r   test_doc_invalid_type_blockedr|   \   sk    '(I6RGD!43;43443r   c                n   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  }dd|iz  }t        t        j                  |            d x}}y )	Nz*/api/three-docs/system/3docs-schema/secretri   r   r   r   r   r    r!   rw   rs   s          r   test_doc_invalid_doc_blockedr~   a   sl    '(TV\]GD!43;43443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  }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 )Nz*/api/three-docs/system/anu-guide/checklist  r   r   r   r   r    r!   expected_pathrk   rm   r$   rn   rw   rp   s           r   !test_doc_missing_file_returns_404r   f   s    *+WY_`JD$43;43443"?d""""?d"""?""""""d"""d"""""""r   c                L   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  }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}}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}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            d x}x}}|d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            d x}x}}|d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            d x}x}}y )Nz-/api/three-docs/project/anu-guide-system/planr   r   r   r   r   r    r!   contentrk   rm   r$   rn   sizemtimedocplanr;   r<   r=   r-   topiczanu-guide-systemr1   rX   rw   r   r   r$   rF   rG   rH   rI   rP   rJ   rK   rN   s              r   'test_doc_valid_project_plan_returns_200r   m   sf   *7JD$ 43;434439996T>6T6TT7d?7d7dd; & ;&    ;&   ;   &       =...=.....=....=...........<$9$<9$$$$<9$$$<$$$9$$$$$$$r   c                   ddl m} dz  }|j                          |dz  j                  dd       |j                  dfd}|j                  |d	|       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  }
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   }|j                  }d} ||      }|stdt        j                  |      t        j                  |      t        j                  |      t        j                  |      dz  }t        t        j                  |            dx}x}x}}y)u\   task topic에 plan.md만 있을 때 context-notes 요청 → 404 + expected_path 키 포함.r   Nmy-task-topicplan.md# My Task Plan
utf-8encodingc                "    | dk(  rS  |       S Nrc   r   doc_typeorig_get_basetmp_paths    r   
_fake_basezVtest_404_response_includes_expected_path_for_missing_context_notes.<locals>._fake_base       vOX&&r   _three_docs_get_base_dirz0/api/three-docs/task/my-task-topic/context-notesr   r   r   r   r   r    r!   r   rk   rm   r$   rn   zcontext-notes.mdJassert %(py7)s
{%(py7)s = %(py3)s
{%(py3)s = %(py1)s.endswith
}(%(py5)s)
}r'   r   r!   py7r   strdashboard.routes_get
routes_getmkdir
write_textr   setattrr   r>   r?   r@   rA   rB   rC   rD   rE   endswithr   r   monkeypatchrg	topic_dirr   r   r$   rF   rG   rH   rI   rP   rM   @py_assert6@py_format8r   s    `              @r   Btest_404_response_includes_expected_path_for_missing_context_notesr   ~   s    & ?*IOO&&'9G&L //M'
 6
C*:FJD$ 43;43443"?d""""?d"""?""""""d"""d""""""" = ))=*<=)*<===== ===)===*<==========r   c                   ddl m} dz  }|j                          |dz  j                  dd       |j                  dfd}|j                  |d	|       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  }
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   }|j                  }d} ||      }|stdt        j                  |      t        j                  |      t        j                  |      t        j                  |      dz  }t        t        j                  |            dx}x}x}}y)uX   task topic에 plan.md만 있을 때 checklist 요청 → 404 + expected_path 키 포함.r   Nr   r   r   r   r   c                "    | dk(  rS  |       S r   r   r   s    r   r   zRtest_404_response_includes_expected_path_for_missing_checklist.<locals>._fake_base   r   r   r   z,/api/three-docs/task/my-task-topic/checklistr   r   r   r   r   r    r!   r   rk   rm   r$   rn   zchecklist.mdr   r   r   r   r   s    `              @r   >test_404_response_includes_expected_path_for_missing_checklistr      s    &?*IOO&&'9G&L//M'
 6
C*6JD$ 43;43443"?d""""?d"""?""""""d"""d""""""" 9 ))9.9).99999 999)999.9999999999r   c                   ddl m} dz  j                  dd       |j                  dfd}|j	                  |d|       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  }	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}}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  }	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}}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  }	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)uO   system 타입 단독 .md 파일: context-notes/checklist → 404, plan → 200.r   Nzfoo.mdz
# Foo Doc
r   r   c                "    | dk(  rS  |       S )Nr:   r   r   s    r   r   zGtest_system_single_md_returns_404_for_non_plan_docs.<locals>._fake_base   s    xOX&&r   r   z(/api/three-docs/system/foo/context-notesr   r   r   r   r   r    r!   r   rk   rm   r$   rn   z$/api/three-docs/system/foo/checklistz/api/three-docs/system/foo/planr   r   r   )r   r   r   r   r   r   r>   r?   r@   rA   rB   rC   rD   rE   )r   r   r   r   r   r   r$   rF   rG   rH   rI   rP   r   s    `          @r   3test_system_single_md_returns_404_for_non_plan_docsr      s    & $$]W$E//M'
 6
C ++UW]^JD$43;43443"?d""""?d"""?""""""d"""d""""""" ++QSYZJD$43;43443"?d""""?d"""?""""""d"""d""""""" ++LfUJD$43;43443999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  }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}|d
   }||v }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            d	x}x}}y	)uQ   doc 이름이 올바르지 않을 때 → 400 + error 키 + 'Invalid doc' 포함.z//api/three-docs/system/3docs-schema/invalid-docri   r   r   r   r   r    r!   Nrj   rk   rm   r$   rn   zInvalid doc)z%(py1)s in %(py4)sr<   r=   r-   rw   r   s              r   4test_400_response_has_error_key_for_invalid_doc_namer      s   *96JD$ 43;434437d?7d7dd)DM)=M))))=M)))=)))M)))))))r   )r   r   )r   r   r   r   )r   r   r   r   r   zpytest.MonkeyPatchr   r   )&__doc__
__future__r   builtinsr@   _pytest.assertion.rewrite	assertionrewriter>   syspathlibr   pytestWORKSPACE_ROOTr   pathinsertr   r   r   r   fixturer   rQ   r`   rg   rq   ru   rx   rz   r|   r~   r   r   r   r   r   r   r   r   r   <module>r      s'   #   
  +,~chh&HHOOAs>*+ 
  $;8



#%">>#'>6H>	>:::#':6H:	:6#'6H	D*r   