Files
cleveragents-core/features/repositories_coverage.feature
freemo c9abb45adf
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 15s
CI / build (pull_request) Successful in 16s
CI / quality (pull_request) Successful in 18s
CI / security (pull_request) Successful in 31s
CI / typecheck (pull_request) Successful in 55s
CI / integration_tests (pull_request) Successful in 3m28s
CI / unit_tests (pull_request) Successful in 10m38s
CI / docker (pull_request) Successful in 16s
CI / benchmark-regression (pull_request) Successful in 20m39s
CI / coverage (pull_request) Successful in 41m22s
CI / lint (push) Successful in 13s
CI / quality (push) Successful in 17s
CI / build (push) Successful in 22s
CI / typecheck (push) Successful in 29s
CI / security (push) Successful in 29s
CI / benchmark-regression (push) Has been skipped
CI / integration_tests (push) Successful in 2m40s
CI / unit_tests (push) Successful in 11m4s
CI / docker (push) Successful in 1m5s
CI / benchmark-publish (push) Successful in 12m10s
CI / coverage (push) Successful in 1h7m46s
test(coverage): add Behave BDD scenarios for 9 under-covered modules
Added 246 new BDD scenarios across 9 feature files to improve unit test
coverage for modules that were either entirely untested or had significant
coverage gaps:

- lock_service_coverage.feature (27 scenarios): validation branches,
  TTL boundaries, re-entrant acquisition, rollback on exceptions
- plan_apply_service_coverage.feature (54 scenarios): operation labels,
  diff rendering (plain/rich/json), artifact building, validation gate,
  changeset resolution and cleanup
- plan_executor_coverage.feature (51 scenarios): step parsing, execute
  actor integration, strategize/execute guards, stub retry/recovery,
  decision tree construction
- skill_cli_coverage_r3.feature (22 scenarios): tools refresh, list/show
  JSON fallback, capability summary errors, remove confirmation
- changeset_repository_coverage.feature (39 scenarios): entry/tool repos
  validation, database error wrapping, domain conversion, SQLite store
  CRUD operations
- repositories_coverage.feature (20 scenarios): get_by_name/namespace
  errors, list_available filters, delete with ActionInUseError, plan
  update with invariants/processing_state/error_details
- sandbox_copy_on_write_coverage.feature (12 scenarios): create OSError
  wrapping, get_path state transitions, commit edge cases, rollback
  errors, cleanup with missing paths
- bridge_coverage.feature (8 scenarios): __del__ suppression, async task
  cancellation, execute_graph message type handling, stream config,
  state checkpointer
- plan_cli_coverage.feature (13 scenarios): legacy apply/list/cd paths,
  use-action with estimation/invariant actors, lifecycle-apply guards,
  status errors, error recovery display

All 246 scenarios (1105 steps) pass. Step definitions use unique prefixes
to prevent ambiguous step conflicts with existing tests.

ISSUES CLOSED: #467
2026-02-27 13:47:42 -05:00

