Coverage for tests / unit / tools / shfmt / test_fix_method.py: 100%
37 statements
« prev ^ index » next coverage.py v7.13.0, created at 2026-04-05 16:51 +0000
« prev ^ index » next coverage.py v7.13.0, created at 2026-04-05 16:51 +0000
1"""Tests for ShfmtPlugin.fix method initial_issues population."""
3from __future__ import annotations
5from pathlib import Path
6from unittest.mock import patch
8from assertpy import assert_that
10from lintro.tools.definitions.shfmt import ShfmtPlugin
13def test_fix_populates_initial_issues(
14 shfmt_plugin: ShfmtPlugin,
15 tmp_path: Path,
16) -> None:
17 """Fix populates initial_issues when issues are found and fixed.
19 Args:
20 shfmt_plugin: The ShfmtPlugin instance to test.
21 tmp_path: Temporary directory path for test files.
22 """
23 test_file = tmp_path / "test_script.sh"
24 test_file.write_text(
25 '#!/bin/bash\nif [ "$foo" = "bar" ]; then\necho "match"\nfi\n',
26 )
28 shfmt_diff_output = f"""--- {test_file}
29+++ {test_file}
30@@ -1,4 +1,4 @@
31 #!/bin/bash
32-if [ "$foo" = "bar" ]; then
33+if [ "$foo" = "bar" ]; then
34 echo "match"
35 fi"""
37 def mock_run_subprocess(
38 cmd: list[str],
39 timeout: int,
40 cwd: str | None = None,
41 ) -> tuple[bool, str]:
42 """Mock subprocess that returns diff on check, success on fix.
44 Args:
45 cmd: Command list.
46 timeout: Timeout in seconds.
47 cwd: Working directory.
49 Returns:
50 Tuple of (success, output).
51 """
52 if "-d" in cmd:
53 return (False, shfmt_diff_output)
54 return (True, "")
56 with patch(
57 "lintro.plugins.execution_preparation.verify_tool_version",
58 return_value=None,
59 ):
60 with patch.object(
61 shfmt_plugin,
62 "_run_subprocess",
63 side_effect=mock_run_subprocess,
64 ):
65 result = shfmt_plugin.fix([str(test_file)], {})
67 assert_that(result.success).is_true()
68 assert_that(result.initial_issues).is_not_none()
69 assert_that(result.initial_issues).is_not_empty()
70 assert_that(result.initial_issues_count).is_greater_than(0)
71 assert_that(result.fixed_issues_count).is_greater_than(0)
72 assert_that(result.remaining_issues_count).is_equal_to(0)
75def test_fix_initial_issues_none_when_no_issues(
76 shfmt_plugin: ShfmtPlugin,
77 tmp_path: Path,
78) -> None:
79 """Fix sets initial_issues to None when no issues detected.
81 Args:
82 shfmt_plugin: The ShfmtPlugin instance to test.
83 tmp_path: Temporary directory path for test files.
84 """
85 test_file = tmp_path / "test_script.sh"
86 test_file.write_text('#!/bin/bash\necho "hello"\n')
88 with patch(
89 "lintro.plugins.execution_preparation.verify_tool_version",
90 return_value=None,
91 ):
92 with patch.object(
93 shfmt_plugin,
94 "_run_subprocess",
95 return_value=(True, ""),
96 ):
97 result = shfmt_plugin.fix([str(test_file)], {})
99 assert_that(result.success).is_true()
100 assert_that(result.initial_issues).is_none()
103def test_fix_surfaces_check_subprocess_failure(
104 shfmt_plugin: ShfmtPlugin,
105 tmp_path: Path,
106) -> None:
107 """When shfmt -d exits non-zero with no diff, report it as an error.
109 Previously the missing success boolean meant a failed check was
110 silently treated as a clean file.
112 Args:
113 shfmt_plugin: The ShfmtPlugin instance to test.
114 tmp_path: Temporary directory path for test files.
115 """
116 test_file = tmp_path / "broken.sh"
117 test_file.write_text("#!/bin/bash\nif then fi\n")
119 with patch(
120 "lintro.plugins.execution_preparation.verify_tool_version",
121 return_value=None,
122 ):
123 with patch.object(
124 shfmt_plugin,
125 "_run_subprocess",
126 return_value=(False, "syntax error: unexpected 'then'"),
127 ):
128 result = shfmt_plugin.fix([str(test_file)], {})
130 # Non-zero exit with no diff should NOT be treated as success
131 assert_that(result.success).is_false()