U
    ÕÃhâ‡  ã                   @   s<  d dl mZmZmZmZ d dlZd dlZd dlm	Z	 d dl
mZmZmZmZmZ d dlmZ d dlZd dlmZ d dlZd dlZd dlmZmZmZ ejejdd	 e e¡Zeeee d
œdd„Z eeee dœdd„Z!ee eeee e"dœdd„Z#eedœdd„Z$eeeef dœdd„Z%deeee dœdd„Z&dS )é    )Úcapture_exceptionÚcapture_messageÚset_tagÚset_contextN©ÚWorkbook©ÚFontÚPatternFillÚ	AlignmentÚBorderÚSide)Údataframe_to_rows)Údatetime)ÚOptionalÚListÚDictz4%(asctime)s - %(name)s - %(levelname)s - %(message)s)ÚlevelÚformat)ÚcontentÚ	base_nameÚreturnc              
   C   sä   |r| st  d¡ tdƒ dS tj dd¡}|› d}tj ||¡}zHtj|dd t|d	d
d}| | ¡ W 5 Q R X t  	d|› ¡ |W S  t
k
rÞ } z4t  d|› d|› ¡ td|› d|› ƒ W Y ¢dS d}~X Y nX dS )zÕSave test script to file.

    Args:
        content (str): Content to write to file
        base_name (str): Base name for the file

    Returns:
        Optional[str]: Filename if successful, None otherwise
    z$Filename and content cannot be emptyu(   âŒ Filename and content cannot be emptyNÚtestsÚ	generatedz.txtT©Úexist_okÚwzutf-8)Úencodingz Test script saved successfully: zError saving file ú: u   âŒ Error saving file )ÚloggerÚerrorÚprintÚosÚpathÚjoinÚmakedirsÚopenÚwriteÚinfoÚ	Exception)r   r   Ú
output_dirÚfilenameÚ	file_pathÚfileÚe© r/   ú?/var/www/html/testcasegenerator.evdpl.com/utils/file_handler.pyÚsave_test_script   s"    


r1   )Ú
test_casesr   r   c              
      sÖ  |r| st  d¡ tdƒ dS |› d}tj dd¡}tj|dd tj ||¡}z4t| ƒ}|svt  d	¡ t	| ƒ}nBt  d
t
|ƒ› d¡ g }| ¡ D ]\}}t	||d}	| |	¡ q˜|rÆt |¡nt ¡ ‰ ˆ jrt  d¡ tdƒ t dgdgdgdgdgdgdœ¡‰ dˆ jkr"dˆ d< nˆ d  d¡ˆ d< ddddddddg}
|
D ]}|ˆ jkrLdˆ |< qLdˆ jkrŠˆ d  dd„ ¡ˆ d< ˆ  d¡‰ dddddddddg	}ˆ jD ]}||kr°| |¡ q°‡ fdd„|D ƒ}ˆ j|d ‰ tj|d!d"v}ˆ j|d#d$d% |jd$ }tˆ jƒD ]J\}}tˆ |  t¡ t
¡ ¡ t
|ƒƒ}t|d& d'ƒ|jtd(| ƒ _ qW 5 Q R X t  d)|› ¡ |W S  t!k
rÐ } z(t  d*|› ¡ td+|› ƒ W Y ¢dS d}~X Y nX dS ),zéSave test cases to Excel file.

    Args:
        test_cases (str): Test cases content to write to Excel
        base_name (str): Base name for the file

    Returns:
        Optional[str]: Filename if successful, None otherwise
    z'Filename and test cases cannot be emptyu+   âŒ Filename and test cases cannot be emptyNz.xlsxr   r   Tr   z6No TEST TYPE sections found, using traditional parsingzFound z TEST TYPE sections)Údefault_sectionzNo test cases could be parsedu$   âš ï¸ No test cases could be parsedzNo test cases foundÚ )ÚSectionÚTitleÚScenarioÚStepsúExpected ResultúActual Resultr5   ÚGeneralr6   r7   ÚPreconditionsr8   r9   r:   ÚStatusÚPriorityc                 S   s*   t | tƒr"d dd„ t| ƒD ƒ¡S | p(dS )NÚ
