Coverage for tests / config / test_init_command.py: 100%
67 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"""Tests for lintro init command."""
3from pathlib import Path
5import pytest
6from assertpy import assert_that
7from click.testing import CliRunner
9from lintro.cli_utils.commands.init import (
10 DEFAULT_CONFIG_TEMPLATE,
11 MINIMAL_CONFIG_TEMPLATE,
12 init_command,
13)
16@pytest.fixture
17def runner() -> CliRunner:
18 """Create a Click test runner.
20 Returns:
21 CliRunner: A Click test runner instance.
22 """
23 return CliRunner()
26def test_creates_minimal_template(
27 runner: CliRunner,
28 tmp_path: Path,
29) -> None:
30 """Should use minimal template with --minimal flag.
32 Args:
33 runner: Click test runner instance.
34 tmp_path: Temporary directory path for test files.
35 """
36 with runner.isolated_filesystem(temp_dir=tmp_path):
37 runner.invoke(init_command, ["--minimal"])
39 config_file = Path(".lintro-config.yaml")
40 content = config_file.read_text()
42 # Minimal template should be shorter
43 assert_that(content).contains("# Lintro Configuration (Minimal)")
44 # But still have core sections
45 assert_that(content).contains("enforce:")
46 assert_that(content).contains("tools:")
47 # Minimal doesn't have all tools
48 assert_that(content).does_not_contain("bandit:")
51def test_refuses_to_overwrite_existing(
52 runner: CliRunner,
53 tmp_path: Path,
54) -> None:
55 """Should refuse to overwrite existing file without --force.
57 Args:
58 runner: Click test runner instance.
59 tmp_path: Temporary directory path for test files.
60 """
61 with runner.isolated_filesystem(temp_dir=tmp_path):
62 # Create existing file
63 Path(".lintro-config.yaml").write_text("existing content")
65 result = runner.invoke(init_command)
67 assert_that(result.exit_code).is_equal_to(1)
68 assert_that(result.output).contains("already exists")
69 assert_that(result.output).contains("Use --force to overwrite")
71 # Original content should be preserved
72 content = Path(".lintro-config.yaml").read_text()
73 assert_that(content).is_equal_to("existing content")
76def test_force_overwrites_existing(
77 runner: CliRunner,
78 tmp_path: Path,
79) -> None:
80 """Should overwrite existing file with --force.
82 Args:
83 runner: Click test runner instance.
84 tmp_path: Temporary directory path for test files.
85 """
86 with runner.isolated_filesystem(temp_dir=tmp_path):
87 # Create existing file
88 Path(".lintro-config.yaml").write_text("existing content")
90 result = runner.invoke(init_command, ["--force"])
92 assert_that(result.exit_code).is_equal_to(0)
93 assert_that(result.output).contains("Created .lintro-config.yaml")
95 # Should have new template content
96 content = Path(".lintro-config.yaml").read_text()
97 assert_that(content).contains("enforce:")
100def test_custom_output_path(
101 runner: CliRunner,
102 tmp_path: Path,
103) -> None:
104 """Should create file at custom path with --output.
106 Args:
107 runner: Click test runner instance.
108 tmp_path: Temporary directory path for test files.
109 """
110 with runner.isolated_filesystem(temp_dir=tmp_path):
111 result = runner.invoke(
112 init_command,
113 ["--output", "custom-config.yaml"],
114 )
116 assert_that(result.exit_code).is_equal_to(0)
117 assert_that(result.output).contains("Created custom-config.yaml")
119 config_file = Path("custom-config.yaml")
120 assert_that(config_file.exists()).is_true()
123def test_shows_next_steps(
124 runner: CliRunner,
125 tmp_path: Path,
126) -> None:
127 """Should show helpful next steps.
129 Args:
130 runner: Click test runner instance.
131 tmp_path: Temporary directory path for test files.
132 """
133 with runner.isolated_filesystem(temp_dir=tmp_path):
134 result = runner.invoke(init_command)
136 assert_that(result.output).contains("Next steps:")
137 assert_that(result.output).contains("lintro config")
138 assert_that(result.output).contains("lintro check")
141def test_default_template_is_valid_yaml() -> None:
142 """Default template should be valid YAML."""
143 import yaml
145 parsed = yaml.safe_load(DEFAULT_CONFIG_TEMPLATE)
147 assert_that(parsed).contains("enforce")
148 assert_that(parsed).contains("execution")
149 assert_that(parsed).contains("tools")
152def test_minimal_template_is_valid_yaml() -> None:
153 """Minimal template should be valid YAML."""
154 import yaml
156 parsed = yaml.safe_load(MINIMAL_CONFIG_TEMPLATE)
158 assert_that(parsed).contains("enforce")
159 assert_that(parsed).contains("tools")
162def test_default_template_has_sensible_defaults() -> None:
163 """Default template should have sensible default values."""
164 import yaml
166 parsed = yaml.safe_load(DEFAULT_CONFIG_TEMPLATE)
168 assert_that(parsed["enforce"]["line_length"]).is_equal_to(88)
169 assert_that(parsed["enforce"]["target_python"]).is_equal_to("py313")
170 assert_that(parsed["execution"]["tool_order"]).is_equal_to("priority")
171 assert_that(parsed["tools"]["ruff"]["enabled"]).is_true()
172 assert_that(parsed["defaults"]["mypy"]["strict"]).is_true()
173 assert_that(parsed["defaults"]["mypy"]["ignore_missing_imports"]).is_true()