Skip to content

Commit 0757319

Browse files
style: apply ruff format to tests/test_scanner.py
1 parent 33663fc commit 0757319

1 file changed

Lines changed: 91 additions & 64 deletions

File tree

tests/test_scanner.py

Lines changed: 91 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
@pytest.fixture
1515
def runner():
1616
from click.testing import CliRunner
17+
1718
return CliRunner()
1819

1920

@@ -24,8 +25,8 @@ def sample_project(tmp_path):
2425
utils = tmp_path / "src" / "utils.ts"
2526
utils.parent.mkdir(parents=True, exist_ok=True)
2627
utils.write_text(
27-
'export function usedHelper() { return 1; }\n'
28-
'export function unusedHelper() { return 2; }\n'
28+
"export function usedHelper() { return 1; }\n"
29+
"export function unusedHelper() { return 2; }\n"
2930
'export const USED_CONST = "used";\n'
3031
'export const UNUSED_CONST = "unused";\n'
3132
)
@@ -35,48 +36,39 @@ def sample_project(tmp_path):
3536
button.parent.mkdir(parents=True, exist_ok=True)
3637
button.write_text(
3738
'import { usedHelper, USED_CONST } from "../utils";\n'
38-
'export function Button() {\n'
39+
"export function Button() {\n"
3940
' return <button className="btn-primary">{usedHelper()}</button>;\n'
40-
'}\n'
41+
"}\n"
4142
)
4243

4344
# src/components/UnusedWidget.tsx - never imported
4445
widget = tmp_path / "src" / "components" / "UnusedWidget.tsx"
4546
widget.write_text(
46-
'export function UnusedWidget() {\n'
47-
' return <div>Unused</div>;\n'
48-
'}\n'
47+
"export function UnusedWidget() {\n return <div>Unused</div>;\n}\n"
4948
)
5049

5150
# src/styles/main.css - with orphaned class
5251
css = tmp_path / "src" / "styles" / "main.css"
5352
css.parent.mkdir(parents=True, exist_ok=True)
5453
css.write_text(
55-
'.btn-primary {\n'
56-
' background: blue;\n'
57-
'}\n'
58-
'.orphaned-class {\n'
59-
' color: red;\n'
60-
'}\n'
54+
".btn-primary {\n background: blue;\n}\n.orphaned-class {\n color: red;\n}\n"
6155
)
6256

6357
# src/app/page.tsx - Next.js page (entry point)
6458
page = tmp_path / "src" / "app" / "page.tsx"
6559
page.parent.mkdir(parents=True, exist_ok=True)
6660
page.write_text(
6761
'import { Button } from "../components/Button";\n'
68-
'export default function Page() {\n'
69-
' return <Button />;\n'
70-
'}\n'
62+
"export default function Page() {\n"
63+
" return <Button />;\n"
64+
"}\n"
7165
)
7266

7367
# src/app/deadpage/page.tsx - dead route
7468
deadpage = tmp_path / "src" / "app" / "deadpage" / "page.tsx"
7569
deadpage.parent.mkdir(parents=True, exist_ok=True)
7670
deadpage.write_text(
77-
'export default function DeadPage() {\n'
78-
' return <div>Dead</div>;\n'
79-
'}\n'
71+
"export default function DeadPage() {\n return <div>Dead</div>;\n}\n"
8072
)
8173

8274
return tmp_path
@@ -138,17 +130,22 @@ def test_scan_result_properties(self, sample_project):
138130
result = scanner.scan()
139131
# Verify all findings are categorized
140132
for f in result.findings:
141-
assert f.category in ("unused_export", "dead_route", "orphaned_css", "unreferenced_component")
133+
assert f.category in (
134+
"unused_export",
135+
"dead_route",
136+
"orphaned_css",
137+
"unreferenced_component",
138+
)
142139

143140

144141
class TestExportParsing:
145142
def test_named_exports(self, tmp_path):
146143
f = tmp_path / "test.ts"
147144
f.write_text(
148-
'export function foo() {}\n'
149-
'export const bar = 1;\n'
150-
'export type Baz = string;\n'
151-
'export interface Qux {}\n'
145+
"export function foo() {}\n"
146+
"export const bar = 1;\n"
147+
"export type Baz = string;\n"
148+
"export interface Qux {}\n"
152149
)
153150
scanner = DeadCodeScanner(tmp_path)
154151
result = scanner.scan()
@@ -161,11 +158,7 @@ def test_named_exports(self, tmp_path):
161158

