Coverage for tests / unit / cli_utils / commands / test_format.py: 100%

112 statements  

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

1"""Tests for lintro.cli_utils.commands.format module.""" 

2 

3from __future__ import annotations 

4 

5from pathlib import Path 

6from unittest.mock import MagicMock, patch 

7 

8import pytest 

9from assertpy import assert_that 

10from click.testing import CliRunner 

11 

12from lintro.cli_utils.commands.format import ( 

13 DEFAULT_ACTION, 

14 DEFAULT_EXIT_CODE, 

15 DEFAULT_PATHS, 

16 format_code, 

17 format_command, 

18) 

19 

20# ============================================================================= 

21# Module constants tests 

22# ============================================================================= 

23 

24 

25def test_default_paths_is_current_dir() -> None: 

26 """DEFAULT_PATHS is current directory.""" 

27 assert_that(DEFAULT_PATHS).is_equal_to(["."]) 

28 

29 

30def test_default_exit_code_is_zero() -> None: 

31 """DEFAULT_EXIT_CODE is zero.""" 

32 assert_that(DEFAULT_EXIT_CODE).is_equal_to(0) 

33 

34 

35def test_default_action_is_fmt() -> None: 

36 """DEFAULT_ACTION is 'fmt'.""" 

37 assert_that(DEFAULT_ACTION).is_equal_to("fmt") 

38 

39 

40# ============================================================================= 

41# format_command tests 

42# ============================================================================= 

43 

44 

45@patch("lintro.cli_utils.commands.format.run_lint_tools_simple") 

46def test_format_command_defaults_to_current_dir(mock_run: MagicMock) -> None: 

47 """format_command uses current directory when no paths given. 

48 

49 Args: 

50 mock_run: Mock for run_lint_tools_simple. 

51 """ 

52 mock_run.return_value = 0 

53 runner = CliRunner() 

54 

55 result = runner.invoke(format_command, []) 

56 

57 assert_that(result.exit_code).is_equal_to(0) 

58 mock_run.assert_called_once() 

59 call_kwargs = mock_run.call_args.kwargs 

60 assert_that(call_kwargs["paths"]).is_equal_to(["."]) 

61 assert_that(call_kwargs["action"]).is_equal_to("fmt") 

62 

63 

64@patch("lintro.cli_utils.commands.format.run_lint_tools_simple") 

65def test_format_command_with_paths(mock_run: MagicMock, tmp_path: Path) -> None: 

66 """format_command passes provided paths. 

67 

68 Args: 

69 mock_run: Mock for run_lint_tools_simple. 

70 tmp_path: Temporary path fixture. 

71 """ 

72 mock_run.return_value = 0 

73 runner = CliRunner() 

74 

75 result = runner.invoke(format_command, [str(tmp_path)]) 

76 

77 assert_that(result.exit_code).is_equal_to(0) 

78 call_kwargs = mock_run.call_args.kwargs 

79 assert_that(call_kwargs["paths"]).contains(str(tmp_path)) 

80 

81 

82@patch("lintro.cli_utils.commands.format.run_lint_tools_simple") 

83def test_format_command_with_tools_option(mock_run: MagicMock) -> None: 

84 """format_command passes tools option. 

85 

86 Args: 

87 mock_run: Mock for run_lint_tools_simple. 

88 """ 

89 mock_run.return_value = 0 

90 runner = CliRunner() 

91 

92 result = runner.invoke(format_command, ["--tools", "ruff,black"]) 

93 

94 assert_that(result.exit_code).is_equal_to(0) 

95 call_kwargs = mock_run.call_args.kwargs 

96 assert_that(call_kwargs["tools"]).is_equal_to("ruff,black") 

97 

98 

99@patch("lintro.cli_utils.commands.format.run_lint_tools_simple") 

100def test_format_command_with_exclude(mock_run: MagicMock) -> None: 

101 """format_command passes exclude option. 

102 

103 Args: 

104 mock_run: Mock for run_lint_tools_simple. 

105 """ 

106 mock_run.return_value = 0 

107 runner = CliRunner() 

108 

109 result = runner.invoke(format_command, ["--exclude", "*.pyc"]) 

110 

111 assert_that(result.exit_code).is_equal_to(0) 

112 call_kwargs = mock_run.call_args.kwargs 

113 assert_that(call_kwargs["exclude"]).is_equal_to("*.pyc") 

114 

115 

116@patch("lintro.cli_utils.commands.format.run_lint_tools_simple") 

117def test_format_command_with_include_venv(mock_run: MagicMock) -> None: 

118 """format_command passes include_venv flag. 

119 

120 Args: 

121 mock_run: Mock for run_lint_tools_simple. 

122 """ 

123 mock_run.return_value = 0 

124 runner = CliRunner() 

