
    Rix                        d Z ddlZddlZddlZddlmZmZ ddlmZ ddlm	Z	m
Z
 ddlZej                  j                  d e ee      j                   j                                ddlZej&                  defd       Zej&                  defd       Zej&                  defd	       Zej&                  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 G d d      Z G d d      Z G d d      Z  G d d      Z! G d d      Z" G d d       Z# G d! d"      Z$ G d# d$      Z% G d% d&      Z&y)'z@Tests for weekly-retro.py - TDD approach (RED first, then GREEN)    N)datedatetime)Path)	MagicMockpatchreturnc                      ddddddddd	dd
ddddddddddddddddddddddddddddddddd d!d"d#dd$dd%d&d'd(ddd)S )*z0Minimal task-timers.json tasks dict for testing.task-1.1	dev1-teamzDeep work taskz2026-03-09T10:00:00z2026-03-09T10:45:00g     @	completed)task_idteam_iddescription
start_timeend_timeduration_secondsstatustask-1.2zMedium work taskz2026-03-10T11:00:00z2026-03-10T11:20:00g     @task-1.3zMicro work taskz2026-03-11T12:00:00z2026-03-11T12:05:00g     r@task-1.4	dev2-teamzDev2 task Az2026-03-09T14:00:00z2026-03-09T14:10:00g     @task-1.5zDev2 task Bz2026-03-10T15:00:00z2026-03-10T15:25:00g     p@task-1.6zDev2 task C (not completed)z2026-03-11T16:00:00N        runningtask-1.7zDeep work task 2z2026-03-12T09:00:00z2026-03-12T10:00:00g      @)r
   r   r   r   r   r   r    r       P/home/jay/workspace/.worktrees/task-2117-dev1/scripts/tests/test_weekly_retro.pysample_tasksr       s    
 ""+/- &!
 ""-/- &!
 "",/- %!
 ""(/- %!
 ""(/- &!
 ""8/ #
 ""-/- &!
o@ @r   c                 `    d| i}|dz  }|j                  t        j                  |             |S )z'Write sample tasks to a temp JSON file.taskstask-timers.json
write_textjsondumps)r    tmp_pathdataps       r   tasks_json_filer+   ]   s3     \"D%%ALLD!"Hr   c                 `    di i}| dz  }|j                  t        j                  |             |S )ztask-timers.json with no tasks.r"   r#   r$   )r(   r)   r*   s      r   empty_tasks_json_filer-   f   s2     R=D%%ALLD!"Hr   c                       	 y)zHSimulated git log output (one line per commit: <hash> <date> <subject>).a@  abc1234 2026-03-09 feat: add new feature
abc1235 2026-03-10 fix: resolve null pointer
abc1236 2026-03-10 fix: another bug
abc1237 2026-03-11 refactor: clean up code
abc1238 2026-03-12 docs: update readme
abc1239 2026-03-12 chore: bump version
abc1240 2026-03-13 some random message
abc1241 2026-03-13 feat: new endpoint
r   r   r   r   sample_git_logr/   o   s    	2	r   c                   *    e Zd Zd Zd Zd Zd Zd Zy)TestLoadTasksc                 N    t        j                  |      }t        |      dk(  sJ y )N   )wr
load_taskslen)selfr+   r"   s      r   test_loads_valid_filez#TestLoadTasks.test_loads_valid_file   s     o.5zQr   c                 F    |dz  }t        j                  |      }|i k(  sJ y )Nzno-file.jsonr4   r5   )r7   r(   missingr"   s       r   )test_returns_empty_dict_when_file_missingz7TestLoadTasks.test_returns_empty_dict_when_file_missing   s&    ^+g&{{r   c                     |dz  }|j                  t        j                  di i             t        j                  |      }|i k(  sJ y )Nbad.jsonother)r%   r&   r'   r4   r5   r7   r(   r*   r"   s       r   .test_returns_empty_dict_when_tasks_key_missingz<TestLoadTasks.test_returns_empty_dict_when_tasks_key_missing   s?    z!	TZZ"./a {{r   c                 h    |dz  }|j                  d       t        j                  |      }|i k(  sJ y )Nr>   z
NOT JSON{{)r%   r4   r5   r@   s       r   'test_returns_empty_dict_on_invalid_jsonz5TestLoadTasks.test_returns_empty_dict_on_invalid_json   s2    z!	\"a {{r   c                 <    t        j                  |      }|i k(  sJ y Nr:   )r7   r-   r"   s      r   #test_empty_tasks_returns_empty_dictz1TestLoadTasks.test_empty_tasks_returns_empty_dict   s    34{{r   N)__name__
__module____qualname__r8   r<   rA   rC   rF   r   r   r   r1   r1      s    
r   r1   c                   $    e Zd Zd Zd Zd Zd Zy)TestFilterTasksByWeekc                 P    t        j                  |d      }t        |      dkD  sJ y N2026-11r   r4   filter_tasks_by_weekr6   r7   r    results      r   test_filters_to_correct_weekz2TestFilterTasksByWeek.test_filters_to_correct_week   s$    ((yA6{Qr   c                 P    t        j                  |d      }t        |      dk(  sJ y )Nz2026-09r   rO   rQ   s      r    test_excludes_tasks_outside_weekz6TestFilterTasksByWeek.test_excludes_tasks_outside_week   s&    ((yA6{ar   c                 n    t        j                  |d      }|j                         D ]  }|d   dk(  rJ  y )NrN   r   r   )r4   rP   values)r7   r    rR   tasks       r   *test_includes_only_completed_when_filteredz@TestFilterTasksByWeek.test_includes_only_completed_when_filtered   s;    ((yAMMO 	1D>[000	1r   c                 >    t        j                  i d      }|i k(  sJ y )NrN   )r4   rP   r7   rR   s     r   test_empty_tasks_returns_emptyz4TestFilterTasksByWeek.test_empty_tasks_returns_empty   s     ((Y7||r   N)rG   rH   rI   rS   rU   rY   r\   r   r   r   rK   rK      s     
1
r   rK   c                   <    e Zd Zd Zd Zd Zd Zd Zd Zd Z	d Z
y	)
TestClassifySessionc                 8    t        j                  d      dk(  sJ y Ni	  deepr4   classify_sessionr7   s    r   test_deep_above_1800z(TestClassifySession.test_deep_above_1800       ""4(F222r   c                 8    t        j                  d      dk(  sJ y r`   rb   rd   s    r   test_deep_at_exactly_1801z-TestClassifySession.test_deep_at_exactly_1801   rf   r   c                 8    t        j                  d      dk(  sJ y )Ni  mediumrb   rd   s    r   test_medium_at_1800z'TestClassifySession.test_medium_at_1800   s    ""4(H444r   c                 8    t        j                  d      dk(  sJ y )NiX  rj   rb   rd   s    r   test_medium_at_600z&TestClassifySession.test_medium_at_600   s    ""3'8333r   c                 8    t        j                  d      dk(  sJ y )NiW  microrb   rd   s    r   test_micro_below_600z(TestClassifySession.test_micro_below_600   s    ""3'7222r   c                 8    t        j                  d      dk(  sJ y )Nr   ro   rb   rd   s    r   test_micro_at_zeroz&TestClassifySession.test_micro_at_zero   s    ""1%000r   c                 8    t        j                  d      dk(  sJ y )Ni   ra   rb   rd   s    r   test_deep_large_valuez)TestClassifySession.test_deep_large_value   rf   r   c                 8    t        j                  d      dk(  sJ y )Ni  rj   rb   rd   s    r   test_medium_midrangez(TestClassifySession.test_medium_midrange   s    ""3'8333r   N)rG   rH   rI   re   rh   rk   rm   rp   rr   rt   rv   r   r   r   r^   r^      s*    33543134r   r^   c                   6    e Zd Zd Zd Zd Zd Zd Zd Zd Z	y)	TestComputeTeamMetricsc                     |j                         D ci c]  \  }}|d   dk(  s|| }}}t        j                  |      }|d   d   dk(  sJ |d   d   dk(  sJ y c c}}w )Nr   r   r   
task_count   r      itemsr4   compute_team_metricsr7   r    kvr   metricss         r   test_task_count_per_teamz/TestComputeTeamMetrics.test_task_count_per_team   sw    &2&8&8&:Ydaak[>XQTY	Y)))4{#L1Q666{#L1Q666 Zs
   AAc                     |j                         D ci c]  \  }}|d   dk(  s|| }}}t        j                  |      }|d   d   t        j                  dd      k(  sJ y c c}}w )Nr   r   r   avg_duration_secondsg     x@MbP?relr~   r4   r   pytestapproxr   s         r   test_avg_duration_dev1z-TestComputeTeamMetrics.test_avg_duration_dev1   l    &2&8&8&:Ydaak[>XQTY	Y)))4{#$:;v}}VY]?^^^^ Z
   A%A%c                     |j                         D ci c]  \  }}|d   dk(  s|| }}}t        j                  |      }|d   d   t        j                  dd      k(  sJ y c c}}w )Nr   r   r   r   g     h@r   r   r   r   s         r   test_avg_duration_dev2z-TestComputeTeamMetrics.test_avg_duration_dev2   r   r   c                     |j                         D ci c]  \  }}|d   dk(  s|| }}}t        j                  |      }|d   d   }|d   dk(  sJ |d   dk(  sJ |d	   dk(  sJ y c c}}w )
Nr   r   r   session_patternra   r|   rj      ro   r}   r7   r    r   r   r   r   sps          r   test_session_pattern_dev1z0TestComputeTeamMetrics.test_session_pattern_dev1   s    &2&8&8&:Ydaak[>XQTY	Y)))4[!"34 &zQ(|q   '{a Z
   A)A)c                     |j                         D ci c]  \  }}|d   dk(  s|| }}}t        j                  |      }|d   d   }|d   dk(  sJ |d   dk(  sJ |d	   dk(  sJ y c c}}w )
Nr   r   r   r   ra   r   rj   r|   ro   r}   r   s          r   test_session_pattern_dev2z0TestComputeTeamMetrics.test_session_pattern_dev2   s    &2&8&8&:Ydaak[>XQTY	Y)))4[!"34&zQ(|q   '{a Zr   c                 <    t        j                  i       }|i k(  sJ y rE   )r4   r   )r7   r   s     r   rF   z:TestComputeTeamMetrics.test_empty_tasks_returns_empty_dict  s    ))"-"}}r   c                     |j                         D ci c]  \  }}|d   dk(  s|| }}}t        j                  |      }|j                         D ]  }d|v sJ |d   dk(  rJ  yc c}}w )z0fix_pct is set later when commit data is merged.r   r   fix_pctr   N)r~   r4   r   rW   )r7   r    r   r   r   r   	team_datas          r   ,test_fix_pct_not_set_by_compute_team_metricszCTestComputeTeamMetrics.test_fix_pct_not_set_by_compute_team_metrics  s~    &2&8&8&:Ydaak[>XQTY	Y)))4 ) 	/I	)))Y'3...	/ Zs
   A(A(N)
rG   rH   rI   r   r   r   r   r   rF   r   r   r   r   rx   rx      s'    7__	  /r   rx   c                   N    e 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)TestParseGitLogc                 B    t        j                  |      }|d   dk(  sJ y )Ntotal   r4   parse_git_logr7   r/   rR   s      r   test_total_commit_countz'TestParseGitLog.test_total_commit_count  s$    !!.1g!###r   c                 H    t        j                  |      }|d   d   dk(  sJ y )Nby_typefeatr|   r   r   s      r   test_feat_countzTestParseGitLog.test_feat_count  *    !!.1i (A---r   c                 H    t        j                  |      }|d   d   dk(  sJ y )Nr   fixr|   r   r   s      r   test_fix_countzTestParseGitLog.test_fix_count#  s*    !!.1i '1,,,r   c                 H    t        j                  |      }|d   d   dk(  sJ y )Nr   refactorr   r   r   s      r   test_refactor_countz#TestParseGitLog.test_refactor_count'  s*    !!.1i ,111r   c                 H    t        j                  |      }|d   d   dk(  sJ y )Nr   docsr   r   r   s      r   test_docs_countzTestParseGitLog.test_docs_count+  r   r   c                 H    t        j                  |      }|d   d   dk(  sJ y )Nr   chorer   r   r   s      r   test_chore_countz TestParseGitLog.test_chore_count/  *    !!.1i )Q...r   c                 H    t        j                  |      }|d   d   dk(  sJ y )Nr   r?   r   r   r   s      r   test_other_countz TestParseGitLog.test_other_count3  r   r   c                 \    t        j                  d      }|d   dk(  sJ |d   d   dk(  sJ y )N r   r   r   r   r   r[   s     r   !test_empty_log_returns_zero_totalz1TestParseGitLog.test_empty_log_returns_zero_total7  s<    !!"%g!###i (A---r   c                 N    t        j                  |      }dD ]  }||d   v rJ  y )N)r   r   r   r   r   r?   r   r   )r7   r/   rR   ts       r   !test_all_types_present_in_by_typez1TestParseGitLog.test_all_types_present_in_by_type<  s4    !!.1F 	*Ay))))	*r   c                 L    d}t        j                  |      }|d   d   dk(  sJ y )Nz+abc1234 2026-03-09 feat(api): add endpoint
r   r   r   r   r7   logrR   s      r   test_feat_with_scopez$TestParseGitLog.test_feat_with_scopeA  s/    <!!#&i (A---r   c                 L    d}t        j                  |      }|d   d   dk(  sJ y )Nz)abc1234 2026-03-09 Fix: uppercase prefix
r   r   r   r   r   s      r   test_case_insensitive_prefixz,TestParseGitLog.test_case_insensitive_prefixF  s/    :!!#&i '1,,,r   N)rG   rH   rI   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r     s9    $.-2.//.
*
.
-r   r   c                       e Zd Zd Zd Zd Zy)TestFetchGitLogc                     t               }d|_        d|_        t        d|      5  t	        j
                  t        d      dd      }d d d        d	v sJ y # 1 sw Y   xY w)
Nr   z#abc1234 2026-03-09 feat: something
subprocess.runreturn_value/fake
2026-03-09
2026-03-15	workspacesinceuntilzfeat: somethingr   
returncodestdoutr   r4   fetch_git_logr   r7   mock_resultoutputs      r   test_returns_stdout_on_successz.TestFetchGitLog.test_returns_stdout_on_successR  sf    k!"C#+> 	%%w-""F	 !F***	 	s   "AA c                     t               }d|_        d|_        t        d|      5  t	        j
                  t        d      dd      }d d d        dk(  sJ y # 1 sw Y   xY w)	N   r   r   r   r   r   r   r   r   r   s      r   (test_returns_empty_string_on_git_failurez8TestFetchGitLog.test_returns_empty_string_on_git_failure^  sd    k!$#+> 	%%w-""F	 ||	 	s   "AA!c                     t        dt        d            5  t        j                  t	        d      dd      }d d d        dk(  sJ y # 1 sw Y   xY w)	Nr   zgit not foundside_effectr   r   r   r   r   )r   FileNotFoundErrorr4   r   r   )r7   r   s     r   &test_returns_empty_string_on_exceptionz6TestFetchGitLog.test_returns_empty_string_on_exceptionj  sS    #1B?1ST 	%%w-""F	 ||	 	s   "A		AN)rG   rH   rI   r   r   r   r   r   r   r   r   Q  s    
+
r   r   c                   $    e Zd Zd Zd Zd Zd Zy)TestComputeFixPctc                 n    ddddd}t        j                  |      t        j                  d      k(  sJ y )N
      r3   r   r   r   r         >@r4   compute_fix_pctr   r   r7   commitss     r   test_fix_pct_basicz$TestComputeFixPct.test_fix_pct_basicz  s3    1a+@A!!'*fmmD.AAAAr   c                 n    ddddd}t        j                  |      t        j                  d      k(  sJ y )Nr   r   r   r   r   r   r   s     r   test_fix_pct_zero_when_no_fixz/TestComputeFixPct.test_fix_pct_zero_when_no_fix~  s3    1b+AB!!'*fmmC.@@@@r   c                 l    dddid}t        j                  |      t        j                  d      k(  sJ y )Nr   r   r   r   r   r   s     r   !test_fix_pct_zero_when_no_commitsz3TestComputeFixPct.test_fix_pct_zero_when_no_commits  s2    5!*5!!'*fmmC.@@@@r   c                 l    dddid}t        j                  |      t        j                  d      k(  sJ y )N   r   r   g      Y@r   r   s     r   test_fix_pct_100z"TestComputeFixPct.test_fix_pct_100  s2    5!*5!!'*fmmE.BBBBr   N)rG   rH   rI   r   r   r   r   r   r   r   r   r   y  s    BAACr   r   c                   0    e Zd Zd Zd Zd Zd Zd Zd Zy)TestDetectAnomaliesc                     dddddddddi}t        j                  |d       }t        d	 |D              sJ t        d
 |D              sJ y )Nr   r   g     A@     @@r   ra   rj   ro   rz   r   r   r   
prev_teamsc              3   0   K   | ]  }d |v xr d|v   yw)r   r   Nr   .0as     r   	<genexpr>zDTestDetectAnomalies.test_fix_pct_anomaly_above_30.<locals>.<genexpr>  s!     J19>6kQ&66J   c              3   $   K   | ]  }d |v  
 yw)z35.0%Nr   r  s     r   r  zDTestDetectAnomalies.test_fix_pct_anomaly_above_30.<locals>.<genexpr>  s     3A7a<3   r4   detect_anomaliesanyr7   teams	anomaliess      r   test_fix_pct_anomaly_above_30z1TestDetectAnomalies.test_fix_pct_anomaly_above_30  s`     (.,-a#H	
 ''$?	J	JJJJ33333r   c                 t    dddddddddi}t        j                  |d 	      }t        d
 |D              rJ y )Nr   r   r   r   r   r   r   r   r   c              3   0   K   | ]  }d |v xr d|v   yw)r   r   Nr   r  s     r   r  zDTestDetectAnomalies.test_no_fix_pct_anomaly_at_30.<locals>.<genexpr>  s!     NqyA~:+*::Nr  r
  r  s      r   test_no_fix_pct_anomaly_at_30z1TestDetectAnomalies.test_no_fix_pct_anomaly_at_30  sO     (.,-Q#G	
 ''$?	NINNNNNr   c                     dddddddddi}dd	ddd