c                 S   s"   g | ]\}}|d  › d|› ‘qS ©é   z. r/   ©Ú.0ÚiÚstepr/   r/   r0   Ú
<listcomp>t   s     z7save_excel_report.<locals>.<lambda>.<locals>.<listcomp>r4   )Ú
isinstanceÚlistr$   Ú	enumerate)Úxr/   r/   r0   Ú<lambda>t   ó    z#save_excel_report.<locals>.<lambda>c                    s   g | ]}|ˆ j kr|‘qS r/   ©Úcolumns)rC   Úcol©Údfr/   r0   rF      s     
 z%save_excel_report.<locals>.<listcomp>rM   Úopenpyxl)ÚengineFú
Test Cases)ÚindexZ
sheet_nameé   é2   éA   z!Excel report saved successfully: zError saving Excel report: u   âŒ Error saving Excel report: )"r   r    r!   r"   r#   r$   r%   Úextract_test_type_sectionsr(   Úparse_traditional_formatÚlenÚitemsÚextendÚpdÚ	DataFrameÚemptyÚwarningrN   ZfillnaÚapplyÚappendZreindexZExcelWriterÚto_excelZsheetsrI   ÚmaxZastypeÚstrÚminÚcolumn_dimensionsÚchrÚwidthr)   )r2   r   r+   r*   ÚfilepathÚsectionsÚ	test_dataÚsection_nameÚsection_contentZsection_dataZrequired_columnsrO   Zcolumn_orderÚwriterZ	worksheetÚidxÚ
max_lengthr.   r/   rP   r0   Úsave_excel_report2   sz    





ú





þ,rs   )r2   Ústatus_valuesÚsource_typeÚitem_idsr   c           #   
   C   sº  zzddl m} ddlm}m}m}m}m}	 ddlm	}
 |ƒ }| 
|j¡ | d¡}d|› |d< |dd	d
|d _dt ¡  d¡› |d< d|› |d< dd |¡› |d< dt| ƒ› |d< i }| D ]0}| dd¡}| |d¡}| |d¡d ||< qÈd|d< |dd|d _d}| ¡ D ]*\}}|› d|› |d|› < |d7 }q| d¡}dd d!d"d#d$g}t|dƒD ]6\}}|jd||d%}|dd|_|d&d&d'd(|_qnt| d)ƒD ] \}}| dd*¡}d*}d+|kröd,|krö| d+¡d-  d,¡d }|j|d| dd*¡d% |j|d)| d d*¡d% | d!d*¡}t|tƒrVd. d/d0„ t|ƒD ƒ¡}|j|d1|d% | d"d*¡}t|tƒrˆd. |¡}|j|d2|d% | dd*¡}| |d¡}|j|d3|d% |j|d4|d% q°|jD ]r}d}|
|d jƒ}|D ]:}z&tt|jƒƒ|krtt|jƒƒ}W n   Y nX qôt|d) d5ƒ}||j | _!qÚdd6l"m#}  | ƒ }!| $|!¡ |! %d¡ |! &¡ W S  t'k
r´ }" zt( )d7|"› ¡ |"‚W 5 d8}"~"X Y nX d8S )9ab  Create an Excel report from test cases data.
    
    Args:
        test_cases (List[Dict]): List of test case dictionaries
        status_values (Dict): Status values for test cases
        source_type (str): Source type (e.g., 'Jira', 'Azure')
        item_ids (List[str]): List of item IDs
        
    Returns:
        bytes: Excel file as bytes
    r   r   r   )Úget_column_letterÚSummaryzTest Cases Report - ÚA1Té   )ÚboldÚsizezGenerated on: z%Y-%m-%d %H:%M:%SZA3zSource Type: ZA4z
