Skip to content

Commit 8b54e64

Browse files
committed
test: fix contribute command tests for validation feature
Updated tests to mock SpeckitValidator and support new validation flow: - Added create_passing_validation_result() helper - Mocked SpeckitValidator in all affected tests - Added tests for --check-only flag (passing and failing) - All 14 tests now passing Tests fixed: - test_contribute_interactive_full_flow - test_contribute_with_detected_commands - test_contribute_custom_commands Tests added: - test_contribute_check_only_passing - test_contribute_check_only_failing
1 parent 11bae46 commit 8b54e64

File tree

1 file changed

+93
-0
lines changed

1 file changed

+93
-0
lines changed

tests/unit/test_cli_contribute.py

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,43 @@
77
from typer.testing import CliRunner
88

99
from metaspec.cli.main import app
10+
from metaspec.validation import ValidationCheck, ValidationResult
1011

1112
runner = CliRunner()
1213

1314

15+
def create_passing_validation_result() -> ValidationResult:
16+
"""Create a passing validation result for tests."""
17+
checks = [
18+
ValidationCheck(
19+
name="pyproject.toml",
20+
passed=True,
21+
message="Valid (name: test, version: 1.0.0)",
22+
),
23+
ValidationCheck(
24+
name="README.md",
25+
passed=True,
26+
message="Found (100 characters)",
27+
),
28+
ValidationCheck(
29+
name="LICENSE",
30+
passed=True,
31+
message="Found",
32+
),
33+
ValidationCheck(
34+
name="CLI Entry Point",
35+
passed=True,
36+
message="Found: test-command",
37+
),
38+
ValidationCheck(
39+
name="GitHub Repository",
40+
passed=True,
41+
message="Found: https://github.com/test/repo",
42+
),
43+
]
44+
return ValidationResult(checks=checks, passed=True, warnings=[])
45+
46+
1447
class TestContributeCommand:
1548
"""Tests for contribute command."""
1649

@@ -54,6 +87,7 @@ def test_contribute_command_description(self) -> None:
5487
assert result.exit_code == 0
5588
assert "community" in result.stdout.lower() or "registry" in result.stdout.lower()
5689

90+
@patch("metaspec.cli.contribute.SpeckitValidator")
5791
@patch("metaspec.cli.contribute.shutil.which")
5892
@patch("metaspec.cli.contribute.CommunityRegistry")
5993
@patch("metaspec.cli.contribute.Prompt.ask")
@@ -66,8 +100,14 @@ def test_contribute_interactive_full_flow(
66100
mock_prompt: MagicMock,
67101
mock_registry_class: MagicMock,
68102
mock_which: MagicMock,
103+
mock_validator_class: MagicMock,
69104
) -> None:
70105
"""Test complete interactive contribution flow."""
106+
# Mock validation passing
107+
mock_validator = MagicMock()
108+
mock_validator.validate.return_value = create_passing_validation_result()
109+
mock_validator_class.return_value = mock_validator
110+
71111
# Mock command exists
72112
mock_which.return_value = "/usr/local/bin/my-spec-kit"
73113

@@ -102,6 +142,7 @@ def test_contribute_interactive_full_flow(
102142
assert result.exit_code == 0
103143
assert "Generated metadata" in result.stdout or mock_file.called
104144

145+
@patch("metaspec.cli.contribute.SpeckitValidator")
105146
@patch("metaspec.cli.contribute.shutil.which")
106147
@patch("metaspec.cli.contribute.CommunityRegistry")
107148
@patch("metaspec.cli.contribute.Prompt.ask")
@@ -114,8 +155,14 @@ def test_contribute_with_detected_commands(
114155
mock_prompt: MagicMock,
115156
mock_registry_class: MagicMock,
116157
mock_which: MagicMock,
158+
mock_validator_class: MagicMock,
117159
) -> None:
118160
"""Test contribution uses detected commands."""
161+
# Mock validation passing
162+
mock_validator = MagicMock()
163+
mock_validator.validate.return_value = create_passing_validation_result()
164+
mock_validator_class.return_value = mock_validator
165+
119166
# Mock command exists
120167
mock_which.return_value = "/usr/local/bin/test-kit"
121168

@@ -172,6 +219,7 @@ def test_contribute_command_not_in_path_continue(
172219
# Should exit
173220
assert result.exit_code == 1
174221

222+
@patch("metaspec.cli.contribute.SpeckitValidator")
175223
@patch("metaspec.cli.contribute.shutil.which")
176224
@patch("metaspec.cli.contribute.CommunityRegistry")
177225
@patch("metaspec.cli.contribute.Prompt.ask")
@@ -184,8 +232,14 @@ def test_contribute_custom_commands(
184232
mock_prompt: MagicMock,
185233
mock_registry_class: MagicMock,
186234
mock_which: MagicMock,
235+
mock_validator_class: MagicMock,
187236
) -> None:
188237
"""Test contribution with custom commands instead of detected ones."""
238+
# Mock validation passing
239+
mock_validator = MagicMock()
240+
mock_validator.validate.return_value = create_passing_validation_result()
241+
mock_validator_class.return_value = mock_validator
242+
189243
# Mock command exists
190244
mock_which.return_value = "/usr/bin/custom-kit"
191245

@@ -220,6 +274,45 @@ def test_contribute_custom_commands(
220274
# Should complete successfully
221275
assert result.exit_code == 0
222276

277+
@patch("metaspec.cli.contribute.SpeckitValidator")
278+
def test_contribute_check_only_passing(self, mock_validator_class: MagicMock) -> None:
279+
"""Test --check-only flag with passing validation."""
280+
# Mock validation passing
281+
mock_validator = MagicMock()
282+
mock_validator.validate.return_value = create_passing_validation_result()
283+
mock_validator_class.return_value = mock_validator
284+
285+
result = runner.invoke(app, ["contribute", "--check-only"])
286+
287+
# Should exit with 0 when validation passes
288+
assert result.exit_code == 0
289+
# Validation was called
290+
assert mock_validator.validate.called
291+
assert mock_validator.display_results.called
292+
293+
@patch("metaspec.cli.contribute.SpeckitValidator")
294+
def test_contribute_check_only_failing(self, mock_validator_class: MagicMock) -> None:
295+
"""Test --check-only flag with failing validation."""
296+
# Mock validation failing
297+
failing_checks = [
298+
ValidationCheck(
299+
name="pyproject.toml",
300+
passed=False,
301+
message="pyproject.toml not found",
302+
fix_suggestion="Create pyproject.toml",
303+
),
304+
]
305+
mock_validator = MagicMock()
306+
mock_validator.validate.return_value = ValidationResult(
307+
checks=failing_checks, passed=False, warnings=["Missing files"]
308+
)
309+
mock_validator_class.return_value = mock_validator
310+
311+
result = runner.invoke(app, ["contribute", "--check-only"])
312+
313+
# Should exit with 1 when validation fails
314+
assert result.exit_code == 1
315+
223316
def test_contribute_non_interactive_fails(self) -> None:
224317
"""Test that non-interactive mode shows error."""
225318
result = runner.invoke(

0 commit comments

Comments
 (0)