"""Step definitions for validation_pipeline_stream_coverage.feature. Exercises the _ThreadLocalStream helper methods that lack coverage: - encoding property (line 58) - writable() method (line 61) - readable() method (line 64) - flush() with active buffer (line 75) - isatty() method (line 79) All tests use a simple mock original stream — no real I/O needed. """ from __future__ import annotations from typing import Any from behave import given, then, when from behave.runner import Context from cleveragents.application.services.validation_pipeline import ( _ThreadLocalStream, ) # --------------------------------------------------------------------------- # Mock original stream # --------------------------------------------------------------------------- class _MockOriginalStream: """Configurable mock that mimics a real stdout/stderr.""" def __init__(self) -> None: self.encoding: str = "utf-8" self._has_encoding: bool = True self._isatty_return: bool = False self._written: list[str] = [] self._flushed: bool = False def write(self, s: str) -> int: self._written.append(s) return len(s) def flush(self) -> None: self._flushed = True def isatty(self) -> bool: return self._isatty_return class _NoEncodingStream: """Mock stream without an encoding attribute.""" def write(self, s: str) -> int: return len(s) def flush(self) -> None: pass def isatty(self) -> bool: return False # --------------------------------------------------------------------------- # Background # --------------------------------------------------------------------------- @given("a thread-local stream wrapping a mock original stream") def step_given_tl_stream(context: Context) -> None: context.tls_original = _MockOriginalStream() context.tls_stream = _ThreadLocalStream(context.tls_original) context.tls_result: Any = None context.tls_captured: str = "" context.tls_error: Exception | None = None # --------------------------------------------------------------------------- # Given steps # --------------------------------------------------------------------------- @given('the original stream has encoding "{enc}"') def step_given_encoding(context: Context, enc: str) -> None: context.tls_original.encoding = enc @given("the original stream has no encoding attribute") def step_given_no_encoding(context: Context) -> None: context.tls_stream = _ThreadLocalStream(_NoEncodingStream()) @given("the original stream isatty returns True") def step_given_isatty_true(context: Context) -> None: context.tls_original._isatty_return = True @given("the original stream isatty returns False") def step_given_isatty_false(context: Context) -> None: context.tls_original._isatty_return = False @given("capture is started on the thread-local stream") def step_given_capture_started(context: Context) -> None: context.tls_stream.start_capture() # --------------------------------------------------------------------------- # When steps # --------------------------------------------------------------------------- @when("I read the thread-local stream encoding") def step_when_read_encoding(context: Context) -> None: context.tls_result = context.tls_stream.encoding @when("I check if the thread-local stream is writable") def step_when_check_writable(context: Context) -> None: context.tls_result = context.tls_stream.writable() @when("I check if the thread-local stream is readable") def step_when_check_readable(context: Context) -> None: context.tls_result = context.tls_stream.readable() @when("I flush the thread-local stream") def step_when_flush(context: Context) -> None: try: context.tls_stream.flush() context.tls_error = None except Exception as exc: context.tls_error = exc @when("I check if the thread-local stream isatty") def step_when_check_isatty(context: Context) -> None: context.tls_result = context.tls_stream.isatty() @when('I write "{text}" to the thread-local stream') def step_when_write(context: Context, text: str) -> None: context.tls_stream.write(text) @when("capture is stopped on the thread-local stream") def step_when_stop_capture(context: Context) -> None: context.tls_captured = context.tls_stream.stop_capture() # --------------------------------------------------------------------------- # Then steps # --------------------------------------------------------------------------- @then('the encoding should be "{enc}"') def step_then_encoding(context: Context, enc: str) -> None: assert context.tls_result == enc, ( f"Expected encoding '{enc}', got '{context.tls_result}'" ) @then("writable should return True") def step_then_writable_true(context: Context) -> None: assert context.tls_result is True, ( f"Expected writable()=True, got {context.tls_result}" ) @then("readable should return False") def step_then_readable_false(context: Context) -> None: assert context.tls_result is False, ( f"Expected readable()=False, got {context.tls_result}" ) @then("the flush should succeed without error") def step_then_flush_ok(context: Context) -> None: assert context.tls_error is None, f"Expected no error, got {context.tls_error}" @then("the original stream flush should be called") def step_then_original_flushed(context: Context) -> None: assert context.tls_original._flushed, ( "Expected original stream flush() to be called" ) @then("isatty should return True") def step_then_isatty_true(context: Context) -> None: assert context.tls_result is True, ( f"Expected isatty()=True, got {context.tls_result}" ) @then("isatty should return False") def step_then_isatty_false(context: Context) -> None: assert context.tls_result is False, ( f"Expected isatty()=False, got {context.tls_result}" ) @then('the original stream should have received "{text}"') def step_then_original_received(context: Context, text: str) -> None: assert text in context.tls_original._written, ( f"Expected '{text}' in original writes, got {context.tls_original._written}" ) @then('the captured text should be "{text}"') def step_then_captured_text(context: Context, text: str) -> None: assert context.tls_captured == text, ( f"Expected captured text '{text}', got '{context.tls_captured}'" ) @then("the captured text should be empty") def step_then_captured_text_empty(context: Context) -> None: assert context.tls_captured == "", ( f"Expected empty captured text, got '{context.tls_captured}'" )