Skip to content

Commit 5a1729d

Browse files
Sergio SisternesCopilot
andcommitted
test: add exit_code assertions per Copilot review (#602)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent b753d60 commit 5a1729d

File tree

6 files changed

+35
-18
lines changed

6 files changed

+35
-18
lines changed

CHANGELOG.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2929
- Preserve custom git ports across protocols: non-default ports on `ssh://` and `https://` dependency URLs (e.g. Bitbucket Datacenter on SSH port 7999, self-hosted GitLab on HTTPS port 8443) are now captured as a first-class `port` field on `DependencyReference` and threaded through all clone URL builders. When the SSH clone fails, the HTTPS fallback reuses the same port instead of silently dropping it (#661, #731)
3030
- Detect port-like first path segment in SCP shorthand (`git@host:7999/path`) and raise an actionable error suggesting the `ssh://` URL form, instead of silently misparsing the port as part of the repository path (#784)
3131
- Fix `apm init` showing overwrite confirmation prompt three times on Windows CP950 terminals (#602)
32-
- Propagate headers and environment variables through OpenCode MCP adapter with defensive copies to prevent mutation (#622)
3332

3433
## [0.8.12] - 2026-04-19
3534

src/apm_cli/commands/_helpers.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -100,16 +100,6 @@ def _lazy_prompt():
100100
return None
101101

102102

103-
def _lazy_confirm():
104-
"""Lazy import for Rich Confirm to improve startup performance."""
105-
try:
106-
from rich.prompt import Confirm
107-
108-
return Confirm
109-
except ImportError:
110-
return None
111-
112-
113103
# ------------------------------------------------------------------
114104
# Shared orphan-detection helpers
115105
# ------------------------------------------------------------------

src/apm_cli/commands/deps/cli.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -450,11 +450,8 @@ def clean(dry_run: bool, yes: bool):
450450

451451
# Confirmation prompt (skip if --yes provided)
452452
if not yes:
453-
try:
454-
from rich.prompt import Confirm
455-
confirm = Confirm.ask("Continue?")
456-
except ImportError:
457-
confirm = click.confirm("Continue?")
453+
# Plain click.confirm: Rich Confirm.ask triple-prompts on CP950 terminals; see #602
454+
confirm = click.confirm("Continue?")
458455

459456
if not confirm:
460457
logger.progress("Operation cancelled")

src/apm_cli/commands/init.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ def init(ctx, project_name, yes, plugin, verbose):
8383
logger.warning("apm.yml already exists")
8484

8585
if not yes:
86+
# Plain click.confirm: Rich Confirm.ask triple-prompts on CP950 terminals; see #602
8687
confirm = click.confirm("Continue and overwrite?")
8788

8889
if not confirm:
@@ -174,7 +175,7 @@ def _interactive_project_setup(default_name, logger):
174175
# Lazy import rich pieces
175176
from rich.console import Console # type: ignore
176177
from rich.panel import Panel # type: ignore
177-
from rich.prompt import Confirm, Prompt # type: ignore
178+
from rich.prompt import Prompt # type: ignore
178179

179180
console = _get_console() or Console()
180181
console.print("\n[info]Setting up your APM project...[/info]")
@@ -201,7 +202,8 @@ def _interactive_project_setup(default_name, logger):
201202
Panel(summary_content, title="About to create", border_style="cyan")
202203
)
203204

204-
if not Confirm.ask("\nIs this OK?", default=True):
205+
# Plain click.confirm: Rich Confirm.ask triple-prompts on CP950 terminals; see #602
206+
if not click.confirm("\nIs this OK?", default=True):
205207
console.print("[info]Aborted.[/info]")
206208
sys.exit(0)
207209

tests/unit/test_deps_clean_command.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import os
55
import tempfile
66
from pathlib import Path
7+
from unittest.mock import patch
78

89
import pytest
910
from click.testing import CliRunner
@@ -102,3 +103,14 @@ def test_dry_run_no_apm_modules_reports_already_clean(self):
102103

103104
assert result.exit_code == 0
104105
assert "already clean" in result.output
106+
107+
def test_clean_confirm_uses_click(self):
108+
"""Test that clean confirmation uses click.confirm, not Rich (#602)."""
109+
with self._chdir_tmp() as tmp:
110+
Path("apm.yml").write_text("name: test-project\nversion: 1.0.0\n")
111+
apm_modules = self._create_fake_apm_modules(tmp)
112+
113+
with patch("apm_cli.commands.deps.cli.click.confirm", return_value=False) as mock_confirm:
114+
result = self.runner.invoke(cli, ["deps", "clean"])
115+
mock_confirm.assert_called_once_with("Continue?")
116+
assert "cancelled" in result.output.lower()

tests/unit/test_init_command.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,16 +255,33 @@ def test_init_existing_project_confirm_uses_click(self):
255255

256256
with patch("apm_cli.commands.init.click.confirm", return_value=True) as mock_confirm:
257257
result = self.runner.invoke(cli, ["init", "--yes"])
258+
assert result.exit_code == 0
258259
# --yes skips the prompt entirely, so confirm should NOT be called
259260
mock_confirm.assert_not_called()
260261

261262
with patch("apm_cli.commands.init.click.confirm", return_value=False) as mock_confirm:
262263
result = self.runner.invoke(cli, ["init"])
264+
assert result.exit_code == 0
263265
mock_confirm.assert_called_once_with("Continue and overwrite?")
264266
assert "Initialization cancelled" in result.output
265267
finally:
266268
os.chdir(self.original_dir) # restore CWD before TemporaryDirectory cleanup
267269

270+
def test_init_interactive_setup_confirm_uses_click(self):
271+
"""Test that interactive setup 'Is this OK?' uses click.confirm, not Rich (#602)."""
272+
with tempfile.TemporaryDirectory() as tmp_dir:
273+
os.chdir(tmp_dir)
274+
try:
275+
with patch("apm_cli.commands.init.click.confirm", return_value=False) as mock_confirm:
276+
# Provide input for the Rich Prompt.ask calls (name, version, desc, author)
277+
result = self.runner.invoke(
278+
cli, ["init"], input="test-project\n1.0.0\nA description\nAuthor\n"
279+
)
280+
assert result.exit_code == 0
281+
mock_confirm.assert_called_once_with("\nIs this OK?", default=True)
282+
finally:
283+
os.chdir(self.original_dir)
284+
268285
def test_init_validates_project_structure(self):
269286
"""Test that init creates minimal project structure."""
270287
with tempfile.TemporaryDirectory() as tmp_dir:

0 commit comments

Comments
 (0)