Files
temp/features/repositories_error_handling_coverage.feature
freemo 8ea00f5185 fix: restore CI quality tests to passing state (#4175)
Co-authored-by: Jeffrey Phillips Freeman <the@jeffreyfreeman.me>
Co-committed-by: Jeffrey Phillips Freeman <the@jeffreyfreeman.me>
2026-04-08 11:02:14 +00:00

510 lines
27 KiB
Gherkin

@phase1 @domain @repository @error_handling_coverage
Feature: Repository error handling coverage for major repository classes
As a system operating under unstable database conditions
I want all repository error-handling paths to be covered
So that OperationalError, IntegrityError, and DatabaseError paths are exercised
# ==========================================================================
# NamespacedProjectRepository error handling
# ==========================================================================
# --- create: IntegrityError (UNIQUE) -> DatabaseError "already exists" ----
@project_repo @transient_error
Scenario: NamespacedProjectRepository create raises DatabaseError on UNIQUE IntegrityError
Given a namespaced project repository with session raising UNIQUE IntegrityError on flush
When a namespaced project is created and a repo error is expected
Then a repo DatabaseError should be raised containing "already exists"
# --- create: IntegrityError (non-UNIQUE) -> DatabaseError -----------------
@project_repo @transient_error
Scenario: NamespacedProjectRepository create raises DatabaseError on non-UNIQUE IntegrityError
Given a namespaced project repository with session raising non-UNIQUE IntegrityError on flush
When a namespaced project is created and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to create project"
# --- create: OperationalError -> DatabaseError ----------------------------
@project_repo @transient_error
Scenario: NamespacedProjectRepository create raises DatabaseError on OperationalError
Given a namespaced project repository with session raising OperationalError on flush
When a namespaced project is created and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to create project"
# --- get: OperationalError -> DatabaseError -------------------------------
@project_repo @transient_error
Scenario: NamespacedProjectRepository get raises DatabaseError on OperationalError
Given a namespaced project repository with session raising OperationalError on query
When a namespaced project is fetched by name and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to get project"
# --- list_projects: OperationalError -> DatabaseError ---------------------
@project_repo @transient_error
Scenario: NamespacedProjectRepository list_projects raises DatabaseError on OperationalError
Given a namespaced project repository with session raising OperationalError on query
When namespaced projects are listed and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to list projects"
# --- update: OperationalError -> DatabaseError ----------------------------
@project_repo @transient_error
Scenario: NamespacedProjectRepository update raises DatabaseError on OperationalError
Given a namespaced project repository with session raising OperationalError on query
When a namespaced project is updated and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to update project"
# --- delete: OperationalError -> DatabaseError ----------------------------
@project_repo @transient_error
Scenario: NamespacedProjectRepository delete raises DatabaseError on OperationalError
Given a namespaced project repository with session raising OperationalError on query
When a namespaced project is deleted and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to delete project"
# ==========================================================================
# ToolRepository error handling
# ==========================================================================
# --- add: IntegrityError (UNIQUE) -> DuplicateToolError -------------------
@tool_repo @transient_error
Scenario: ToolRepository add raises DuplicateToolError on UNIQUE IntegrityError
Given a tool repository with session raising UNIQUE IntegrityError on flush
When a tool is added and a repo error is expected
Then a repo DuplicateToolError should be raised
# --- add: IntegrityError (non-UNIQUE) -> DatabaseError --------------------
@tool_repo @transient_error
Scenario: ToolRepository add raises DatabaseError on non-UNIQUE IntegrityError
Given a tool repository with session raising non-UNIQUE IntegrityError on flush
When a tool is added and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to create tool"
# --- add: OperationalError -> DatabaseError -------------------------------
@tool_repo @transient_error
Scenario: ToolRepository add raises DatabaseError on OperationalError
Given a tool repository with session raising OperationalError on flush
When a tool is added and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to create tool"
# --- get_by_name: OperationalError -> DatabaseError -----------------------
@tool_repo @transient_error
Scenario: ToolRepository get_by_name raises DatabaseError on OperationalError
Given a tool repository with session raising OperationalError on query
When a tool is fetched by name and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to get tool"
# --- list_all: OperationalError -> DatabaseError --------------------------
@tool_repo @transient_error
Scenario: ToolRepository list_all raises DatabaseError on OperationalError
Given a tool repository with session raising OperationalError on query
When all tools are listed and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to list tools"
# --- update: ToolNotFoundError (not found) --------------------------------
@tool_repo @not_found
Scenario: ToolRepository update raises ToolNotFoundError when tool not found
Given a tool repository backed by a clean in-memory database
When a non-existent tool is updated and a repo error is expected
Then a repo ToolNotFoundError should be raised
# --- update: OperationalError -> DatabaseError ----------------------------
@tool_repo @transient_error
Scenario: ToolRepository update raises DatabaseError on OperationalError
Given a tool repository with session raising OperationalError on query
When a non-existent tool is updated and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to update tool"
# --- remove: ToolNotFoundError (not found) --------------------------------
@tool_repo @not_found
Scenario: ToolRepository remove raises ToolNotFoundError when tool not found
Given a tool repository backed by a clean in-memory database
When a non-existent tool is removed and a repo error is expected
Then a repo ToolNotFoundError should be raised
# --- remove: OperationalError -> DatabaseError ----------------------------
@tool_repo @transient_error
Scenario: ToolRepository remove raises DatabaseError on OperationalError
Given a tool repository with session raising OperationalError on query
When a non-existent tool is removed and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to delete tool"
# ==========================================================================
# AutomationProfileRepository error handling
# ==========================================================================
# --- get_by_name: OperationalError -> DatabaseError -----------------------
@profile_repo @transient_error
Scenario: AutomationProfileRepository get_by_name raises DatabaseError on OperationalError
Given an automation profile repository with session raising OperationalError on query
When an automation profile is fetched by name and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to get profile"
# --- list_all: OperationalError -> DatabaseError --------------------------
@profile_repo @transient_error
Scenario: AutomationProfileRepository list_all raises DatabaseError on OperationalError
Given an automation profile repository with session raising OperationalError on query
When all automation profiles are listed and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to list profiles"
# --- upsert: OperationalError -> DatabaseError ----------------------------
@profile_repo @transient_error
Scenario: AutomationProfileRepository upsert raises DatabaseError on OperationalError
Given an automation profile repository with session raising OperationalError on query
When an automation profile is upserted and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to upsert profile"
# --- delete: OperationalError -> DatabaseError ----------------------------
@profile_repo @transient_error
Scenario: AutomationProfileRepository delete raises DatabaseError on OperationalError
Given an automation profile repository with session raising OperationalError on query
When an automation profile is deleted and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to delete profile"
# ==========================================================================
# ResourceTypeRepository error handling
# ==========================================================================
# --- create: IntegrityError (non-UNIQUE) -> DatabaseError -----------------
@resource_type_repo @transient_error
Scenario: ResourceTypeRepository create raises DatabaseError on non-UNIQUE IntegrityError
Given a resource type repository with session that passes query but raises non-UNIQUE IntegrityError on flush
When a resource type is created and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to create resource type"
# --- create: OperationalError -> DatabaseError ----------------------------
@resource_type_repo @transient_error
Scenario: ResourceTypeRepository create raises DatabaseError on OperationalError
Given a resource type repository with session raising OperationalError on flush
When a resource type is created and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to create resource type"
# --- get: OperationalError -> DatabaseError -------------------------------
@resource_type_repo @transient_error
Scenario: ResourceTypeRepository get raises DatabaseError on OperationalError
Given a resource type repository with session raising OperationalError on query
When a resource type is fetched by name and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to get resource type"
# --- list_types: OperationalError -> DatabaseError ------------------------
@resource_type_repo @transient_error
Scenario: ResourceTypeRepository list_types raises DatabaseError on OperationalError
Given a resource type repository with session raising OperationalError on query
When resource types are listed and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to list resource types"
# --- update: OperationalError -> DatabaseError ----------------------------
@resource_type_repo @transient_error
Scenario: ResourceTypeRepository update raises DatabaseError on OperationalError
Given a resource type repository with session raising OperationalError on query
When a resource type is updated and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to update resource type"
# --- delete: OperationalError -> DatabaseError ----------------------------
@resource_type_repo @transient_error
Scenario: ResourceTypeRepository delete raises DatabaseError on OperationalError
Given a resource type repository with session raising OperationalError on query
When a resource type is deleted and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to delete resource type"
# ==========================================================================
# ResourceRepository error handling
# ==========================================================================
# --- create: IntegrityError (UNIQUE) -> DuplicateResourceError ------------
@resource_repo @transient_error
Scenario: ResourceRepository create raises DuplicateResourceError on UNIQUE IntegrityError
Given a resource repository with session that passes initial queries but raises UNIQUE IntegrityError on flush
When a resource is created and a repo error is expected
Then a repo DuplicateResourceError should be raised
# --- create: IntegrityError (non-UNIQUE) -> DatabaseError -----------------
@resource_repo @transient_error
Scenario: ResourceRepository create raises DatabaseError on non-UNIQUE IntegrityError
Given a resource repository with session that passes initial queries but raises non-UNIQUE IntegrityError on flush
When a resource is created and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to create resource"
# --- create: OperationalError -> DatabaseError ----------------------------
@resource_repo @transient_error
Scenario: ResourceRepository create raises DatabaseError on OperationalError
Given a resource repository with session raising OperationalError on flush
When a resource is created and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to create resource"
# --- get: OperationalError -> DatabaseError -------------------------------
@resource_repo @transient_error
Scenario: ResourceRepository get raises DatabaseError on OperationalError
Given a resource repository with session raising OperationalError on query
When a resource is fetched by ID and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to get resource"
# --- get_by_name: OperationalError -> DatabaseError -----------------------
@resource_repo @transient_error
Scenario: ResourceRepository get_by_name raises DatabaseError on OperationalError
Given a resource repository with session raising OperationalError on query
When a resource is fetched by name and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to get resource by name"
# --- list_resources: OperationalError -> DatabaseError --------------------
@resource_repo @transient_error
Scenario: ResourceRepository list_resources raises DatabaseError on OperationalError
Given a resource repository with session raising OperationalError on query
When resources are listed and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to list resources"
# --- update: OperationalError -> DatabaseError ----------------------------
@resource_repo @transient_error
Scenario: ResourceRepository update raises DatabaseError on OperationalError
Given a resource repository with session raising OperationalError on query
When a resource is updated and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to update resource"
# --- delete: OperationalError -> DatabaseError ----------------------------
@resource_repo @transient_error
Scenario: ResourceRepository delete raises DatabaseError on OperationalError
Given a resource repository with session raising OperationalError on query
When a resource is deleted and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to delete resource"
# --- resolve_namespaced_name: OperationalError -> DatabaseError -----------
@resource_repo @transient_error
Scenario: ResourceRepository resolve_namespaced_name raises DatabaseError on OperationalError
Given a resource repository with session raising OperationalError on query
When a resource is resolved by name-or-id and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to resolve resource"
# ==========================================================================
# ProjectResourceLinkRepository error handling
# ==========================================================================
# --- create_link: IntegrityError -> DatabaseError -------------------------
@link_repo @transient_error
Scenario: ProjectResourceLinkRepository create_link raises DatabaseError on IntegrityError
Given a project resource link repository with session that passes query but raises IntegrityError on flush
When a project resource link is created and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to create link"
# --- create_link: OperationalError -> DatabaseError -----------------------
@link_repo @transient_error
Scenario: ProjectResourceLinkRepository create_link raises DatabaseError on OperationalError
Given a project resource link repository with session raising OperationalError on flush
When a project resource link is created and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to create link"
# --- list_links: OperationalError -> DatabaseError ------------------------
@link_repo @transient_error
Scenario: ProjectResourceLinkRepository list_links raises DatabaseError on OperationalError
Given a project resource link repository with session raising OperationalError on query
When project resource links are listed and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to list links"
# --- get_link: OperationalError -> DatabaseError --------------------------
@link_repo @transient_error
Scenario: ProjectResourceLinkRepository get_link raises DatabaseError on OperationalError
Given a project resource link repository with session raising OperationalError on query
When a project resource link is fetched and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to get link"
# --- remove_link: OperationalError -> DatabaseError -----------------------
@link_repo @transient_error
Scenario: ProjectResourceLinkRepository remove_link raises DatabaseError on OperationalError
Given a project resource link repository with session raising OperationalError on query
When a project resource link is removed and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to remove link"
# ==========================================================================
# ValidationAttachmentRepository error handling
# ==========================================================================
# --- attach: IntegrityError (UNIQUE) -> DuplicateValidationAttachmentError
@validation_repo @transient_error
Scenario: ValidationAttachmentRepository attach raises DuplicateValidationAttachmentError on UNIQUE IntegrityError
Given a validation attachment repository with session that passes query but raises UNIQUE IntegrityError on flush
When a validation is attached and a repo error is expected
Then a repo DuplicateValidationAttachmentError should be raised
# --- attach: IntegrityError (non-UNIQUE) -> DatabaseError -----------------
@validation_repo @transient_error
Scenario: ValidationAttachmentRepository attach raises DatabaseError on non-UNIQUE IntegrityError
Given a validation attachment repository with session that passes query but raises non-UNIQUE IntegrityError on flush
When a validation is attached and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to attach validation"
# --- attach: OperationalError -> DatabaseError ----------------------------
@validation_repo @transient_error
Scenario: ValidationAttachmentRepository attach raises DatabaseError on OperationalError
Given a validation attachment repository with session raising OperationalError on flush
When a validation is attached and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to attach validation"
# --- detach: OperationalError -> DatabaseError ----------------------------
@validation_repo @transient_error
Scenario: ValidationAttachmentRepository detach raises DatabaseError on OperationalError
Given a validation attachment repository with session raising OperationalError on query
When a validation is detached and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to detach validation"
# --- list_for_resource: OperationalError -> DatabaseError -----------------
@validation_repo @transient_error
Scenario: ValidationAttachmentRepository list_for_resource raises DatabaseError on OperationalError
Given a validation attachment repository with session raising OperationalError on query
When validation attachments are listed and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to list attachments"
# ==========================================================================
# LifecyclePlanRepository error handling
# ==========================================================================
# --- create: IntegrityError (non-UNIQUE) -> DatabaseError -----------------
@plan_repo @transient_error
# @tdd_issue @tdd_issue_4260 @tdd_expected_fail @skip
@skip
Scenario: LifecyclePlanRepository create raises DatabaseError on non-UNIQUE IntegrityError
Given a lifecycle plan repository with session raising non-UNIQUE IntegrityError on flush
When a lifecycle plan is created and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to create plan"
# --- create: OperationalError -> DatabaseError ----------------------------
@plan_repo @transient_error
# @tdd_issue @tdd_issue_4260 @tdd_expected_fail @skip
@skip
Scenario: LifecyclePlanRepository create raises DatabaseError on OperationalError
Given a lifecycle plan repository with session raising OperationalError on flush
When a lifecycle plan is created and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to create plan"
# --- get: OperationalError -> DatabaseError -------------------------------
@plan_repo @transient_error
Scenario: LifecyclePlanRepository get raises DatabaseError on OperationalError
Given a lifecycle plan repository with session raising OperationalError on query
When a lifecycle plan is fetched by ID and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to get plan"
# --- get_by_name: OperationalError -> DatabaseError -----------------------
@plan_repo @transient_error
Scenario: LifecyclePlanRepository get_by_name raises DatabaseError on OperationalError
Given a lifecycle plan repository with session raising OperationalError on query
When a lifecycle plan is fetched by name and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to get plan by name"
# --- update: OperationalError -> DatabaseError ----------------------------
@plan_repo @transient_error
Scenario: LifecyclePlanRepository update raises DatabaseError on OperationalError
Given a lifecycle plan repository with session raising OperationalError on query
When a lifecycle plan is updated and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to update plan"
# --- delete: OperationalError -> DatabaseError ----------------------------
@plan_repo @transient_error
Scenario: LifecyclePlanRepository delete raises DatabaseError on OperationalError
Given a lifecycle plan repository with session raising OperationalError on query
When a lifecycle plan is deleted and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to delete plan"
# --- list_plans: OperationalError -> DatabaseError ------------------------
@plan_repo @transient_error
Scenario: LifecyclePlanRepository list_plans raises DatabaseError on OperationalError
Given a lifecycle plan repository with session raising OperationalError on query
When lifecycle plans are listed and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to list plans"
# --- count: OperationalError -> DatabaseError -----------------------------
@plan_repo @transient_error
Scenario: LifecyclePlanRepository count raises DatabaseError on OperationalError
Given a lifecycle plan repository with session raising OperationalError on query
When lifecycle plans are counted and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to count plans"
# ==========================================================================
# ResourceRepository DAG operations error handling
# ==========================================================================
# --- link_child: IntegrityError -> DatabaseError --------------------------
@resource_repo @dag @transient_error
Scenario: ResourceRepository link_child raises DatabaseError on IntegrityError
Given a resource repository with session that has resources but raises IntegrityError on link flush
When a resource child is linked and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to link"
# --- link_child: OperationalError -> DatabaseError ------------------------
@resource_repo @dag @transient_error
Scenario: ResourceRepository link_child raises DatabaseError on OperationalError during link
Given a resource repository with session that has resources but raises OperationalError on link flush
When a resource child is linked and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to link"
# --- unlink_child: OperationalError -> DatabaseError ----------------------
@resource_repo @dag @transient_error
Scenario: ResourceRepository unlink_child raises DatabaseError on OperationalError
Given a resource repository with session raising OperationalError on query
When a resource child is unlinked and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to unlink"
# --- get_children: OperationalError -> DatabaseError ----------------------
@resource_repo @dag @transient_error
Scenario: ResourceRepository get_children raises DatabaseError on OperationalError
Given a resource repository with session raising OperationalError on query
When resource children are fetched and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to get children"
# --- get_parents: OperationalError -> DatabaseError -----------------------
@resource_repo @dag @transient_error
Scenario: ResourceRepository get_parents raises DatabaseError on OperationalError
Given a resource repository with session raising OperationalError on query
When resource parents are fetched and a repo error is expected
Then a repo DatabaseError should be raised containing "Failed to get parents"