233 lines
13 KiB
Gherkin
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
@unit @repository @coverage
Feature: Repository coverage for ActionRepository and LifecyclePlanRepository
Exercise uncovered lines and branches in repositories.py to boost
line-rate and branch-rate for ActionRepository and LifecyclePlanRepository.
Background:
Given a repos-cov in-memory database with lifecycle schema
And a repos-cov action repository
And a repos-cov lifecycle plan repository
# ---------------------------------------------------------------------------
# ActionRepository.get_by_name DatabaseError on OperationalError
# ---------------------------------------------------------------------------
@action @error_handling
Scenario: ActionRepository.get_by_name raises DatabaseError on OperationalError
Given a repos-cov action repository with a session that raises OperationalError on query
When repos-cov get_by_name is called with "local/broken-action"
Then repos-cov a DatabaseError should be raised containing "Failed to get action by name"
# ---------------------------------------------------------------------------
# ActionRepository.get_by_name success path returns domain object
# ---------------------------------------------------------------------------
@action
Scenario: ActionRepository.get_by_name returns domain object for existing action
Given repos-cov an available action "local/findable" exists
When repos-cov get_by_name is called with "local/findable"
Then repos-cov the returned action should have name "local/findable"
# ---------------------------------------------------------------------------
# ActionRepository.get_by_namespace with state filter returning results
# ---------------------------------------------------------------------------
@action
Scenario: ActionRepository.get_by_namespace with state filter returns matching actions
Given repos-cov an action "local/active-one" exists with state "available"
And repos-cov an action "local/archived-one" exists with state "archived"
When repos-cov get_by_namespace is called with namespace "local" and state "available"
Then repos-cov exactly 1 action should be in the result list
And repos-cov the result list should contain action named "local/active-one"
# ---------------------------------------------------------------------------
# ActionRepository.get_by_namespace DatabaseError on OperationalError
# ---------------------------------------------------------------------------
@action @error_handling
Scenario: ActionRepository.get_by_namespace raises DatabaseError on OperationalError
Given a repos-cov action repository with a session that raises OperationalError on query
When repos-cov get_by_namespace is called with namespace "local" expecting error
Then repos-cov a DatabaseError should be raised containing "Failed to list actions in namespace"
# ---------------------------------------------------------------------------
# ActionRepository.list_available without namespace filter
# ---------------------------------------------------------------------------
@action
Scenario: ActionRepository.list_available returns all available actions without namespace
Given repos-cov an action "ns1/act-a" exists with state "available"
And repos-cov an action "ns2/act-b" exists with state "available"
And repos-cov an action "ns1/act-c" exists with state "archived"
When repos-cov list_available is called without a namespace filter
Then repos-cov exactly 2 actions should be in the result list
# ---------------------------------------------------------------------------
# ActionRepository.list_available with namespace filter
# ---------------------------------------------------------------------------
@action
Scenario: ActionRepository.list_available returns available actions filtered by namespace
Given repos-cov an action "nsx/avail-1" exists with state "available"
And repos-cov an action "nsy/avail-2" exists with state "available"
When repos-cov list_available is called with namespace "nsx"
Then repos-cov exactly 1 action should be in the result list
# ---------------------------------------------------------------------------
# ActionRepository.list_available DatabaseError on OperationalError
# ---------------------------------------------------------------------------
@action @error_handling
Scenario: ActionRepository.list_available raises DatabaseError on OperationalError
Given a repos-cov action repository with a session that raises OperationalError on query
When repos-cov list_available is called and an error is expected
Then repos-cov a DatabaseError should be raised containing "Failed to list available actions"
# ---------------------------------------------------------------------------
# ActionRepository.update with arguments having min_value and max_value
# ---------------------------------------------------------------------------
@action @update
Scenario: ActionRepository.update persists arguments with min_value and max_value
Given repos-cov an available action "local/minmax-action" exists
And repos-cov the action has arguments with min_value and max_value set
When repos-cov the action is updated via the repository
Then repos-cov the update should succeed
And repos-cov the retrieved action arguments should have min_value and max_value
# ---------------------------------------------------------------------------
# ActionRepository.delete ActionInUseError when plans reference the action
# ---------------------------------------------------------------------------
@action @delete @error_handling
Scenario: ActionRepository.delete raises ActionInUseError when plans reference the action
Given repos-cov an available action "local/in-use-action" exists
And a repos-cov lifecycle plan references action "local/in-use-action"
When repos-cov delete is called for action "local/in-use-action"
Then repos-cov an ActionInUseError should be raised for "local/in-use-action"
# ---------------------------------------------------------------------------
# ActionRepository.delete successful deletion when no plans reference it
# ---------------------------------------------------------------------------
@action @delete
Scenario: ActionRepository.delete succeeds and returns True for unreferenced action
Given repos-cov an available action "local/deletable" exists
When repos-cov delete is called for action "local/deletable"
Then repos-cov the delete result should be True
And repos-cov get_by_id for "local/deletable" should return None
# ---------------------------------------------------------------------------
# ActionRepository.delete returns False for non-existent action
# ---------------------------------------------------------------------------
@action @delete
Scenario: ActionRepository.delete returns False for non-existent action
When repos-cov delete is called for action "local/ghost"
Then repos-cov the delete result should be False
# ---------------------------------------------------------------------------
# DuplicatePlanError instantiation
# ---------------------------------------------------------------------------
@plan @error_class
Scenario: DuplicatePlanError stores plan_id and message
When repos-cov a DuplicatePlanError is created for plan_id "01HGZ6FE0A00000000TESTPLAN"
Then repos-cov the error message should contain "01HGZ6FE0A00000000TESTPLAN"
And repos-cov the error plan_id attribute should be "01HGZ6FE0A00000000TESTPLAN"
# ---------------------------------------------------------------------------
# LifecyclePlanRepository.get_by_name success path
# ---------------------------------------------------------------------------
@plan
Scenario: LifecyclePlanRepository.get_by_name returns domain object for existing plan
Given repos-cov an available action "local/plan-target" exists
And a repos-cov lifecycle plan linked to "local/plan-target" with name "local/my-plan" has been persisted
When repos-cov plan get_by_name is called with "local/my-plan"
Then repos-cov the returned plan should not be None
# ---------------------------------------------------------------------------
# LifecyclePlanRepository.get_by_name returns None for missing
# ---------------------------------------------------------------------------
@plan
Scenario: LifecyclePlanRepository.get_by_name returns None for non-existent plan
When repos-cov plan get_by_name is called with "local/no-such-plan"
Then repos-cov the returned plan should be None
# ---------------------------------------------------------------------------
# LifecyclePlanRepository.get_by_name DatabaseError on OperationalError
# ---------------------------------------------------------------------------
@plan @error_handling
Scenario: LifecyclePlanRepository.get_by_name raises DatabaseError on OperationalError
Given a repos-cov plan repository with a session that raises OperationalError on query
When repos-cov plan get_by_name is called with "local/error-plan" expecting error
Then repos-cov a DatabaseError should be raised containing "Failed to get plan by name"
# ---------------------------------------------------------------------------
# LifecyclePlanRepository.update full update with project_links, arguments, invariants
# ---------------------------------------------------------------------------
@plan @update
Scenario: LifecyclePlanRepository.update persists project links, arguments, and invariants
Given repos-cov an available action "local/plan-upd-action" exists
And a repos-cov lifecycle plan linked to "local/plan-upd-action" with name "local/upd-plan" has been persisted
And repos-cov the plan has project_links, arguments, and invariants with text attribute
When repos-cov the plan is updated via the repository
Then repos-cov the plan update should succeed
And repos-cov the retrieved plan should have project links
And repos-cov the retrieved plan should have arguments
And repos-cov the retrieved plan should have invariants
# ---------------------------------------------------------------------------
# LifecyclePlanRepository.update invariants as plain strings (no .text attr)
# ---------------------------------------------------------------------------
@plan @update
Scenario: LifecyclePlanRepository.update handles invariants as plain strings
Given repos-cov an available action "local/plan-str-inv" exists
And a repos-cov lifecycle plan linked to "local/plan-str-inv" with name "local/str-inv-plan" has been persisted
And repos-cov the plan has invariants as plain strings without text attribute
When repos-cov the plan is updated via the repository
Then repos-cov the plan update should succeed
And repos-cov the retrieved plan should have invariants
# ---------------------------------------------------------------------------
# LifecyclePlanRepository.update invariant source with .value attribute
# ---------------------------------------------------------------------------
@plan @update
Scenario: LifecyclePlanRepository.update handles invariant source with .value enum
Given repos-cov an available action "local/plan-enum-inv" exists
And a repos-cov lifecycle plan linked to "local/plan-enum-inv" with name "local/enum-inv-plan" has been persisted
And repos-cov the plan has invariants with InvariantSource enum values
When repos-cov the plan is updated via the repository
Then repos-cov the plan update should succeed
# ---------------------------------------------------------------------------
# LifecyclePlanRepository.update processing_state without .value (plain str)
# ---------------------------------------------------------------------------
@plan @update
Scenario: LifecyclePlanRepository.update handles processing_state as plain string
Given repos-cov an available action "local/plan-str-state" exists
And a repos-cov lifecycle plan linked to "local/plan-str-state" with name "local/str-state-plan" has been persisted
And repos-cov the plan processing_state is set to a plain string "processing"
When repos-cov the plan is updated via the repository
Then repos-cov the plan update should succeed
# ---------------------------------------------------------------------------
# LifecyclePlanRepository.update error_details and changeset_id fields
# ---------------------------------------------------------------------------
@plan @update
Scenario: LifecyclePlanRepository.update persists error_details and changeset_id
Given repos-cov an available action "local/plan-err-detail" exists
And a repos-cov lifecycle plan linked to "local/plan-err-detail" with name "local/err-detail-plan" has been persisted
And repos-cov the plan has error_message, error_details, and changeset_id set
When repos-cov the plan is updated via the repository
Then repos-cov the plan update should succeed
And repos-cov the retrieved plan should have the error_message set