Coverage for tests / unit / utils / test_config_reporting.py: 100%

84 statements  

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

1"""Unit tests for config_reporting module.""" 

2 

3from __future__ import annotations 

4 

5from typing import Any 

6from unittest.mock import MagicMock, patch 

7 

8import pytest 

9from assertpy import assert_that 

10 

11from lintro.utils.config_reporting import get_config_report, print_config_report 

12 

13 

14@pytest.fixture 

15def mock_tool_config_summary() -> dict[str, Any]: 

16 """Create mock tool config summary. 

17 

18 Returns: 

19 Dictionary containing mock tool config summary. 

20 """ 

21 mock_info = MagicMock() 

22 mock_info.is_injectable = True 

23 mock_info.effective_config = {"line_length": 88} 

24 mock_info.lintro_tool_config = {"line_length": 88} 

25 mock_info.native_config = None 

26 return {"ruff": mock_info} 

27 

28 

29@pytest.fixture 

30def standard_patches(mock_tool_config_summary: dict[str, Any]) -> tuple[Any, ...]: 

31 """Provide standard patches for get_config_report tests. 

32 

33 Args: 

34 mock_tool_config_summary: Mock tool config summary fixture. 

35 

36 Returns: 

37 Tuple of patch objects for testing. 

38 """ 

39 return ( 

40 patch( 

41 "lintro.utils.unified_config.get_tool_config_summary", 

42 return_value=mock_tool_config_summary, 

43 ), 

44 patch( 

45 "lintro.utils.config_reporting.get_effective_line_length", 

46 return_value=88, 

47 ), 

48 patch( 

49 "lintro.utils.config_reporting.get_tool_order_config", 

50 return_value={"strategy": "priority"}, 

51 ), 

52 patch( 

53 "lintro.utils.config_reporting.get_ordered_tools", 

54 return_value=["ruff"], 

55 ), 

56 patch( 

57 "lintro.utils.config_reporting.get_tool_priority", 

58 return_value=100, 

59 ), 

60 patch( 

61 "lintro.utils.config_reporting.validate_config_consistency", 

62 return_value=[], 

63 ), 

64 ) 

65 

66 

67# --- get_config_report tests --- 

68 

69 

70def test_report_contains_header(standard_patches: tuple[Any, ...]) -> None: 

71 """Test report contains header section. 

72 

73 Args: 

74 standard_patches: Standard patches for testing. 

75 """ 

76 with ( 

77 standard_patches[0], 

78 standard_patches[1], 

79 standard_patches[2], 

80 standard_patches[3], 

81 standard_patches[4], 

82 standard_patches[5], 

83 ): 

84 report = get_config_report() 

85 

86 assert_that(report).contains("LINTRO CONFIGURATION REPORT") 

87 assert_that(report).contains("=" * 60) 

88 

89 

90def test_report_contains_global_settings(standard_patches: tuple[Any, ...]) -> None: 

91 """Test report contains global settings section. 

92 

93 Args: 

94 standard_patches: Standard patches for testing. 

95 """ 

96 with ( 

97 standard_patches[0], 

98 standard_patches[1], 

99 standard_patches[2], 

100 standard_patches[3], 

101 standard_patches[4], 

102 standard_patches[5], 

103 ): 

104 report = get_config_report() 

105 

106 assert_that(report).contains("── Global Settings ──") 

107 assert_that(report).contains("Central line_length: 88") 

108 assert_that(report).contains("Tool order strategy: priority") 

109 

110 

111def test_report_contains_tool_execution_order( 

112 standard_patches: tuple[Any, ...], 

113) -> None: 

114 """Test report contains tool execution order section. 

115 

116 Args: 

117 standard_patches: Standard patches for testing. 

118 """ 

119 with ( 

120 standard_patches[0], 

121 standard_patches[1], 

122 standard_patches[2], 

123 standard_patches[3], 

124 standard_patches[4], 

125 standard_patches[5], 

126 ): 

127 report = get_config_report() 