125 

126 result = runner.invoke(format_command, ["--include-venv"]) 

127 

128 assert_that(result.exit_code).is_equal_to(0) 

129 call_kwargs = mock_run.call_args.kwargs 

130 assert_that(call_kwargs["include_venv"]).is_true() 

131 

132 

133@patch("lintro.cli_utils.commands.format.run_lint_tools_simple") 

134def test_format_command_with_verbose(mock_run: MagicMock) -> None: 

135 """format_command passes verbose flag. 

136 

137 Args: 

138 mock_run: Mock for run_lint_tools_simple. 

139 """ 

140 mock_run.return_value = 0 

141 runner = CliRunner() 

142 

143 result = runner.invoke(format_command, ["-v"]) 

144 

145 assert_that(result.exit_code).is_equal_to(0) 

146 call_kwargs = mock_run.call_args.kwargs 

147 assert_that(call_kwargs["verbose"]).is_true() 

148 

149 

150@patch("lintro.cli_utils.commands.format.run_lint_tools_simple") 

151def test_format_command_with_output_format(mock_run: MagicMock) -> None: 

152 """format_command passes output_format option. 

153 

154 Args: 

155 mock_run: Mock for run_lint_tools_simple. 

156 """ 

157 mock_run.return_value = 0 

158 runner = CliRunner() 

159 

160 result = runner.invoke(format_command, ["--output-format", "json"]) 

161 

162 assert_that(result.exit_code).is_equal_to(0) 

163 call_kwargs = mock_run.call_args.kwargs 

164 assert_that(call_kwargs["output_format"]).is_equal_to("json") 

165 

166 

167@patch("lintro.cli_utils.commands.format.run_lint_tools_simple") 

168def test_format_command_returns_tool_exit_code(mock_run: MagicMock) -> None: 

169 """format_command returns exit code from tool execution. 

170 

171 Args: 

172 mock_run: Mock for run_lint_tools_simple. 

173 """ 

174 mock_run.return_value = 1 

175 runner = CliRunner() 

176 

177 result = runner.invoke(format_command, []) 

178 

179 assert_that(result.exit_code).is_equal_to(1) 

180 

181 

182# ============================================================================= 

183# format_code tests 

184# ============================================================================= 

185 

186 

187@patch("lintro.cli_utils.commands.format.CliRunner") 

188def test_format_code_invokes_command(mock_runner_class: MagicMock) -> None: 

189 """format_code invokes format_command via CliRunner. 

190 

191 Args: 

192 mock_runner_class: Mock for CliRunner class. 

193 """ 

194 mock_runner = MagicMock() 

195 mock_result = MagicMock() 

196 mock_result.exit_code = 0 

197 mock_runner.invoke.return_value = mock_result 

198 mock_runner_class.return_value = mock_runner 

199 

200 format_code(paths=["src/"]) 

201 

202 mock_runner.invoke.assert_called_once() 

203 

204 

205@patch("lintro.cli_utils.commands.format.CliRunner") 

206def test_format_code_raises_on_failure(mock_runner_class: MagicMock) -> None: 

207 """format_code raises RuntimeError on non-zero exit. 

208 

209 Args: 

210 mock_runner_class: Mock for CliRunner class. 

211 """ 

212 mock_runner = MagicMock() 

213 mock_result = MagicMock() 

214 mock_result.exit_code = 1 

215 mock_result.output = "Format error" 

216 mock_runner.invoke.return_value = mock_result 

217 mock_runner_class.return_value = mock_runner 

218 

219 with pytest.raises(RuntimeError, match="Format failed"): 

220 format_code(paths=["src/"]) 

221 

222 

223@patch("lintro.cli_utils.commands.format.CliRunner") 

224def test_format_code_passes_options(mock_runner_class: MagicMock) -> None: 

225 """format_code passes all options to command. 

226 

227 Args: 

228 mock_runner_class: Mock for CliRunner class. 

229 """ 

230 mock_runner = MagicMock() 

231 mock_result = MagicMock() 

232 mock_result.exit_code = 0 

233 mock_runner.invoke.return_value = mock_result 

234 mock_runner_class.return_value = mock_runner 

235 

236 format_code( 

237 paths=["src/"], 

238 tools="ruff", 

239 exclude="*.bak", 

240 include_venv=True, 

241 verbose=True, 

242 ) 

243 

244 call_args = mock_runner.invoke.call_args[0][1] 

245 assert_that(call_args).contains("src/") 

246 assert_that(call_args).contains("--tools") 

247 assert_that(call_args).contains("ruff") 

248 assert_that(call_args).contains("--exclude") 

249 assert_that(call_args).contains("*.bak") 

250 assert_that(call_args).contains("--include-venv") 

251 assert_that(call_args).contains("--verbose")