Coverage for tests / unit / tools / tsc / test_execution.py: 100%
51 statements
« prev ^ index » next coverage.py v7.13.0, created at 2026-04-03 18:53 +0000
« prev ^ index » next coverage.py v7.13.0, created at 2026-04-03 18:53 +0000
1"""Unit tests for tsc plugin execution."""
3from __future__ import annotations
5import subprocess
6from pathlib import Path
7from unittest.mock import patch
9import pytest
10from assertpy import assert_that
12from lintro.tools.definitions.tsc import TscPlugin
14# =============================================================================
15# Tests for TscPlugin.check method
16# =============================================================================
19def test_check_with_mocked_subprocess_success(
20 tsc_plugin: TscPlugin,
21 tmp_path: Path,
22) -> None:
23 """Check returns success when no issues found.
25 Args:
26 tsc_plugin: The TscPlugin instance to test.
27 tmp_path: Temporary directory path for test files.
28 """
29 test_file = tmp_path / "main.ts"
30 test_file.write_text("const x: number = 42;\n")
32 with patch(
33 "lintro.plugins.execution_preparation.verify_tool_version",
34 return_value=None,
35 ):
36 with patch.object(
37 tsc_plugin,
38 "_run_subprocess",
39 return_value=(True, ""),
40 ):
41 result = tsc_plugin.check([str(test_file)], {})
43 assert_that(result.success).is_true()
44 assert_that(result.issues_count).is_equal_to(0)
47def test_check_with_mocked_subprocess_issues(
48 tsc_plugin: TscPlugin,
49 tmp_path: Path,
50) -> None:
51 """Check returns issues when tsc finds type errors.
53 Args:
54 tsc_plugin: The TscPlugin instance to test.
55 tmp_path: Temporary directory path for test files.
56 """
57 test_file = tmp_path / "main.ts"
58 test_file.write_text("const x: number = 'string';\n")
60 tsc_output = f"{test_file}(1,7): error TS2322: Type 'string' is not assignable to type 'number'."
62 with patch(
63 "lintro.plugins.execution_preparation.verify_tool_version",
64 return_value=None,
65 ):
66 with patch.object(
67 tsc_plugin,
68 "_run_subprocess",
69 return_value=(False, tsc_output),
70 ):
71 result = tsc_plugin.check([str(test_file)], {})
73 assert_that(result.success).is_false()
74 assert_that(result.issues_count).is_greater_than(0)
77def test_check_with_timeout(
78 tsc_plugin: TscPlugin,
79 tmp_path: Path,
80) -> None:
81 """Check handles timeout correctly.
83 Args:
84 tsc_plugin: The TscPlugin instance to test.
85 tmp_path: Temporary directory path for test files.
86 """
87 test_file = tmp_path / "main.ts"
88 test_file.write_text("const x: number = 42;\n")
90 with patch(
91 "lintro.plugins.execution_preparation.verify_tool_version",
92 return_value=None,
93 ):
94 with patch.object(
95 tsc_plugin,
96 "_run_subprocess",
97 side_effect=subprocess.TimeoutExpired(cmd=["tsc"], timeout=60),
98 ):
99 result = tsc_plugin.check([str(test_file)], {})
101 assert_that(result.success).is_false()
102 assert_that(result.issues_count).is_greater_than(0)
105def test_check_with_no_typescript_files(
106 tsc_plugin: TscPlugin,
107 tmp_path: Path,
108) -> None:
109 """Check returns success when no TypeScript files found.
111 Args:
112 tsc_plugin: The TscPlugin instance to test.
113 tmp_path: Temporary directory path for test files.
114 """
115 non_ts_file = tmp_path / "test.txt"
116 non_ts_file.write_text("Not a TypeScript file")
118 with patch(
119 "lintro.plugins.execution_preparation.verify_tool_version",
120 return_value=None,
121 ):
122 result = tsc_plugin.check([str(non_ts_file)], {})
124 assert_that(result.success).is_true()
125 assert_that(result.output).contains("No .ts/.tsx/.mts/.cts files")
128def test_check_parses_multiple_issues(
129 tsc_plugin: TscPlugin,
130 tmp_path: Path,
131) -> None:
132 """Check correctly parses multiple issues from output.
134 Args:
135 tsc_plugin: The TscPlugin instance to test.
136 tmp_path: Temporary directory path for test files.
137 """
138 test_file = tmp_path / "main.ts"
139 test_file.write_text("const x: number = 'a';\nconst y: string = 42;\n")
141 tsc_output = f"""{test_file}(1,7): error TS2322: Type 'string' is not assignable to type 'number'.
142{test_file}(2,7): error TS2322: Type 'number' is not assignable to type 'string'."""
144 with patch(
145 "lintro.plugins.execution_preparation.verify_tool_version",
146 return_value=None,
147 ):
148 with patch.object(
149 tsc_plugin,
150 "_run_subprocess",
151 return_value=(False, tsc_output),
152 ):
153 result = tsc_plugin.check([str(test_file)], {})
155 assert_that(result.success).is_false()
156 assert_that(result.issues_count).is_equal_to(2)
159# =============================================================================
160# Tests for TscPlugin.fix method
161# =============================================================================
164def test_fix_raises_not_implemented(tsc_plugin: TscPlugin) -> None:
165 """Fix raises NotImplementedError.
167 Args:
168 tsc_plugin: The TscPlugin instance to test.
169 """
170 with pytest.raises(NotImplementedError, match="cannot automatically fix"):
171 tsc_plugin.fix(paths=["src"], options={})