@phase1 @domain @repository @action_repository Feature: Action Repository Persistence As a system operator managing reusable actions I want the action repository to reliably persist and retrieve actions So that lifecycle plans can reference well-defined action templates Background: Given a clean in-memory database with the lifecycle schema And an action repository backed by the database # --------------------------------------------------------------------------- # Creating actions # --------------------------------------------------------------------------- @action_create Scenario: A new action is persisted and retrievable Given a valid action domain object named "local/deploy-service" When the action is saved through the repository Then the repository should not raise an error And the persisted action should retain the name "local/deploy-service" @action_create @error_handling Scenario: Saving an action with a duplicate name is rejected Given a valid action domain object named "local/deploy-service" And the action has already been saved once When a second action with the same name "local/deploy-service" is saved Then a DuplicateActionError should be raised mentioning "local/deploy-service" # --------------------------------------------------------------------------- # Retrieving actions by identifier # --------------------------------------------------------------------------- @action_read Scenario: An action is retrieved by its unique identifier Given a valid action domain object named "local/lookup-test" And the action has been saved through the repository When the action is looked up by its identifier Then the returned action should have the name "local/lookup-test" @action_read Scenario: Looking up a non-existent identifier returns nothing When an action is looked up by the identifier "01ZZZZZZZZZZZZZZZZZZZZZZZZ" Then no action should be returned # --------------------------------------------------------------------------- # Retrieving actions by name # --------------------------------------------------------------------------- @action_read Scenario: An action is retrieved by its full namespaced name Given a valid action domain object named "local/named-lookup" And the action has been saved through the repository When the action is looked up by name "local/named-lookup" Then the returned action should have the name "local/named-lookup" @action_read Scenario: Looking up a non-existent name returns nothing When the action is looked up by name "local/does-not-exist" Then no action should be returned # --------------------------------------------------------------------------- # Listing actions by namespace # --------------------------------------------------------------------------- @action_list Scenario: Actions in a namespace are listed without a state filter Given the following actions have been saved: | name | | local/alpha-action | | local/beta-action | | shared/gamma-action | When actions in the "local" namespace are listed Then 2 actions should be returned And the returned action names should include "local/alpha-action" And the returned action names should include "local/beta-action" @action_list Scenario: Actions in a namespace are filtered by state Given the following actions have been saved: | name | state | | local/archived-one | archived | | local/available-one | available | When actions in the "local" namespace are listed with state "available" Then 1 action should be returned And the returned action names should include "local/available-one" # --------------------------------------------------------------------------- # Listing actions by state # --------------------------------------------------------------------------- @action_list Scenario: Actions are listed by their lifecycle state Given the following actions have been saved: | name | state | | local/available-a | available | | local/available-b | available | | local/archived-a | archived | When actions in the "available" state are listed Then 2 actions should be returned # --------------------------------------------------------------------------- # Listing available actions # --------------------------------------------------------------------------- @action_list Scenario: Available actions are listed across all namespaces Given the following actions have been saved: | name | state | | local/avail-one | available | | shared/avail-two | available | | local/archived-only | archived | When all available actions are listed Then 2 actions should be returned @action_list Scenario: Available actions are filtered by namespace Given the following actions have been saved: | name | state | | local/avail-one | available | | shared/avail-two | available | When available actions in the "local" namespace are listed Then 1 action should be returned And the returned action names should include "local/avail-one" # --------------------------------------------------------------------------- # Updating actions # --------------------------------------------------------------------------- @action_update Scenario: An existing action is updated with new field values Given a valid action domain object named "local/updatable" And the action has been saved through the repository When the action description is changed to "Updated definition of done" And the action is updated through the repository Then the repository should not raise an error @action_update @error_handling Scenario: Updating a non-existent action raises an error Given a valid action domain object named "local/phantom" When the phantom action is updated without being saved first Then a DatabaseError should be raised about the missing action # --------------------------------------------------------------------------- # Deleting actions # --------------------------------------------------------------------------- @action_delete Scenario: An existing action is deleted successfully Given a valid action domain object named "local/deletable" And the action has been saved through the repository When the action is deleted by its identifier Then the delete operation should return true And looking up the deleted action by identifier should return nothing @action_delete Scenario: Deleting a non-existent action returns false When an action with identifier "01ZZZZZZZZZZZZZZZZZZZZZZZZ" is deleted Then the delete operation should return false @action_delete @error_handling Scenario: Deleting an action that is still referenced by plans is rejected Given a valid action domain object named "local/in-use-action" And the action has been saved through the repository And a lifecycle plan references that action When the referenced action is deleted Then an ActionInUseError should be raised # --------------------------------------------------------------------------- # Error classes # --------------------------------------------------------------------------- @error_handling Scenario: DuplicateActionError carries the offending action name When a DuplicateActionError is created for name "local/conflict" Then the error should contain the message "local/conflict" And the error should expose the action name "local/conflict" @error_handling Scenario: ActionInUseError carries the action identifier and plan count When an ActionInUseError is created for action "01ABC" with 3 referencing plans Then the error should mention "01ABC" and "3 plan(s)" And the error should expose action identifier "01ABC" and plan count 3 # --------------------------------------------------------------------------- # Partial branch coverage - ProjectRepository.delete (line 145) # --------------------------------------------------------------------------- @project_delete Scenario: Deleting a non-existent project completes without error Given a project repository backed by the database When a project with identifier 99999 is deleted Then the delete operation should complete without error # --------------------------------------------------------------------------- # Partial branch coverage - PlanRepository.update (line 215) # --------------------------------------------------------------------------- @plan_update Scenario: Updating a plan that does not exist leaves the plan unchanged Given a plan repository backed by the database And a plan domain object with identifier 99999 When the non-existent plan is updated through the repository Then the plan object should be returned unchanged