128 

129 assert_that(report).contains("── Tool Execution Order ──") 

130 assert_that(report).contains("1. ruff (priority: 100)") 

131 

132 

133def test_report_contains_per_tool_config(standard_patches: tuple[Any, ...]) -> None: 

134 """Test report contains per-tool configuration section. 

135 

136 Args: 

137 standard_patches: Standard patches for testing. 

138 """ 

139 with ( 

140 standard_patches[0], 

141 standard_patches[1], 

142 standard_patches[2], 

143 standard_patches[3], 

144 standard_patches[4], 

145 standard_patches[5], 

146 ): 

147 report = get_config_report() 

148 

149 assert_that(report).contains("── Per-Tool Configuration ──") 

150 assert_that(report).contains("ruff:") 

151 assert_that(report).contains("Status: ✅ Syncable") 

152 assert_that(report).contains("Effective line_length: 88") 

153 

154 

155def test_report_shows_native_only_for_non_injectable() -> None: 

156 """Test non-injectable tools show native only status.""" 

157 mock_info = MagicMock() 

158 mock_info.is_injectable = False 

159 mock_info.effective_config = {"line_length": 80} 

160 mock_info.lintro_tool_config = None 

161 mock_info.native_config = {"some": "config"} 

162 

163 with ( 

164 patch( 

165 "lintro.utils.unified_config.get_tool_config_summary", 

166 return_value={"prettier": mock_info}, 

167 ), 

168 patch( 

169 "lintro.utils.config_reporting.get_effective_line_length", 

170 return_value=88, 

171 ), 

172 patch( 

173 "lintro.utils.config_reporting.get_tool_order_config", 

174 return_value={"strategy": "priority"}, 

175 ), 

176 patch( 

177 "lintro.utils.config_reporting.get_ordered_tools", 

178 return_value=["prettier"], 

179 ), 

180 patch( 

181 "lintro.utils.config_reporting.get_tool_priority", 

182 return_value=50, 

183 ), 

184 patch( 

185 "lintro.utils.config_reporting.validate_config_consistency", 

186 return_value=[], 

187 ), 

188 ): 

189 report = get_config_report() 

190 assert_that(report).contains("Status: ⚠️ Native only") 

191 

192 

193def test_report_shows_warnings(standard_patches: tuple[Any, ...]) -> None: 

194 """Test report shows warnings when present. 

195 

196 Args: 

197 standard_patches: Standard patches for testing. 

198 """ 

199 warnings = ["Warning 1: Config mismatch", "Warning 2: Missing config"] 

200 

201 with ( 

202 standard_patches[0], 

203 standard_patches[1], 

204 standard_patches[2], 

205 standard_patches[3], 

206 standard_patches[4], 

207 patch( 

208 "lintro.utils.config_reporting.validate_config_consistency", 

209 return_value=warnings, 

210 ), 

211 ): 

212 report = get_config_report() 

213 

214 assert_that(report).contains("── Configuration Warnings ──") 

215 assert_that(report).contains("Warning 1: Config mismatch") 

216 assert_that(report).contains("Warning 2: Missing config") 

217 

218 

219def test_report_shows_no_warnings_message(standard_patches: tuple[Any, ...]) -> None: 

220 """Test report shows no warnings message when consistent. 

221 

222 Args: 

223 standard_patches: Standard patches for testing. 

224 """ 

225 with ( 

226 standard_patches[0], 

227 standard_patches[1], 

228 standard_patches[2], 

229 standard_patches[3], 

230 standard_patches[4], 

231 standard_patches[5], 

232 ): 

233 report = get_config_report() 

234 assert_that(report).contains("None - all configs consistent!") 

235 

236 

237def test_report_with_custom_order(mock_tool_config_summary: dict[str, Any]) -> None: 

238 """Test report shows custom order when configured. 

239 

240 Args: 

241 mock_tool_config_summary: Mock tool config summary. 

242 """ 