d
dddi}t        j                  ||      }t        d |D              sJ y )Nr   r{         $@r   r|   r   r   r   r   r   r   c              3   0   K   | ]  }d |v xr d|v   yw	   생산성r   Nr   r  s     r   r  zCTestDetectAnomalies.test_productivity_drop_50pct.<locals>.<genexpr>  s"     LQ;!#8q(88Lr  r
  r7   currentprevr  s       r   test_productivity_drop_50pctz0TestDetectAnomalies.test_productivity_drop_50pct  sp    (.,-Q#G	
  (.,-Q#G	
 ''DA	L)LLLLr   c                     ddddddddd	i}dd
ddddddd	i}t        j                  ||      }t        d |D              rJ y )Nr   r   r  r   r|   r   r   r   r   r   r   c              3   0   K   | ]  }d |v xr d|v   ywr  r   r  s     r   r  zSTestDetectAnomalies.test_no_productivity_anomaly_when_49pct_drop.<locals>.<genexpr>  s"     P{a'<K1,<<Pr  r
  r  s       r   ,test_no_productivity_anomaly_when_49pct_dropz@TestDetectAnomalies.test_no_productivity_anomaly_when_49pct_drop  ss    (.,-Q#G	
  (.,-Q#G	
 ''DA	PiPPPPPr   c                 t    ddddddddd	i}t        j                  |d 
      }t        d |D              rJ y )Nr   r   r  r   r|   r   r   r   r   r   c              3   $   K   | ]  }d |v  
 yw)r  Nr   r  s     r   r  zHTestDetectAnomalies.test_no_anomaly_when_no_prev_data.<locals>.<genexpr>  s     ;A{a';r	  r
  )r7   r  r  s      r   !test_no_anomaly_when_no_prev_dataz5TestDetectAnomalies.test_no_anomaly_when_no_prev_data  sO    (.,-Q#G	
 ''DA	;;;;;;r   c                     ddddddddddddddddd}d	d
