"""Step definitions for ResourceHandler protocol coverage. Targets uncovered lines in src/cleveragents/resource/handlers/protocol.py: - Line 76: Content.text raises ValueError for binary (encoding=None) - Line 236: ResourceHandler.resolve default stub - Line 254: ResourceHandler.read default stub - Line 271: ResourceHandler.write default stub - Line 288: ResourceHandler.delete default stub - Line 299: ResourceHandler.list_children default stub - Line 311: ResourceHandler.diff default stub - Line 315: ResourceHandler.discover_children default stub - Line 327: ResourceHandler.create_sandbox default stub - Line 338: ResourceHandler.create_checkpoint default stub - Line 349: ResourceHandler.rollback_to default stub - Line 360: ResourceHandler.project_access default stub All steps use the ``phcov`` prefix to avoid collisions with other step files. """ from __future__ import annotations from unittest.mock import MagicMock from behave import given, then, when from behave.runner import Context from cleveragents.domain.models.core.resource import PhysVirt, Resource from cleveragents.resource.handlers.protocol import Content, ResourceHandler # --------------------------------------------------------------------------- # Helpers # --------------------------------------------------------------------------- # A valid ULID for constructing Resource instances. _DUMMY_ULID = "01ARZ3NDEKTSV4RRFFQ69G5FAV" class _BareResourceHandler(ResourceHandler): """Minimal subclass that inherits all Protocol default stubs. Does NOT override any methods, so calling them executes the ``...`` body in the Protocol and returns ``None``. """ pass def _make_dummy_resource() -> Resource: """Create a minimal valid Resource for test use.""" return Resource( resource_id=_DUMMY_ULID, resource_type_name="test-type", classification=PhysVirt.PHYSICAL, location="/tmp/test", ) def _make_mock_sandbox_manager() -> MagicMock: """Create a MagicMock standing in for SandboxManager.""" return MagicMock(name="SandboxManager") # --------------------------------------------------------------------------- # Given steps # --------------------------------------------------------------------------- @given("phcov a Content instance with binary data and encoding None") def step_given_phcov_binary_content(context: Context) -> None: context.phcov_content = Content(data=b"\x89PNG\r\n", encoding=None) context.phcov_error = None @given("phcov a bare ResourceHandler protocol subclass instance") def step_given_phcov_bare_handler(context: Context) -> None: context.phcov_handler = _BareResourceHandler() context.phcov_result = None context.phcov_error = None @given("phcov a dummy Resource and SandboxManager") def step_given_phcov_dummy_resource_and_manager(context: Context) -> None: context.phcov_resource = _make_dummy_resource() context.phcov_sandbox_manager = _make_mock_sandbox_manager() # --------------------------------------------------------------------------- # When steps # --------------------------------------------------------------------------- @when("phcov the text property is accessed") def step_when_phcov_text_property(context: Context) -> None: try: _ = context.phcov_content.text except ValueError as exc: context.phcov_error = exc @when("phcov the resolve method is called") def step_when_phcov_resolve(context: Context) -> None: try: context.phcov_result = context.phcov_handler.resolve( resource=context.phcov_resource, plan_id="plan-001", slot_name="repo", sandbox_manager=context.phcov_sandbox_manager, access="read_only", ) except Exception as exc: context.phcov_error = exc @when("phcov the read method is called") def step_when_phcov_read(context: Context) -> None: try: context.phcov_result = context.phcov_handler.read( resource=context.phcov_resource, path="", ) except Exception as exc: context.phcov_error = exc @when("phcov the write method is called") def step_when_phcov_write(context: Context) -> None: try: context.phcov_result = context.phcov_handler.write( resource=context.phcov_resource, path="test.txt", data=b"hello", ) except Exception as exc: context.phcov_error = exc @when("phcov the delete method is called") def step_when_phcov_delete(context: Context) -> None: try: context.phcov_result = context.phcov_handler.delete( resource=context.phcov_resource, path="", ) except Exception as exc: context.phcov_error = exc @when("phcov the list_children method is called") def step_when_phcov_list_children(context: Context) -> None: try: context.phcov_result = context.phcov_handler.list_children( resource=context.phcov_resource, ) except Exception as exc: context.phcov_error = exc @when("phcov the diff method is called") def step_when_phcov_diff(context: Context) -> None: try: context.phcov_result = context.phcov_handler.diff( resource=context.phcov_resource, other_location="/tmp/other", ) except Exception as exc: context.phcov_error = exc @when("phcov the discover_children method is called") def step_when_phcov_discover_children(context: Context) -> None: try: context.phcov_result = context.phcov_handler.discover_children( resource=context.phcov_resource, ) except Exception as exc: context.phcov_error = exc @when("phcov the create_sandbox method is called") def step_when_phcov_create_sandbox(context: Context) -> None: try: context.phcov_result = context.phcov_handler.create_sandbox( resource=context.phcov_resource, plan_id="plan-001", sandbox_manager=context.phcov_sandbox_manager, ) except Exception as exc: context.phcov_error = exc @when("phcov the create_checkpoint method is called") def step_when_phcov_create_checkpoint(context: Context) -> None: try: context.phcov_result = context.phcov_handler.create_checkpoint( resource=context.phcov_resource, plan_id="plan-001", sandbox_manager=context.phcov_sandbox_manager, phase="execution", ) except Exception as exc: context.phcov_error = exc @when("phcov the rollback_to method is called") def step_when_phcov_rollback_to(context: Context) -> None: try: context.phcov_result = context.phcov_handler.rollback_to( resource=context.phcov_resource, plan_id="plan-001", checkpoint_id="chk-001", sandbox_manager=context.phcov_sandbox_manager, ) except Exception as exc: context.phcov_error = exc @when("phcov the project_access method is called") def step_when_phcov_project_access(context: Context) -> None: try: context.phcov_result = context.phcov_handler.project_access( resource=context.phcov_resource, principal="user-alice", action="read", project_id="proj-001", ) except Exception as exc: context.phcov_error = exc # --------------------------------------------------------------------------- # Then steps # --------------------------------------------------------------------------- @then('phcov a ValueError should be stored with message "{expected_msg}"') def step_then_phcov_valueerror(context: Context, expected_msg: str) -> None: assert context.phcov_error is not None, ( "Expected a ValueError but no exception was raised" ) assert isinstance(context.phcov_error, ValueError), ( f"Expected ValueError, got {type(context.phcov_error).__name__}" ) actual_msg = str(context.phcov_error) assert expected_msg in actual_msg, ( f"Expected message to contain '{expected_msg}', got: '{actual_msg}'" ) @then("phcov the result should be None") def step_then_phcov_result_none(context: Context) -> None: assert context.phcov_error is None, f"Unexpected exception: {context.phcov_error}" assert context.phcov_result is None, ( f"Expected None but got: {context.phcov_result!r}" )