Coverage for tests / unit / ai / test_summary_formatting.py: 100%

74 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2026-04-03 18:53 +0000

1"""Tests for AI summary formatting and rendering. 

2 

3Covers render_summary_terminal, render_summary_github, 

4and render_summary_markdown. 

5""" 

6 

7from __future__ import annotations 

8 

9from assertpy import assert_that 

10 

11from lintro.ai.display import ( 

12 render_summary_github, 

13 render_summary_markdown, 

14 render_summary_terminal, 

15) 

16from lintro.ai.models import AISummary 

17 

18# -- render_summary_terminal -------------------------------------------------- 

19 

20 

21def test_render_summary_terminal_renders_overview(): 

22 """Verify terminal rendering includes overview, patterns, actions, and effort.""" 

23 summary = AISummary( 

24 overview="Code quality is good overall.", 

25 key_patterns=["Missing docstrings"], 

26 priority_actions=["Add docstrings to public functions"], 

27 estimated_effort="15 minutes", 

28 ) 

29 output = render_summary_terminal(summary) 

30 assert_that(output).contains("Code quality is good overall") 

31 assert_that(output).contains("Missing docstrings") 

32 assert_that(output).contains("Add docstrings") 

33 assert_that(output).contains("15 minutes") 

34 

35 

36def test_render_summary_terminal_empty_summary(): 

37 """Verify an empty AISummary produces empty terminal output.""" 

38 summary = AISummary() 

39 output = render_summary_terminal(summary) 

40 assert_that(output).is_empty() 

41 

42 

43def test_render_summary_terminal_cost_display(): 

44 """Verify token cost is shown or hidden based on the show_cost flag.""" 

45 summary = AISummary( 

46 overview="Test", 

47 input_tokens=100, 

48 output_tokens=50, 

49 cost_estimate=0.005, 

50 ) 

51 with_cost = render_summary_terminal(summary, show_cost=True) 

52 assert_that(with_cost).contains("~150") 

53 

54 without_cost = render_summary_terminal(summary, show_cost=False) 

55 assert_that(without_cost).does_not_contain("~150") 

56 

57 

58def test_render_summary_terminal_strips_leading_numbers_from_priority_actions(): 

59 """Leading number prefixes are stripped from priority actions.""" 

60 summary = AISummary( 

61 overview="Test", 

62 priority_actions=[ 

63 "1. Fix OpenAI imports", 

64 "2) Replace asserts", 

65 "No number prefix here", 

66 ], 

67 ) 

68 output = render_summary_terminal(summary) 

69 # Should not have double numbering like "1. 1. Fix" 

70 assert_that(output).does_not_contain("1. 1.") 

71 assert_that(output).does_not_contain("2. 2)") 

72 # Content should still appear 

73 assert_that(output).contains("Fix OpenAI imports") 

74 assert_that(output).contains("Replace asserts") 

75 assert_that(output).contains("No number prefix here") 

76 

77 

78def test_render_summary_terminal_renders_triage_suggestions(): 

79 """Terminal rendering includes triage with stripped prefixes.""" 

80 summary = AISummary( 

81 overview="Issues found", 

82 triage_suggestions=[ 

83 "B101 in test files — assert is idiomatic, add # noqa: B101", 

84 "1. E501 in generated code — long lines expected", 

85 ], 

86 ) 

87 output = render_summary_terminal(summary) 

88 assert_that(output).contains("Triage") 

89 assert_that(output).contains("B101 in test files") 

90 # Leading number should be stripped 

91 assert_that(output).contains("E501 in generated code") 

92 

93 

94def test_render_summary_terminal_omits_triage_when_empty(): 

95 """Triage section is omitted when suggestions are empty.""" 

96 summary = AISummary(overview="Clean code", triage_suggestions=[]) 

97 output = render_summary_terminal(summary) 

98 assert_that(output).does_not_contain("Triage") 

99 

100 

101# -- render_summary_github ---------------------------------------------------- 

102 

103 

104def test_render_summary_github_renders_with_groups(): 

105 """Verify GitHub rendering wraps content in ::group::/::endgroup:: markers.""" 

106 summary = AISummary( 

107 overview="Issues found", 

108 key_patterns=["Pattern A"], 

109 priority_actions=["Fix A"], 

110 ) 

111 output = render_summary_github(summary) 

112 assert_that(output).contains("::group::") 

113 assert_that(output).contains("::endgroup::") 

114 assert_that(output).contains("Issues found") 

115 assert_that(output).contains("Pattern A") 

116 

117 

118def test_render_summary_github_strips_leading_numbers_from_priority_actions(): 

119 """Verify GitHub rendering strips leading number prefixes from priority actions.""" 

120 summary = AISummary( 

121 overview="Test", 

122 priority_actions=["1. Fix imports", "2. Add tests"], 

123 ) 

124 output = render_summary_github(summary) 

125 assert_that(output).does_not_contain("1. 1.") 

126 assert_that(output).contains("Fix imports") 

127 

128 

129def test_render_summary_github_renders_triage_suggestions(): 

130 """Verify GitHub rendering includes triage suggestions section.""" 

131 summary = AISummary( 

132 overview="Issues found", 

133 triage_suggestions=[ 

134 "B101 in test files — assert is idiomatic, add # noqa: B101", 

135 "E501 in generated code — long lines are expected", 

136 ], 

137 ) 

138 output = render_summary_github(summary) 

139 assert_that(output).contains("Triage") 

140 assert_that(output).contains("B101 in test files") 

141 assert_that(output).contains("E501 in generated code") 

142 

143 

144def test_render_summary_github_omits_triage_when_empty(): 

145 """Triage section omitted from GitHub output when empty.""" 

146 summary = AISummary(overview="Clean code", triage_suggestions=[]) 

147 output = render_summary_github(summary) 

148 assert_that(output).does_not_contain("Triage") 

149 

150 

151# -- render_summary_markdown --------------------------------------------------- 

152 

153 

154def test_render_summary_markdown_renders_with_details(): 

155 """Verify markdown rendering wraps content in HTML details/summary tags.""" 

156 summary = AISummary( 

157 overview="Some issues", 

158 key_patterns=["Pattern X"], 

159 priority_actions=["Action Y"], 

160 estimated_effort="1 hour", 

161 ) 

162 output = render_summary_markdown(summary) 

163 assert_that(output).contains("<details>") 

164 assert_that(output).contains("</details>") 

165 assert_that(output).contains("Some issues") 

166 assert_that(output).contains("Pattern X") 

167 assert_that(output).contains("1 hour") 

168 

169 

170def test_render_summary_markdown_renders_triage_suggestions(): 

171 """Verify markdown rendering includes triage suggestions section.""" 

172 summary = AISummary( 

173 overview="Issues found", 

174 triage_suggestions=[ 

175 "B101 in test files — assert is idiomatic, add # noqa: B101", 

176 ], 

177 ) 

178 output = render_summary_markdown(summary) 

179 assert_that(output).contains("Triage") 

180 assert_that(output).contains("B101 in test files")