dddddddi}t        j                  ||      }t        |      dk\  sJ y )Nr|   g      D@g     @@r   r   r   g      I@)r   r   r   r         @r   r   r   r   )r4   r  r6   )r7   r  r  r  s       r    test_multiple_anomalies_returnedz4TestDetectAnomalies.test_multiple_anomalies_returned  s      (-,-Q#G	  (-,-Q#G	
  (.,-Q#G	
 ''$?	9~"""r   N)	rG   rH   rI   r  r  r  r  r"  r%  r   r   r   r   r     s#    4
OM(Q,<#r   r   c                   $    e Zd Zd Zd Zd Zd Zy)TestComputeTrendc                     dddddddddi}dd	dddd
dddi}t        j                  ||      }|d   t        j                  d      k(  sJ y )Nr      r   r$  r   r|   r   rz   r   r   r   r   r{   r   task_count_change_pctg      4@r4   compute_trendr   r   r7   currr  trends       r   test_positive_task_count_changez0TestComputeTrend.test_positive_task_count_change  sy     (.,-Q#G	
  (.,-Q#G	
   t,,-t1DDDDr   c                     ddddddddd	i}ddd
dddddd	i}t        j                  ||      }|d   t        j                  d      k(  sJ y )Nr   r         @r$  r   r   r|   r   r*  r   avg_duration_change_pctg      $r,  r.  s       r   !test_negative_avg_duration_changez2TestComputeTrend.test_negative_avg_duration_change  sy     (-,-Q#G	
  (.,-Q#G	
   t,./6==3GGGGr   c                 X    ddddddddd	i}t        j                  |d       }|i k(  sJ y )
Nr   r   r3  r$  r   r   r|   r   r*  r4   r-  )r7   r/  r0  s      r   test_no_prev_dataz"TestComputeTrend.test_no_prev_data+  sD     (-,-Q#G	
   t,{{r   c                 p    ddddddddd	i}ddd
dddddd	i}t        j                  ||      }d|v sJ y )Nr   r   r   r$  r|   r   r   r   r*  r   r+  r7  r.  s       r   +test_zero_prev_task_count_no_division_errorz<TestComputeTrend.test_zero_prev_task_count_no_division_error7  sj    (.,-Q#G	
 (+,-Q#G	
   t,&%///r   N)rG   rH   rI   r1  r5  r8  r:  r   r   r   r'  r'    s    E(H(
0r   r'  c                   *    e Zd Zd Zd Zd Zd Zd Zy)TestSnapshotIOc                 t    |dz  }di d}t        j                  ||d       |dz  }|j                         sJ y )Nretro-snapshotsrN   weekr  week-2026-11.jsonr4   save_snapshotexists)r7   r(   snapshot_dirr)   expecteds        r   test_save_snapshot_creates_filez.TestSnapshotIO.test_save_snapshot_creates_fileS  sD    "33!B/
|Y7"55   r   c                     |dz  }ddddiid}t        j                  ||d       t        j                  |dz  j	                               }|d   dk(  sJ |d	   d   d   dk(  sJ y )
Nr>  rN   r   rz   r   r?  rA  r@  r  )r4   rC  r&   loads	read_text)r7   r(   rE  r)   saveds        r   test_save_snapshot_contentz)TestSnapshotIO.test_save_snapshot_contentZ  s~    "33![<:K,LM
|Y7

L+>>IIKLV}	)))W~k*<8A===r   c                 p    |dz  dz  dz  }t        j                  ddi|d       |j                         sJ y )Nra   nestedr>  r@  rN   rB  )r7   r(   rE  s      r   )test_save_snapshot_creates_dir_if_missingz8TestSnapshotIO.test_save_snapshot_creates_dir_if_missingb  s@    &(836GG
&),lIF""$$$r   c                     |dz  }|j                          ddddiid}|dz  j                  t        j                  |             t	        j
                  |d      }|J |d   d   d   dk(  sJ y )	Nr>  2026-10r   rz   r   r?  week-2026-10.jsonr  )mkdirr%   r&   r'   r4   load_snapshot)r7   r(   rE  r)   loadeds        r   test_load_snapshot_returns_dataz.TestSnapshotIO.test_load_snapshot_returns_datag  s    "33![<:K,LM	+	+77

48HI!!,	:!!!g{+L9Q>>>r   c                 b    |dz  }|j                          t        j                  |d      }|J y )Nr>  rQ  )rS  r4   rT  )r7   r(   rE  rR   s       r   ,test_load_snapshot_returns_none_when_missingz;TestSnapshotIO.test_load_snapshot_returns_none_when_missingp  s5    "33!!,	:~~r   N)rG   rH   rI   rG  rL  rO  rV  rX  r   r   r   r<  r<  R  s    !>%
?r   r<  c                   $    e Zd Zd Zd Zd Zd Zy)TestGetWeekPeriodc                 t    t        j                  d      \  }}t        |      dk(  sJ t        |      dk(  sJ y )NrN   r   r   )r4   get_week_periodstrr7   startends      r   test_2026_week_11_periodz*TestGetWeekPeriod.test_2026_week_11_period}  s:    ''	2
s5z\)))3x<'''r   c                 \    t        j                  d      \  }}||z
  j                  dk(  sJ y NrN      )r4   r\  daysr^  s      r   test_period_span_is_7_daysz,TestGetWeekPeriod.test_period_span_is_7_days  s.    ''	2
se!!Q&&&r   c                 ^    t        j                  d      \  }}|j                         dk(  sJ y rM   r4   r\  weekday)r7   r_  _s      r   test_start_is_mondayz&TestGetWeekPeriod.test_start_is_monday  s*    %%i0q}}!###r   c                 ^    t        j                  d      \  }}|j                         dk(  sJ y rc  rh  )r7   rj  r`  s      r   test_end_is_sundayz$TestGetWeekPeriod.test_end_is_sunday  s*    ##I.3{{}!!!r   N)rG   rH   rI   ra  rf  rk  rm  r   r   r   rZ  rZ  |  s    (
'$"r   rZ  c                       e Zd Zd Zd Zy)TestGetCurrentWeekc                     t        j                         }|j                  d      }t        |      dk(  sJ t	        |d         t	        |d         }}d|cxk  rdk  sJ  J d|cxk  rdk  sJ  J y )N-r|   r   r   i  i4  5   )r4   get_current_weeksplitr6   int)r7   r@  partsyearwnums        r   test_returns_iso_week_formatz/TestGetCurrentWeek.test_returns_iso_week_format  st    ""$

35zQq]CaMdt#t#####DBr   c                     t        d      5 }t        ddd      |j                  _        d |_        t        j                         }d d d        dk(  sJ y # 1 sw Y   xY w)Nzweekly_retro.datei  r   r   c                      t        | i |S rE   )r   )r  kws     r   <lambda>z?TestGetCurrentWeek.test_format_is_zero_padded.<locals>.<lambda>  s    T1^^ r   z2026-02)r   r   todayr   r   r4   rs  )r7   	mock_dater@  s      r   test_format_is_zero_paddedz-TestGetCurrentWeek.test_format_is_zero_padded  s]    &' 	)9+/a+;IOO($CI!&&(D	) y   		) 	)s   9AAN)rG   rH   rI   ry  r  r   r   r   ro  ro    s    !r   ro  c                   B    e Zd Zd Zd Zd Zd Zd Zd Zd Z	d Z
d	 Zy
)TestBuildReportc                     |dz  }t               }d|_        d|_        t        d|      5  t	        j
                  d|||      }d d d        dv sJ d	|v sJ d
|v sJ d|v sJ d|v sJ d|v sJ y # 1 sw Y   .xY w)Nr>  r   zKabc1 2026-03-09 feat: f1
abc2 2026-03-10 fix: f2
abc3 2026-03-11 chore: c1
r   r   rN   r@  r   
tasks_filerE  r@  periodr  r   r0  r  r   r   r   r   r4   build_reportr7   r+   r(   rE  mock_gitreports         r   test_report_has_required_keysz-TestBuildReport.test_report_has_required_keys  s    "33;p#(; 	__"*)	F	 6!!!&   F"""&   f$$$	 	s   A22A;c                     |dz  }t               }d|_        d|_        t        d|      5  t	        j
                  d|||      }d d d        d   dk(  sJ y # 1 sw Y   xY w)	Nr>  r   r   r   r   rN   r  r@  r  r  s         r   test_report_week_matches_inputz.TestBuildReport.test_report_week_matches_input  sq    "33;#(; 	__"*)	F	 f~***	 	s   AA!c                     |dz  }t               }d|_        d|_        t        d|      5  t	        j
                  d|||      }d d d        d   d	   d