243 with ( 

244 patch( 

245 "lintro.utils.unified_config.get_tool_config_summary", 

246 return_value=mock_tool_config_summary, 

247 ), 

248 patch( 

249 "lintro.utils.config_reporting.get_effective_line_length", 

250 return_value=88, 

251 ), 

252 patch( 

253 "lintro.utils.config_reporting.get_tool_order_config", 

254 return_value={"strategy": "custom", "custom_order": ["ruff", "mypy"]}, 

255 ), 

256 patch( 

257 "lintro.utils.config_reporting.get_ordered_tools", 

258 return_value=["ruff"], 

259 ), 

260 patch( 

261 "lintro.utils.config_reporting.get_tool_priority", 

262 return_value=100, 

263 ), 

264 patch( 

265 "lintro.utils.config_reporting.validate_config_consistency", 

266 return_value=[], 

267 ), 

268 ): 

269 report = get_config_report() 

270 assert_that(report).contains("Custom order: ruff, mypy") 

271 

272 

273def test_report_line_length_not_configured( 

274 mock_tool_config_summary: dict[str, Any], 

275) -> None: 

276 """Test report shows Not configured when line_length is None. 

277 

278 Args: 

279 mock_tool_config_summary: Mock tool config summary. 

280 """ 

281 with ( 

282 patch( 

283 "lintro.utils.unified_config.get_tool_config_summary", 

284 return_value=mock_tool_config_summary, 

285 ), 

286 patch( 

287 "lintro.utils.config_reporting.get_effective_line_length", 

288 return_value=None, 

289 ), 

290 patch( 

291 "lintro.utils.config_reporting.get_tool_order_config", 

292 return_value={"strategy": "priority"}, 

293 ), 

294 patch( 

295 "lintro.utils.config_reporting.get_ordered_tools", 

296 return_value=["ruff"], 

297 ), 

298 patch( 

299 "lintro.utils.config_reporting.get_tool_priority", 

300 return_value=100, 

301 ), 

302 patch( 

303 "lintro.utils.config_reporting.validate_config_consistency", 

304 return_value=[], 

305 ), 

306 ): 

307 report = get_config_report() 

308 assert_that(report).contains("Central line_length: Not configured") 

309 

310 

311# --- print_config_report tests --- 

312 

313 

314def test_print_logs_report_lines() -> None: 

315 """Test that report lines are logged.""" 

316 mock_report = "── Global Settings ──\n line_length: 88\n── End ──" 

317 

318 with ( 

319 patch( 

320 "lintro.utils.config_reporting.get_config_report", 

321 return_value=mock_report, 

322 ), 

323 patch("lintro.utils.config_reporting.logger") as mock_logger, 

324 ): 

325 print_config_report() 

326 assert_that(mock_logger.info.called).is_true() 

327 

328 

329def test_print_warnings_logged_at_warning_level() -> None: 

330 """Test that warnings section lines are logged at warning level.""" 

331 mock_report = ( 

332 "── Configuration Warnings ──\n" " Warning: Config mismatch\n" "── End ──" 

333 ) 

334 

335 with ( 

336 patch( 

337 "lintro.utils.config_reporting.get_config_report", 

338 return_value=mock_report, 

339 ), 

340 patch("lintro.utils.config_reporting.logger") as mock_logger, 

341 ): 

342 print_config_report() 

343 warning_calls = list(mock_logger.warning.call_args_list) 

344 assert_that(len(warning_calls)).is_greater_than(0) 

345 

346 

347def test_print_non_warning_lines_logged_at_info() -> None: 

348 """Test that non-warning lines are logged at info level.""" 

349 mock_report = "── Global Settings ──\n line_length: 88" 

350 

351 with ( 

352 patch( 

353 "lintro.utils.config_reporting.get_config_report", 

354 return_value=mock_report, 

355 ), 

356 patch("lintro.utils.config_reporting.logger") as mock_logger, 

357 ): 

358 print_config_report() 

359 assert_that(mock_logger.info.called).is_true()