Item IDs: z, ZA5zTotal Test Cases: ÚA6r6   ÚUnknownú
Not TestedrA   zStatus Summary:ZA8)r{   é	   r   ÚArT   r7   r8   r9   r=   zItem ID)ÚrowÚcolumnÚvalueZCCCCCCZsolid)Ústart_colorZ	end_colorZ	fill_typerV   r4   ú(ú)éÿÿÿÿr?   c                 S   s"   g | ]\}}|d  › d|› ‘qS r@   r/   rB   r/   r/   r0   rF   å   s     z'create_excel_report.<locals>.<listcomp>é   é   é   é   rW   )ÚBytesIOzError creating Excel report: N)*rR   r   Úopenpyxl.stylesr	   r
   r   r   r   Zopenpyxl.utilsrw   ÚremoveÚactiveZcreate_sheetZfontr   ÚnowÚstrftimer$   r[   Úgetr\   rI   ÚcellÚfillÚsplitrG   rH   rN   rƒ   rf   r„   rg   rh   rj   Úior   ÚsaveÚseekÚgetvaluer)   r   r    )#r2   rt   ru   rv   r   r	   r
   r   r   r   rw   ÚwbZ
summary_wsZstatus_countsÚtcZtc_idÚstatusr‚   ÚcountZtc_wsÚheadersrO   Úheaderr”   ÚtitleÚitem_idÚstepsZexpected_resultrƒ   rr   Zcolumn_letterZadjusted_widthr   Úoutputr.   r/   r/   r0   Úcreate_excel_report™   sˆ    







r¥   )Ú	test_caser   c           
   
   C   s
  zÂ|   d¡r*| d  ¡  dd¡ ¡ | d< |   d¡rn| d  ¡ }|rd|dkrdt dd|¡}|| d< qvd| d< nd| d< |   d¡rJ| d }t|tƒrþg }|D ]N}|rœ| ¡ rœ| ¡  dd¡ ¡ }t d	d|¡}t d
d|¡}|rœ| |¡ qœ|rô|nd| d< nJt|tƒr@| ¡ r@| ¡  dd¡ ¡ }t dd|¡}|| d< nd| d< nd| d< |   d¡rœ| d  ¡ }|r’|dkr’t dd|¡}|| d< nd| d< nd| d< |   d¡rØ| d  ¡ }|rØt dd|¡}|| d< |   d¡dkr„|   d¡rft| d tƒrf| d  ¡ rf| d  ¡ }| 	¡  
d¡s\t|ƒdkrXd|d  	¡  |dd…  nd}|| d< n|   d¡r„d| d › | d< |   d¡s˜d| d< |   d¡rÀ| d  ¡  dd¡ ¡ | d< | W S  tk
r }	 z t dt|	ƒ› ¡ |  W Y ¢S d}	~	X Y nX dS )zFValidate and clean up test case data to ensure quality and consistencyr6   ú**r4   r7   zNo scenario providedú\s+Ú r8   z^\s*\d+\.\s*z^\s*[-*]\s*zNo steps providedr9   zNo expected result providedr:   )ÚverifyÚensureÚvalidateÚcheckrA   zVerify r   NzVerify resultzExecute the steps to validate: r=   r   r>   zError validating test case: )r“   ÚstripÚreplaceÚreÚsubrG   rH   rc   rf   ÚlowerÚ
startswithr[   r)   r   ra   )
r¦   Zscenarior£   Zcleaned_stepsrE   Úcleaned_stepÚexpectedÚactualÚderivedr.   r/   r/   r0   Ú_validate_and_clean_test_case  sp    








*.
r¸   )r2   r   c           
      C   sŒ   i }d}t t || ¡ƒ}|s i S t|ƒD ]^\}}| d¡ ¡ }| ¡ }|d t|ƒk rf||d   ¡ nt| ƒ}| ||…  ¡ }	|	||< q(|S )zêExtract sections from test cases content based on TEST TYPE markers.
    
    Args:
        test_cases (str): The full test cases content
        
    Returns:
        Dict[str, str]: Dictionary of section name to section content
    zTEST TYPE:\s*([^\n]+)rA   )	rH   r°   ÚfinditerrI   Úgroupr®   Úendr[   Ústart)