k(  sJ |d   d   dk(  sJ y # 1 sw Y   $xY w)Nr>  r   r   r   r   rN   r  r  r_  r   r`  r   r  r  s         r   test_report_period_datesz(TestBuildReport.test_report_period_dates  s    "33;#(; 	__"*)	F	 h(L888h&,666	 	s   A((A1c                     |dz  }t               }d|_        d|_        t        d|      5  t	        j
                  d|||      }d d d        dd	   v sJ y # 1 sw Y   xY w)
Nr>  r   r   r   r   rN   r  r   r  r  r  s         r   test_report_teams_include_dev1z.TestBuildReport.test_report_teams_include_dev1  sq    "33;#(; 	__"*)	F	 fWo---	 	s   AA c                     |dz  }t               }d|_        d|_        t        d|      5  t	        j
                  d|||      }d d d        d   i k(  sJ |d	   g k(  sJ y # 1 sw Y   xY w)
Nr>  r   r   r   r   rN   r  r  r  r  )r7   r-   r(   rE  r  r  s         r   test_report_with_empty_tasksz,TestBuildReport.test_report_with_empty_tasks  s    "33;#(; 	__"0)	F	 g"$$$k"b(((	 	s   A""A+c                     |dz  }t        dt              5  t        j                  d|||      }d d d        d   d   dk(  sJ y # 1 sw Y   xY w)	Nr>  r   r   rN   r  r   r   r   )r   r   r4   r  )r7   r+   r(   rE  r  s        r   test_report_with_git_failurez,TestBuildReport.test_report_with_git_failure  sb    "33#1BC 	__"*)	F	 i )Q...	 	s   AAc                     |dz  }t               }d|_        d|_        t        d|      5  t	        j
                  d|||       d d d        |dz  j                         sJ y # 1 sw Y   xY w)	Nr>  r   r   r   r   rN   r  rA  )r   r   r   r   r4   r  rD  )r7   r+   r(   rE  r  s        r   test_snapshot_saved_after_buildz/TestBuildReport.test_snapshot_saved_after_build  su    "33;#(; 	OO"*)		 22::<<<	 	   A##A,c           	      h   |dz  }|j                          dddddddd	d
did}|dz  j                  t        j                  |             t	               }d|_        d|_        t        d|      5  t        j                  d|||      }d d d        d   i k7  sJ d|d   v sJ y # 1 sw Y   xY w)Nr>  rQ  r      g     @@r$  r   r   r|   r   r*  r?  rR  r   r   r   r   rN   r  r0  r+  )
rS  r%   r&   r'   r   r   r   r   r4   r  )r7   r+   r(   rE  	prev_datar  r  s          r   test_trend_uses_prev_snapshotz-TestBuildReport.test_trend_uses_prev_snapshot  s    "33 "$,2"02a!'L	

	 
+	+77