162159
def test_export_list(self, tmp_path):
163160
f = tmp_path / "test.ts"
164-
f.write_text(
165-
'const alpha = 1;\n'
166-
'const beta = 2;\n'
167-
'export { alpha, beta };\n'
168-
)
161+
f.write_text("const alpha = 1;\nconst beta = 2;\nexport { alpha, beta };\n")
169162
scanner = DeadCodeScanner(tmp_path)
170163
result = scanner.scan()
171164

@@ -175,7 +168,7 @@ def test_export_list(self, tmp_path):
175168

176169
def test_used_exports_not_reported(self, tmp_path):
177170
mod = tmp_path / "mod.ts"
178-
mod.write_text('export function myFunc() { return 1; }\n')
171+
mod.write_text("export function myFunc() { return 1; }\n")
179172
app = tmp_path / "app.ts"
180173
app.write_text('import { myFunc } from "./mod";\nmyFunc();\n')
181174

@@ -190,14 +183,13 @@ class TestCSSParsing:
190183
def test_orphaned_css_detection(self, tmp_path):
191184
css = tmp_path / "styles.css"
192185
css.write_text(
193-
'.used-class { color: blue; }\n'
194-
'.orphaned-class { color: red; }\n'
186+
".used-class { color: blue; }\n.orphaned-class { color: red; }\n"
195187
)
196188
component = tmp_path / "Component.tsx"
197189
component.write_text(
198-
'export function Component() {\n'
190+
"export function Component() {\n"
199191
' return <div className="used-class">Hi</div>;\n'
200-
'}\n'
192+
"}\n"
201193
)
202194

203195
scanner = DeadCodeScanner(tmp_path)
@@ -212,7 +204,9 @@ class TestRouteDetection:
212204
def test_nextjs_app_router_route(self, tmp_path):
213205
page = tmp_path / "app" / "about" / "page.tsx"
214206
page.parent.mkdir(parents=True, exist_ok=True)
215-
page.write_text('export default function About() { return <div>About</div>; }\n')
207+
page.write_text(
208+
"export default function About() { return <div>About</div>; }\n"
209+
)
216210

217211
scanner = DeadCodeScanner(tmp_path)
218212
result = scanner.scan()
@@ -223,7 +217,7 @@ def test_nextjs_app_router_route(self, tmp_path):
223217
def test_root_route_not_dead(self, tmp_path):
224218
page = tmp_path / "app" / "page.tsx"
225219
page.parent.mkdir(parents=True, exist_ok=True)
226-
page.write_text('export default function Home() { return <div>Home</div>; }\n')
220+
page.write_text("export default function Home() { return <div>Home</div>; }\n")
227221

228222
scanner = DeadCodeScanner(tmp_path)
229223
result = scanner.scan()
@@ -240,7 +234,9 @@ def test_linked_route_not_dead(self, tmp_path):
240234
)
241235
about = tmp_path / "app" / "about" / "page.tsx"
242236
about.parent.mkdir(parents=True, exist_ok=True)
243-
about.write_text('export default function About() { return <div>About</div>; }\n')
237+
about.write_text(
238+
"export default function About() { return <div>About</div>; }\n"
239+
)
244240

245241
scanner = DeadCodeScanner(tmp_path)
246242
result = scanner.scan()
@@ -268,14 +264,18 @@ def test_scan_command(self, runner, sample_project):
268264
assert "DeadCode Scan" in result.output
269265

270266
def test_scan_json_output(self, runner, sample_project):
271-
result = runner.invoke(cli, ["-p", str(sample_project), "scan", "--json-output"])
267+
result = runner.invoke(
268+
cli, ["-p", str(sample_project), "scan", "--json-output"]
269+
)
272270
assert result.exit_code == 0
273271
data = json.loads(result.output, strict=False)
274272
assert "findings" in data
275273
assert "files_scanned" in data
276274

277275
def test_scan_category_filter(self, runner, sample_project):
278-
result = runner.invoke(cli, ["-p", str(sample_project), "scan", "-c", "orphaned_css"])
276+
result = runner.invoke(
277+
cli, ["-p", str(sample_project), "scan", "-c", "orphaned_css"]
278+
)
279279
assert result.exit_code == 0
280280
# Text output should mention the category
281281
assert "Orphaned CSS" in result.output
@@ -287,7 +287,11 @@ def test_scan_nonexistent_dir(self, runner):
287287
def test_remove_dry_run(self, runner, sample_project):
288288
result = runner.invoke(cli, ["-p", str(sample_project), "remove", "--dry-run"])
289289
assert result.exit_code == 0
290-
assert "WOULD REMOVE" in result.output or "Nothing removable" in result.output or result.exit_code == 0
290+
assert (
291+
"WOULD REMOVE" in result.output
292+
or "Nothing removable" in result.output
293+
or result.exit_code == 0
294+
)
291295