r2   rl   Zsection_patternZsection_matchesrD   Úmatchrn   Ú	start_posÚend_posro   r/   r/   r0   rY   e  s    	(
rY   r;   )r2   r3   r   c           )   	   C   sè  g }i }|}d}g }t  d|› ¡ t  d| dd… › ¡ d| krLd| kstd| kr`t d| ¡std	| krd
| krt  d¡ t d| ¡}|D ]Z}| ¡ }|rŽt|ƒdk r®qŽd|ksÎd	|ksÎt d| ¡ ¡rŽi }	||	d< t d|¡}
|
r|
 d¡ ¡  	dd¡ ¡ |	d< nft d|¡}|r>| d¡ ¡  	dd¡ ¡ |	d< n4| d¡d  ¡ }t d|¡rr| 	dd¡ ¡ |	d< t d|tj
¡}|rÈ| d¡ ¡  	dd¡ ¡ }t dd|¡}t dd|¡}||	d< nªt d|tj
¡}|r| d¡ ¡  	dd¡ ¡ }t dd|¡}t dd|¡}||	d< nTt d|tj
¡}|rr| d¡ ¡  	dd¡ ¡ }t dd|¡}t dd|¡}||	d< t d|tj
¡}|rÆ| d¡ ¡  	dd¡ ¡ |	d< t  d|	d dd … › d!¡ nt  d"|dd#… › d!¡ t d$|tj
¡}|rœ| d¡ ¡ }t  d%|dd#… › d!¡ t d&|tj¡}|rbd'd(„ |D ƒ|	d)< t  d*t|	d) ƒ› d+¡ n6d,d(„ | d¡D ƒ}||	d)< t  d*t|	d) ƒ› d-¡ n8t d.|tj
¡}|rV| d¡ ¡ }t  d/|dd#… › d!¡ t d&|tj¡}|rd0d(„ |D ƒ|	d)< t  d*t|	d) ƒ› d+¡ n6d1d(„ | d¡D ƒ}||	d)< t  d*t|	d) ƒ› d-¡ n~t  d2|dd#… › d!¡ t d3|tj
¡}|rº| d¡ ¡ }t  d4|dd#… › d!¡ |g|	d)< nt  d5|dd#… › d!¡ t d6|tj
¡}|r*| d¡ ¡  	dd¡ ¡ }t dd|¡}t dd|¡}||	d7< nªt d8|tj
¡}|r€| d¡ ¡  	dd¡ ¡ }t dd|¡}t dd|¡}||	d7< nTt d9|tj
¡}|rÔ| d¡ ¡  	dd¡ ¡ }t dd|¡}t dd|¡}||	d7< t d:|¡}|rø| d¡ ¡ |	d;< t d<|tj
¡}|rB| d¡ ¡ }|rB| d=¡sB| 	dd¡ ¡ |	d>< t d?|¡}|rr| d¡ ¡  	dd¡ ¡ |	d@< |	 d¡rŽt|	ƒ}	| |	¡ t  dA|	d › ¡ t  dBt|	 ¡ ƒ› ¡ t  dC|	 ddD¡› ¡ t  dE|	 d)dD¡› ¡ qŽ|rt  d*t|ƒ› dF¡ |S t  dG¡ |  d¡} d}!|!t| ƒk rP| |!  ¡ }"|!d7 }!|"sPq$|" dH¡rv|" 	dId¡ ¡ pp|}q$t dJ|"¡}
|
rÒ|r¦|rœ||d)< | |¡ ||
 d¡ ¡  	dd¡ ¡ dKœ}d}g }q$t dL|"¡}|r|r| d¡ ¡  	dd¡ ¡ |d< q$t dM|"¡}|rd|rd| d¡ ¡  	dd¡ ¡ |d< t  dN|d dd … › d!¡ q$t dO|"¡}|r |r dP}g }t  dQ| ddR¡› ¡ q$|	rÀt dS|"¡	rd}||d)< t  dTt|ƒ› dU| ddR¡› ¡ t dV|"¡}#|#r$|# d¡ ¡  	dd¡ ¡ |d7< q$t dW|"¡}$|$	r~|$ ¡ dX 	r@|$ dY¡n|"}%|% ¡  	dd¡ ¡ }&|&r$| |&¡ t  dZ|&› ¡ q$nB|" ¡ 	rÀ|" ¡  	dd¡ ¡ }'|'r$| |'¡ t  d[|'› ¡ q$t dV|"¡}|	rú|	rú| d¡ ¡  	dd¡ ¡ |d7< q$t d\|"¡}(|(
r(|
r(|( d¡ ¡ |d;< q$t d]|"¡}|
rb|
rb| d¡ ¡  	dd¡ ¡ |d>< q$t d^|"¡}|
rœ|
rœ| d¡ ¡  	dd¡ ¡ |d@< q$|r$|s$|"r$d@|k
rÎ|d@  d|" 7  < n~d>|k
rî|d>  d|" 7  < n^d7|kr|d7  d|" 7  < n>d|kr.|d  d|" 7  < nd|kr$|d  d|" 7  < q$|rÎ|rd||d)< | |¡ t  d_| dd`¡› ¡ t  dat| ¡ ƒ› ¡ t  db| ddD¡› ¡ t  dc| d)dD¡› ¡ t  d*t|ƒ› dd¡ |S )ea
  Parse test cases using the traditional format.
    
    Args:
        test_cases (str): Test cases content to parse
        default_section (str): Default section name if none is specified
        
    Returns:
        List[Dict]: List of test case dictionaries
    Fz)Parsing test cases with default section: z)Raw test case content (first 500 chars): Niô  zTitle:zSteps to reproduce:zTC_[A-Z]+_\d+z**Test Case ID:**z**Test Steps:**zDetected test case formatz\n\s*\né
   r5   zTitle:\s*(.*?)(?:\n|$)rA   r§   r4   r6   z%\*\*Test Case ID:\*\*\s*(.*?)(?:\n|$)r?   r   zYScenario:\s*(.*?)(?:\n\s*Preconditions:|\n\s*Steps to reproduce:|\n\s*Expected Result:|$)r©   r¨   r7   zR\*\*Test Scenario:\*\*\s*(.*?)(?:\n\s*\*\*Test Steps:|\n\s*\*\*Expected Result:|$)zHDescription:\s*(.*?)(?:\n\s*Steps to reproduce:|\n\s*Expected Result:|$)zJPreconditions:\s*(.*?)(?:\n\s*Steps to reproduce:|\n\s*Expected Result:|$)r<   zFound preconditions: éd   z...z!No preconditions found in block: éÈ   zX(?:\*\*)?Steps to reproduce:(?:\*\*)?\s*\n([\s\S]*?)(?=\n\s*(?:\*\*)?Expected Result:|$)zFound steps text: zK(?:^|\n)\s*(?:\d+\.\s*|\*\s*|\-\s*)(.*?)(?=\n\s*(?:\d+\.\s*|\*\s*|\-\s*)|$)c                 S   s(   g | ] }|  ¡ r|  ¡  d d¡  ¡ ‘qS ©r§   r4   ©r®   r¯   ©rC   rE   r/   r/   r0   rF   à  s      z,parse_traditional_format.<locals>.<listcomp>r8   z
