Files
cleveragents-core/features/steps/cli_renderers_coverage_steps.py
brent.edwards 79b0a2c52e
CI / lint (push) Successful in 26s
CI / typecheck (push) Successful in 43s
CI / quality (push) Successful in 34s
CI / security (push) Successful in 1m20s
CI / build (push) Successful in 17s
CI / unit_tests (push) Successful in 4m12s
CI / benchmark-regression (push) Has been skipped
CI / integration_tests (push) Successful in 4m9s
CI / docker (push) Successful in 1m23s
CI / e2e_tests (push) Successful in 5m48s
CI / coverage (push) Failing after 13m57s
CI / benchmark-publish (push) Successful in 23m24s
chore(cli): complete renderer migration for remaining command modules (#1059)
## Summary

Migrates 8 CLI command modules from module-level `Console()` objects to the shared `_get_console()` from `renderers.py`. This eliminates redundant Console instances and ensures consistent output handling across all CLI commands.

### Modules Migrated

| Module | Change |
|--------|--------|
| `auto_debug.py` | `Console()` → `_get_console()` |
| `context.py` | `Console()` → `_get_console()` |
| `automation_profile.py` | `Console()` → `_get_console()` |
| `tool.py` | `Console()` → `_get_console()` |
| `project.py` | Both stdout + stderr Console → shared instances |
| `config.py` | `Console()` → `_get_console()` |
| `resource.py` | `Console()` → `_get_console()` |
| `skill.py` | `Console()` → `_get_console()` |

### Approach

Each module-level `console = Console()` was replaced with `console = _get_console()`, keeping the module attribute name `console` intact for backward compatibility with existing test patches. The `from rich.console import Console` import was removed from each module.

Modules NOT migrated in this PR (documented for follow-up):
- `plan.py` — uses streaming/Live display, too large for this scope
- `session.py`, `repl.py`, `lsp.py`, `server.py` — specialized usage patterns

### Quality Gates

| Session | Result |
|---------|--------|
| `nox -s lint` | PASS |
| `nox -s typecheck` | PASS (0 errors) |
| Unit tests (targeted) | All affected scenarios pass |

Partial implementation of #813 (step 2 of 4: Console consolidation). Steps 1, 3, 4 remain open on issue #813.

Reviewed-on: #1059
Co-authored-by: Brent E. Edwards <brent.edwards@cleverthis.com>
Co-committed-by: Brent E. Edwards <brent.edwards@cleverthis.com>
2026-03-19 23:30:55 +00:00

124 lines
4.2 KiB
Python

"""Step definitions for cli_renderers_coverage.feature.
Tests the four shared renderer helpers (render_error, render_success,
render_warning, render_empty) across all output formats to ensure full
branch coverage of ``cleveragents.cli.renderers``.
"""
from __future__ import annotations
import contextlib
from io import StringIO
from behave import given, then, when
from behave.runner import Context
from rich.console import Console
from cleveragents.cli.renderers import (
render_empty,
render_error,
render_success,
render_warning,
)
@given("a captured console for renderers")
def step_captured_console(context: Context) -> None:
"""Create a Rich Console that writes to a StringIO buffer."""
context.renderer_buf = StringIO()
context.renderer_stdout = StringIO()
context.renderer_console = Console(
file=context.renderer_buf,
width=200,
no_color=True,
highlight=False,
force_terminal=False,
)
context.renderer_recovery = None
def _get_output(context: Context) -> str:
"""Combine Rich console buffer and any direct stdout writes."""
return context.renderer_buf.getvalue() + context.renderer_stdout.getvalue()
@given('a recovery hint "{recovery}"')
def step_set_recovery(context: Context, recovery: str) -> None:
"""Store a recovery hint for the next renderer call."""
context.renderer_recovery = recovery
# ---------------------------------------------------------------------------
# render_error
# ---------------------------------------------------------------------------
@when('I call render_error with label "{label}" message "{msg}" fmt "{fmt}"')
def step_call_render_error(context: Context, label: str, msg: str, fmt: str) -> None:
"""Invoke render_error with the given parameters."""
recovery = getattr(context, "renderer_recovery", None)
with contextlib.redirect_stdout(context.renderer_stdout):
render_error(
label,
msg,
fmt=fmt,
recovery=recovery,
console=context.renderer_console,
)
# ---------------------------------------------------------------------------
# render_success
# ---------------------------------------------------------------------------
@when('I call render_success with message "{msg}" fmt "{fmt}"')
def step_call_render_success(context: Context, msg: str, fmt: str) -> None:
"""Invoke render_success with the given parameters."""
with contextlib.redirect_stdout(context.renderer_stdout):
render_success(msg, fmt=fmt, console=context.renderer_console)
# ---------------------------------------------------------------------------
# render_warning
# ---------------------------------------------------------------------------
@when('I call render_warning with message "{msg}" fmt "{fmt}"')
def step_call_render_warning(context: Context, msg: str, fmt: str) -> None:
"""Invoke render_warning with the given parameters."""
with contextlib.redirect_stdout(context.renderer_stdout):
render_warning(msg, fmt=fmt, console=context.renderer_console)
# ---------------------------------------------------------------------------
# render_empty
# ---------------------------------------------------------------------------
@when('I call render_empty with entity_type "{etype}" fmt "{fmt}"')
def step_call_render_empty(context: Context, etype: str, fmt: str) -> None:
"""Invoke render_empty with the given parameters."""
recovery = getattr(context, "renderer_recovery", None)
with contextlib.redirect_stdout(context.renderer_stdout):
render_empty(
etype,
fmt=fmt,
recovery=recovery,
console=context.renderer_console,
)
# ---------------------------------------------------------------------------
# THEN assertions
# ---------------------------------------------------------------------------
@then('the renderer output should contain "{expected}"')
def step_renderer_output_contains(context: Context, expected: str) -> None:
"""Assert the captured output contains the expected text."""
output = _get_output(context)
assert expected in output, (
f"Expected {expected!r} in renderer output, got:\n{output}"
)