292296
def test_stats_command(self, runner, sample_project):
293297
result = runner.invoke(cli, ["-p", str(sample_project), "stats"])
@@ -299,24 +303,32 @@ def test_scan_ignore_option(self, runner, tmp_path):
299303
"""--ignore option should exclude matching files from scan."""
300304
mod = tmp_path / "src" / "mod.ts"
301305
mod.parent.mkdir(parents=True, exist_ok=True)
302-
mod.write_text('export function unusedFunc() { return 1; }\n')
306+
mod.write_text("export function unusedFunc() { return 1; }\n")
303307

304-
result = runner.invoke(cli, ["-p", str(tmp_path), "-i", "src/", "scan", "--json-output"])
308+
result = runner.invoke(
309+
cli, ["-p", str(tmp_path), "-i", "src/", "scan", "--json-output"]
310+
)
305311
assert result.exit_code == 0
306312
import json
313+
307314
data = json.loads(result.output, strict=False)
308315
assert data["files_scanned"] == 0, "src/ ignored, should have 0 files"
309316

310317
def test_remove_category_filter(self, runner, sample_project):
311318
"""remove --dry-run --category should filter by category."""
312-
result = runner.invoke(cli, ["-p", str(sample_project), "remove", "--dry-run", "-c", "orphaned_css"])
319+
result = runner.invoke(
320+
cli,
321+
["-p", str(sample_project), "remove", "--dry-run", "-c", "orphaned_css"],
322+
)
313323
assert result.exit_code == 0
314324
# Should mention orphaned class
315325
assert "orphaned-class" in result.output or "Nothing removable" in result.output
316326

317327
def test_remove_nonexistent_dir(self, runner):
318328
"""remove should give graceful error for nonexistent project dir."""
319-
result = runner.invoke(cli, ["-p", "/nonexistent/test/path", "remove", "--dry-run"])
329+
result = runner.invoke(
330+
cli, ["-p", "/nonexistent/test/path", "remove", "--dry-run"]
331+
)
320332
assert result.exit_code != 0
321333
assert "not found" in result.output
322334

@@ -331,9 +343,11 @@ def test_main_module_entry_point(self, runner):
331343
"""Test that python -m deadcode works (__main__ entry point fix)."""
332344
import subprocess
333345
import sys
346+
334347
result = subprocess.run(
335348
[sys.executable, "-m", "deadcode", "--help"],
336-
capture_output=True, text=True,
349+
capture_output=True,
350+
text=True,
337351
cwd=str(Path(__file__).parent.parent / "src"),
338352
)
339353
assert result.returncode == 0
@@ -385,8 +399,12 @@ def test_multiline_export_list_used_not_reported(self, tmp_path):
385399

386400
export_names = {f.name for f in result.unused_exports}
387401
# usedInApp appears in both an inline export and the export-list; it's imported so should be absent
388-
assert "usedInApp" not in export_names, "usedInApp is imported — should not be reported"
389-
assert "alsoUnused" in export_names, "alsoUnused is never imported — should be reported"
402+
assert "usedInApp" not in export_names, (
403+
"usedInApp is imported — should not be reported"
404+
)
405+
assert "alsoUnused" in export_names, (
406+
"alsoUnused is never imported — should be reported"
407+
)
390408

391409
def test_multiline_export_list_with_aliases(self, tmp_path):
392410
"""export { Foo as Bar } aliases: the local name Foo should be tracked, not the alias."""
@@ -412,11 +430,7 @@ def test_single_line_export_list_still_works(self, tmp_path):
412430
"""Single-line export { Foo, Bar } should continue to work after the fix."""
413431
mod = tmp_path / "src" / "mod.ts"
414432
mod.parent.mkdir(parents=True, exist_ok=True)
415-
mod.write_text(
416-
"const alpha = 1;\n"
417-
"const beta = 2;\n"
418-
"export { alpha, beta };\n"
419-
)
433+
mod.write_text("const alpha = 1;\nconst beta = 2;\nexport { alpha, beta };\n")
420434

421435
scanner = DeadCodeScanner(tmp_path)
422436
result = scanner.scan()
@@ -454,11 +468,11 @@ def test_include_patterns_filters_files(self, tmp_path):
454468
# Create files in two dirs
455469
mod = tmp_path / "src" / "mod.ts"
456470
mod.parent.mkdir(parents=True, exist_ok=True)
457-
mod.write_text('export function foo() { return 1; }\\n')
471+
mod.write_text("export function foo() { return 1; }\\n")
458472