98MN;#(; 	__"*)	F	 g"$$$&&/999	 	s   2B((B1c                     |dz  }t               }d|_        d|_        t        d|      5  t	        j
                  d|||      }d d d        t        d   t              sJ y # 1 sw Y   xY w)	Nr>  r   r   r   r   rN   r  r0  )r   r   r   r   r4   r  
isinstancedictr  s         r   +test_trend_no_prev_returns_empty_or_no_prevz;TestBuildReport.test_trend_no_prev_returns_empty_or_no_prev1  ss    "33;#(; 	__"*)	F	 &/4000	 	r  N)rG   rH   rI   r  r  r  r  r  r  r  r  r  r   r   r   r  r    s/    %(+7.)	/=:<1r   r  c                       e Zd Zd Zd Zd Zy)TestGetPrevWeekc                 8    t        j                  d      dk(  sJ y )NrN   rQ  r4   get_prev_weekrd   s    r   test_week_11_prev_is_10z'TestGetPrevWeek.test_week_11_prev_is_10G      	*i777r   c                 T    t        j                  d      }|j                  d      sJ y )Nz2026-01z2025-)r4   r  
startswith)r7   r  s     r   test_week_01_prev_is_last_yearz.TestGetPrevWeek.test_week_01_prev_is_last_yearJ  s$    	*w'''r   c                 8    t        j                  d      dk(  sJ y )Nz2025-52z2025-51r  rd   s    r   test_week_52_prev_is_51z'TestGetPrevWeek.test_week_52_prev_is_51O  r  r   N)rG   rH   rI   r  r  r  r   r   r   r  r  F  s    8(
8r   r  )'__doc__r&   systempfiler   r   pathlibr   unittest.mockr   r   r   pathinsertr]  __file__parentweekly_retror4   fixturer  r    r+   r-   r/   r1   rK   r^   rx   r   r   r   r   r'  r<  rZ  ro  r  r  r   r   r   <module>r     sf   F  
  #  *  3tH~,,334 5  Bd B BJ t   t     & @ 64 4B3/ 3/v/- /-n   PC C.j# j#dH0 H0`" "T" "0! !.S1 S1v
8 
8r   