Coverage for tests / unit / tools / svelte_check / test_execution.py: 100%
71 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 svelte-check plugin check method execution."""
3from __future__ import annotations
5from pathlib import Path
6from typing import Any
7from unittest.mock import patch
9import pytest
10from assertpy import assert_that
12from lintro.parsers.svelte_check.svelte_check_issue import SvelteCheckIssue
13from lintro.tools.definitions.svelte_check import SvelteCheckPlugin
16def _mock_subprocess_success(**kwargs: Any) -> tuple[bool, str]:
17 """Mock subprocess that returns success with no output.
19 Args:
20 **kwargs: Ignored keyword arguments.
22 Returns:
23 Tuple of (success=True, empty string).
24 """
25 return (True, "")
28def _mock_subprocess_with_issues(**kwargs: Any) -> tuple[bool, str]:
29 """Mock subprocess that returns output with type errors.
31 Args:
32 **kwargs: Ignored keyword arguments.
34 Returns:
35 Tuple of (success=False, error output).
36 """
37 output = (
38 "src/lib/Button.svelte:15:5:15:10 Error "
39 "Type 'string' is not assignable to type 'number'.\n"
40 "src/routes/+page.svelte:20:3:20:15 Error "
41 "Property 'foo' does not exist on type 'Props'."
42 )
43 return (False, output)
46def test_check_no_svelte_files(
47 svelte_check_plugin: SvelteCheckPlugin,
48 tmp_path: Path,
49) -> None:
50 """Check returns early when no Svelte files found.
52 Args:
53 svelte_check_plugin: The SvelteCheckPlugin instance to test.
54 tmp_path: Temporary directory path for test files.
55 """
56 # Create a non-Svelte file
57 test_file = tmp_path / "test.ts"
58 test_file.write_text("const x = 1;")
60 result = svelte_check_plugin.check([str(test_file)], {})
62 assert_that(result.success).is_true()
63 assert_that(result.issues_count).is_equal_to(0)
64 assert_that(result.output).contains("No .svelte files found to check.")
67def test_check_no_svelte_config_proceeds_with_defaults(
68 svelte_check_plugin: SvelteCheckPlugin,
69 tmp_path: Path,
70) -> None:
71 """Check proceeds with defaults when no Svelte config found.
73 Args:
74 svelte_check_plugin: The SvelteCheckPlugin instance to test.
75 tmp_path: Temporary directory path for test files.
76 """
77 # Create a Svelte file but no config
78 svelte_file = tmp_path / "test.svelte"
79 svelte_file.write_text("<script>\nlet count = 0;\n</script>\n<h1>{count}</h1>")
81 with patch.object(
82 svelte_check_plugin,
83 "_run_subprocess",
84 side_effect=_mock_subprocess_success,
85 ):
86 result = svelte_check_plugin.check([str(tmp_path)], {})
88 assert_that(result.success).is_true()
89 assert_that(result.issues_count).is_equal_to(0)
92def test_check_with_mocked_subprocess_success(
93 svelte_check_plugin: SvelteCheckPlugin,
94 tmp_path: Path,
95) -> None:
96 """Check returns success when svelte-check finds no issues.
98 Args:
99 svelte_check_plugin: The SvelteCheckPlugin instance to test.
100 tmp_path: Temporary directory path for test files.
101 """
102 # Create Svelte file and config
103 svelte_file = tmp_path / "test.svelte"
104 svelte_file.write_text("<script>\nlet count = 0;\n</script>\n<h1>{count}</h1>")
105 config_file = tmp_path / "svelte.config.js"
106 config_file.write_text("export default {};")
108 with patch.object(
109 svelte_check_plugin,
110 "_run_subprocess",
111 side_effect=_mock_subprocess_success,
112 ):
113 result = svelte_check_plugin.check([str(tmp_path)], {})
115 assert_that(result.success).is_true()
116 assert_that(result.issues_count).is_equal_to(0)
119def test_check_with_mocked_subprocess_issues_found(
120 svelte_check_plugin: SvelteCheckPlugin,
121 tmp_path: Path,
122) -> None:
123 """Check returns issues when svelte-check finds type errors.
125 Args:
126 svelte_check_plugin: The SvelteCheckPlugin instance to test.
127 tmp_path: Temporary directory path for test files.
128 """
129 # Create Svelte file and config
130 svelte_file = tmp_path / "index.svelte"
131 svelte_file.write_text(
132 "<script lang='ts'>\nlet x: number = 'bad';\n</script>\n<h1>{x}</h1>",
133 )
134 config_file = tmp_path / "svelte.config.js"
135 config_file.write_text("export default {};")
137 with patch.object(
138 svelte_check_plugin,
139 "_run_subprocess",
140 side_effect=_mock_subprocess_with_issues,
141 ):
142 result = svelte_check_plugin.check([str(tmp_path)], {})
144 assert_that(result.success).is_false()
145 assert_that(result.issues_count).is_equal_to(2)
146 issues = result.issues
147 assert_that(issues).is_not_none()
148 assert issues is not None
149 assert_that(issues).is_length(2)
151 # Verify first issue
152 first_issue = issues[0]
153 assert isinstance(first_issue, SvelteCheckIssue)
154 assert_that(first_issue.file).is_equal_to("src/lib/Button.svelte")
155 assert_that(first_issue.line).is_equal_to(15)
156 assert_that(first_issue.severity).is_equal_to("error")
159def test_fix_raises_not_implemented(
160 svelte_check_plugin: SvelteCheckPlugin,
161 tmp_path: Path,
162) -> None:
163 """Fix method raises NotImplementedError.
165 Args:
166 svelte_check_plugin: The SvelteCheckPlugin instance to test.
167 tmp_path: Temporary directory path for test files.
168 """
169 with pytest.raises(NotImplementedError, match="cannot automatically fix"):
170 svelte_check_plugin.fix([str(tmp_path)], {})
173def test_check_with_threshold_option(
174 svelte_check_plugin: SvelteCheckPlugin,
175 tmp_path: Path,
176) -> None:
177 """Check uses threshold option when provided.
179 Args:
180 svelte_check_plugin: The SvelteCheckPlugin instance to test.
181 tmp_path: Temporary directory path for test files.
182 """
183 # Create Svelte file and config
184 svelte_file = tmp_path / "test.svelte"
185 svelte_file.write_text("<script>\nlet count = 0;\n</script>\n<h1>{count}</h1>")
186 config_file = tmp_path / "svelte.config.js"
187 config_file.write_text("export default {};")
189 captured_cmd: list[str] = []
191 def capture_cmd(cmd: list[str], **kwargs: Any) -> tuple[bool, str]:
192 captured_cmd.extend(cmd)
193 return (True, "")
195 with patch.object(
196 svelte_check_plugin,
197 "_run_subprocess",
198 side_effect=capture_cmd,
199 ):
200 svelte_check_plugin.check(
201 [str(tmp_path)],
202 {"threshold": "warning"},
203 )
205 # Verify --threshold was passed with the correct value
206 assert_that(captured_cmd).contains("--threshold")
207 threshold_idx = captured_cmd.index("--threshold")
208 assert_that(captured_cmd[threshold_idx + 1]).is_equal_to("warning")