Extracted z steps using numbered formatc                 S   s(   g | ] }|  ¡ r|  ¡  d d¡  ¡ ‘qS rÃ   rÄ   rÅ   r/   r/   r0   rF   ä  s      z  steps using line-by-line formatzA\*\*Test Steps:\*\*\s*\n([\s\S]*?)(?=\n\s*\*\*Expected Result:|$)zFound test steps text: c                 S   s(   g | ] }|  ¡ r|  ¡  d d¡  ¡ ‘qS rÃ   rÄ   rÅ   r/   r/   r0   rF   ð  s      c                 S   s(   g | ] }|  ¡ r|  ¡  d d¡  ¡ ‘qS rÃ   rÄ   rÅ   r/   r/   r0   rF   ô  s      zNo steps found in block: z)Steps:\s*(.*?)(?:\n\s*Expected Result:|$)z&Found steps with alternative pattern: z*No steps found with any pattern in block: zMExpected Result:\s*(.*?)(?:\n\s*Actual Result:|\n\s*Status:|\n\s*Priority:|$)r9   zP\*\*Expected Result:\*\*\s*(.*?)(?:\n\s*\*\*Actual Result:|\n\s*\*\*Priority:|$)zNExpected Outcome:\s*(.*?)(?:\n\s*Actual Result:|\n\s*Status:|\n\s*Priority:|$)z\n\s*Status:\s*(.*?)(?:\n|$)r=   z*Actual Result:\s*(.*?)(?:\n\s*Priority:|$)z	Priority:r:   zPriority:\s*(.*?)(?:\n|$)r>   zExtracted test case: zTest case fields: z
Scenario: z	NOT FOUNDzSteps: z test cases using block parsingz)Using line-by-line parsing for test casesz###ú#z/^(?:\d+\.\s*)?(?:\*\*)?Title:(?:\*\*)?\s*(.*?)$)r5   r6   z%^(?:\*\*)?Scenario:(?:\*\*)?\s*(.*?)$z*^(?:\*\*)?Preconditions:(?:\*\*)?\s*(.*?)$z%Found preconditions in line-by-line: z+^(?:\*\*)?Steps(?: to reproduce)?:(?:\*\*)?Tz(Started collecting steps for test case: r~   z#^(?:\*\*)?Expected Result:(?:\*\*)?zFinished collecting z steps for test case: z,^(?:\*\*)?Expected Result:(?:\*\*)?\s*(.*?)$z^(?:(\d+)\.|\-|\*)\s*(.*?)$rˆ   rV   zAdded step: zAdded step (no pattern): z^Status:\s*(.*?)$z*^(?:\*\*)?Actual Result:(?:\*\*)?\s*(.*?)$z%^(?:\*\*)?Priority:(?:\*\*)?\s*(.*?)$zFinal test case: zNO TITLEzFinal test case fields: zFinal Scenario: zFinal Steps: z& test cases using line-by-line parsing)r   r(   r°   Úsearchr–   r®   r[   r½   rº   r¯   ÚDOTALLr±   ra   ÚfindallÚ	MULTILINEr³   r“   r¸   rc   ÚdebugrH   ÚkeysÚgroups))r2   r3   rm   Zcurrent_testZcurrent_sectionZcollecting_stepsZcurrent_stepsZtest_case_blocksÚblockr¦   Ztitle_matchZtest_case_id_matchÚ
first_lineZscenario_matchZscenario_textZtest_scenario_matchZalt_scenario_matchZpreconditions_matchZsteps_matchÚ
steps_textZ
step_linesr£   Ztest_steps_matchZalt_steps_matchZexpected_matchZexpected_textZtest_expected_matchZalt_expected_matchZstatus_matchZactual_matchZactual_resultZpriority_matchÚlinesrD   ÚlineZer_matchZ
step_matchZ	step_textr´   Zcleaned_lineZstatus_aloner/   r/   r0   rZ   „  s®   
8

   

 






þ"








rZ   )r;   )'Úutils.error_loggerr   r   r   r   r"   Úpandasr^   rR   r   rŽ   r	   r
   r   r   r   Zopenpyxl.utils.dataframer   r°   r   ÚuuidÚloggingÚtypingr   r   r   ÚbasicConfigÚINFOÚ	getLoggerÚ__name__r   rf   r1   rs   Úbytesr¥   r¸   rY   rZ   r/   r/   r/   r0   Ú<module>   s$   
guW