"""Step definitions for Plan Resume Service coverage boost tests. Targets uncovered validation-error branches in PlanResumeService: - Line 75: __init__ with None lifecycle_service - Line 93: get_resume_metadata with empty plan_id - Line 186: build_resume_summary with empty plan_id - Line 303: record_step_checkpoint with empty plan_id - Line 305: record_step_checkpoint with negative step_index - Line 307: record_step_checkpoint with empty decision_id - Line 309: record_step_checkpoint with empty step_text - Line 354: record_shutdown with empty plan_id - Line 384: set_total_steps with negative total """ from behave import given, then, when from behave.runner import Context from ulid import ULID from cleveragents.application.services.plan_lifecycle_service import ( PlanLifecycleService, ) from cleveragents.application.services.plan_resume_service import ( PlanResumeService, ) from cleveragents.config.settings import Settings from cleveragents.core.exceptions import ValidationError from cleveragents.domain.models.core.plan import ( ProjectLink, ) # ---- Given steps ---- @given("I have a coverage-boost PlanResumeService") def step_create_coverage_boost_service(context: Context) -> None: """Create a lifecycle service and a PlanResumeService for coverage tests.""" settings = Settings() context.cb_lifecycle = PlanLifecycleService(settings=settings) context.cb_resume = PlanResumeService(lifecycle_service=context.cb_lifecycle) context.cb_error = None context.cb_plan_id = None @given("I have a coverage-boost plan in execute phase") def step_create_coverage_boost_plan(context: Context) -> None: """Create a plan in execute/processing state for checkpoint tests.""" action_name = f"local/cb-test-{ULID()!s}"[:30].lower() context.cb_lifecycle.create_action( name=action_name, description="Coverage boost test action", definition_of_done="Step 1\nStep 2", strategy_actor="local/stub-strategy", execution_actor="local/stub-execute", ) plan = context.cb_lifecycle.use_action( action_name=action_name, project_links=[ProjectLink(project_name="local/cb-proj")], ) plan_id = plan.identity.plan_id # Advance to execute/processing context.cb_lifecycle.start_strategize(plan_id) p = context.cb_lifecycle.get_plan(plan_id) p.decision_root_id = str(ULID()) context.cb_lifecycle._commit_plan(p) context.cb_lifecycle.complete_strategize(plan_id) context.cb_lifecycle.execute_plan(plan_id) context.cb_lifecycle.start_execute(plan_id) context.cb_plan_id = plan_id # ---- When steps ---- @when("I try to create a PlanResumeService with None lifecycle_service") def step_create_service_with_none(context: Context) -> None: """Attempt to create PlanResumeService with None.""" context.cb_error = None try: PlanResumeService(lifecycle_service=None) # type: ignore[arg-type] except ValidationError as exc: context.cb_error = exc @when("I try to get resume metadata with empty plan_id") def step_get_metadata_empty_id(context: Context) -> None: """Attempt to get resume metadata with empty string.""" context.cb_error = None try: context.cb_resume.get_resume_metadata("") except ValidationError as exc: context.cb_error = exc @when("I try to build resume summary with empty plan_id") def step_build_summary_empty_id(context: Context) -> None: """Attempt to build resume summary with empty string.""" context.cb_error = None try: context.cb_resume.build_resume_summary("") except ValidationError as exc: context.cb_error = exc @when("I try to record a step checkpoint with empty plan_id") def step_checkpoint_empty_plan_id(context: Context) -> None: """Attempt to record checkpoint with empty plan_id.""" context.cb_error = None try: context.cb_resume.record_step_checkpoint( plan_id="", step_index=0, decision_id="DEC001", step_text="Do something", ) except ValidationError as exc: context.cb_error = exc @when("I try to record a step checkpoint with step_index {index:d}") def step_checkpoint_negative_index(context: Context, index: int) -> None: """Attempt to record checkpoint with given step_index.""" context.cb_error = None try: context.cb_resume.record_step_checkpoint( plan_id=context.cb_plan_id, step_index=index, decision_id="DEC001", step_text="Do something", ) except ValidationError as exc: context.cb_error = exc @when("I try to record a step checkpoint with empty decision_id") def step_checkpoint_empty_decision(context: Context) -> None: """Attempt to record checkpoint with empty decision_id.""" context.cb_error = None try: context.cb_resume.record_step_checkpoint( plan_id=context.cb_plan_id, step_index=0, decision_id="", step_text="Do something", ) except ValidationError as exc: context.cb_error = exc @when("I try to record a step checkpoint with empty step_text") def step_checkpoint_empty_step_text(context: Context) -> None: """Attempt to record checkpoint with empty step_text.""" context.cb_error = None try: context.cb_resume.record_step_checkpoint( plan_id=context.cb_plan_id, step_index=0, decision_id="DEC001", step_text="", ) except ValidationError as exc: context.cb_error = exc @when("I try to record shutdown with empty plan_id") def step_shutdown_empty_plan_id(context: Context) -> None: """Attempt to record shutdown with empty plan_id.""" context.cb_error = None try: context.cb_resume.record_shutdown("") except ValidationError as exc: context.cb_error = exc @when("I try to set total steps to {total:d}") def step_set_total_steps_negative(context: Context, total: int) -> None: """Attempt to set total steps to given value.""" context.cb_error = None try: context.cb_resume.set_total_steps(context.cb_plan_id, total) except ValidationError as exc: context.cb_error = exc # ---- Then steps ---- @then('a coverage-boost ValidationError should be raised with message "{expected_msg}"') def step_assert_validation_error_with_message( context: Context, expected_msg: str ) -> None: """Assert a ValidationError was raised and contains the expected message.""" assert context.cb_error is not None, ( "Expected a ValidationError but none was raised" ) assert isinstance(context.cb_error, ValidationError), ( f"Expected ValidationError, got {type(context.cb_error).__name__}" ) assert expected_msg in str(context.cb_error), ( f"Expected message containing '{expected_msg}', got: {context.cb_error}" )