@@ -22,6 +22,113 @@ def setUp(self):
2222 "menu_theme" : "" ,
2323 }
2424
25+ def _extract_printed_authors (self , mock_print ):
26+ """
27+ Return the list of author display lines in the order they were printed.
28+ """
29+ authors = []
30+ for call in mock_print .call_args_list :
31+ msg = call .args [0 ] if call .args else ""
32+ # lines look like " John Doe <john@example.com>:"
33+ if isinstance (msg , str ) and msg .strip ().endswith (">:" ):
34+ authors .append (msg .strip ()[:- 1 ]) # drop trailing ":"
35+ return authors
36+
37+ @patch ("git_py_stats.generate_cmds.run_git_command" )
38+ @patch ("builtins.print" )
39+ def test_sort_by_commits_desc (self , mock_print , mock_run_git_command ):
40+ """
41+ Test detailed_git_stats when sorting by commits in descending order.
42+ """
43+ # Two authors, B has more commits but fewer insertions
44+ mock_run_git_command .return_value = (
45+ # A1 (2 commits total)
46+ "c1\t Alice\t alice@example.com\t 1609459200\n "
47+ "10\t 1\t a.py\n "
48+ "c2\t Alice\t alice@example.com\t 1609459300\n "
49+ "5\t 0\t a2.py\n "
50+ # B1 (3 commits total)
51+ "c3\t Bob\t bob@example.com\t 1609460000\n "
52+ "1\t 1\t b.py\n "
53+ "c4\t Bob\t bob@example.com\t 1609460100\n "
54+ "2\t 2\t b2.py\n "
55+ "c5\t Bob\t bob@example.com\t 1609460200\n "
56+ "3\t 3\t b3.py\n "
57+ )
58+
59+ cfg = dict (self .mock_config )
60+ cfg ["sort_by" ] = "commits"
61+ cfg ["sort_dir" ] = "desc"
62+
63+ generate_cmds .detailed_git_stats (cfg )
64+
65+ authors = self ._extract_printed_authors (mock_print )
66+ # Expect Bob first (3 commits) then Alice (2)
67+ self .assertGreaterEqual (len (authors ), 2 )
68+ self .assertTrue (authors [0 ].startswith ("Bob <bob@example.com>" ))
69+ self .assertTrue (authors [1 ].startswith ("Alice <alice@example.com>" ))
70+ # Header shows sort choice
71+ printed = " " .join (a .args [0 ] for a in mock_print .call_args_list if a .args )
72+ self .assertIn ("Sorting by: commits (desc)" , printed )
73+
74+ @patch ("git_py_stats.generate_cmds.run_git_command" )
75+ @patch ("builtins.print" )
76+ def test_sort_by_lines_asc_with_name_tiebreaker (self , mock_print , mock_run_git_command ):
77+ """
78+ Test detailed_git_stats when sorting by lines in ascending order.
79+ Attempts to handle a "tiebreaker" when sorting by falling back to
80+ the person's name in ascending order. So if Alice and Bob have the
81+ same number of commits, Alice should be chosen.
82+ """
83+ mock_run_git_command .return_value = (
84+ # Alice: 3+3 = 6 lines
85+ "c1\t Alice\t alice@example.com\t 1609459200\n "
86+ "3\t 3\t a.py\n "
87+ # Bob: 4+2 = 6 lines
88+ "c2\t Bob\t bob@example.com\t 1609460000\n "
89+ "4\t 2\t b.py\n "
90+ )
91+
92+ cfg = dict (self .mock_config )
93+ cfg ["sort_by" ] = "lines"
94+ cfg ["sort_dir" ] = "asc"
95+
96+ generate_cmds .detailed_git_stats (cfg )
97+
98+ authors = self ._extract_printed_authors (mock_print )
99+ self .assertGreaterEqual (len (authors ), 2 )
100+ self .assertTrue (authors [0 ].startswith ("Alice <alice@example.com>" ))
101+ self .assertTrue (authors [1 ].startswith ("Bob <bob@example.com>" ))
102+ printed = " " .join (a .args [0 ] for a in mock_print .call_args_list if a .args )
103+ self .assertIn ("Sorting by: lines (asc)" , printed )
104+
105+ @patch ("git_py_stats.generate_cmds.run_git_command" )
106+ @patch ("builtins.print" )
107+ def test_sort_by_name_desc (self , mock_print , mock_run_git_command ):
108+ """
109+ Test detailed_git_stats when sorting by name in descending order.
110+ """
111+ mock_run_git_command .return_value = (
112+ "c1\t Alice\t alice@example.com\t 1609459200\n "
113+ "1\t 0\t a.py\n "
114+ "c2\t Bob\t bob@example.com\t 1609460000\n "
115+ "1\t 0\t b.py\n "
116+ "c3\t Carol\t carol@example.com\t 1609470000\n "
117+ "1\t 0\t c.py\n "
118+ )
119+
120+ cfg = dict (self .mock_config )
121+ cfg ["sort_by" ] = "name"
122+ cfg ["sort_dir" ] = "desc"
123+
124+ generate_cmds .detailed_git_stats (cfg )
125+
126+ authors = self ._extract_printed_authors (mock_print )
127+ # Descending name: Carol, Bob, Alice
128+ self .assertTrue (authors [0 ].startswith ("Carol <carol@example.com>" ))
129+ self .assertTrue (authors [1 ].startswith ("Bob <bob@example.com>" ))
130+ self .assertTrue (authors [2 ].startswith ("Alice <alice@example.com>" ))
131+
25132 @patch ("git_py_stats.generate_cmds.run_git_command" )
26133 @patch ("builtins.print" )
27134 def test_detailed_git_stats (self , mock_print , mock_run_git_command ):
0 commit comments