459473
lib = tmp_path / "lib" / "helper.ts"
460474
lib.parent.mkdir(parents=True, exist_ok=True)
461-
lib.write_text('export function bar() { return 2; }\\n')
475+
lib.write_text("export function bar() { return 2; }\\n")
462476

463477
scanner = DeadCodeScanner(tmp_path, include_patterns=["src/"])
464478
result = scanner.scan()
@@ -470,11 +484,11 @@ def test_include_patterns_allows_multiple(self, tmp_path):
470484
"""include_patterns can specify multiple directories."""
471485
mod = tmp_path / "src" / "mod.ts"
472486
mod.parent.mkdir(parents=True, exist_ok=True)
473-
mod.write_text('export function foo() { return 1; }\\n')
487+
mod.write_text("export function foo() { return 1; }\\n")
474488

475489
lib = tmp_path / "lib" / "helper.ts"
476490
lib.parent.mkdir(parents=True, exist_ok=True)
477-
lib.write_text('export function bar() { return 2; }\\n')
491+
lib.write_text("export function bar() { return 2; }\\n")
478492

479493
scanner = DeadCodeScanner(tmp_path, include_patterns=["src/", "lib/"])
480494
result = scanner.scan()
@@ -484,45 +498,58 @@ def test_include_patterns_none_scans_all(self, tmp_path):
484498
"""When include_patterns is None, all scannable files are included."""
485499
mod = tmp_path / "src" / "mod.ts"
486500
mod.parent.mkdir(parents=True, exist_ok=True)
487-
mod.write_text('export function foo() { return 1; }\\n')
501+
mod.write_text("export function foo() { return 1; }\\n")
488502

489503
lib = tmp_path / "lib" / "helper.ts"
490504
lib.parent.mkdir(parents=True, exist_ok=True)
491-
lib.write_text('export function bar() { return 2; }\\n')
505+
lib.write_text("export function bar() { return 2; }\\n")
492506

493507
scanner = DeadCodeScanner(tmp_path)
494508
result = scanner.scan()
495509
assert result.files_scanned == 2
496510

511+
497512
class TestScanFormat:
498513
"""Tests for the new --format scan option."""
499514

500515
def test_format_compact(self, runner, sample_project):
501-
result = runner.invoke(cli, ["-p", str(sample_project), "scan", "--format=compact"])
516+
result = runner.invoke(
517+
cli, ["-p", str(sample_project), "scan", "--format=compact"]
518+
)
502519
assert result.exit_code == 0
503520

504521
def test_format_github(self, runner, sample_project):
505-
result = runner.invoke(cli, ["-p", str(sample_project), "scan", "--format=github"])
522+
result = runner.invoke(
523+
cli, ["-p", str(sample_project), "scan", "--format=github"]
524+
)
506525
assert result.exit_code == 0
507526

508527
def test_format_compact_with_findings(self, runner, sample_project):
509-
result = runner.invoke(cli, ["-p", str(sample_project), "scan", "--format=compact"])
528+
result = runner.invoke(
529+
cli, ["-p", str(sample_project), "scan", "--format=compact"]
530+
)
510531
assert result.exit_code == 0
511532
assert "unusedHelper" in result.output or "No dead code" in result.output
512533

513534
def test_format_github_with_findings(self, runner, sample_project):
514-
result = runner.invoke(cli, ["-p", str(sample_project), "scan", "--format=github"])
535+
result = runner.invoke(
536+
cli, ["-p", str(sample_project), "scan", "--format=github"]
537+
)
515538
assert result.exit_code == 0
516539
assert "::" in result.output or "No dead code" in result.output
517540

518541
def test_format_json_legacy_alias(self, runner, sample_project):
519-
result = runner.invoke(cli, ["-p", str(sample_project), "scan", "--json-output"])
542+
result = runner.invoke(
543+
cli, ["-p", str(sample_project), "scan", "--json-output"]
544+
)
520545
assert result.exit_code == 0
521546
data = json.loads(result.output, strict=False)
522547
assert "findings" in data
523548

524549
def test_format_json_explicit(self, runner, sample_project):
525-
result = runner.invoke(cli, ["-p", str(sample_project), "scan", "--format=json"])
550+
result = runner.invoke(
551+
cli, ["-p", str(sample_project), "scan", "--format=json"]
552+
)
526553
assert result.exit_code == 0
527554
data = json.loads(result.output, strict=False)
528555
assert "findings" in data

0 commit comments

Comments
 (0)