fd6d41b371
CI / lint (pull_request) Successful in 14s
CI / typecheck (pull_request) Successful in 26s
CI / security (pull_request) Successful in 21s
CI / quality (pull_request) Successful in 16s
CI / integration_tests (pull_request) Successful in 4m15s
CI / build (pull_request) Successful in 16s
CI / unit_tests (pull_request) Successful in 7m41s
CI / docker (pull_request) Successful in 39s
CI / lint (push) Successful in 13s
CI / coverage (pull_request) Successful in 5m38s
CI / typecheck (push) Successful in 26s
CI / security (push) Successful in 22s
CI / quality (push) Successful in 15s
CI / integration_tests (push) Successful in 4m10s
CI / build (push) Successful in 15s
CI / unit_tests (push) Successful in 8m17s
CI / docker (push) Successful in 41s
CI / coverage (push) Successful in 5m30s
204 lines
9.0 KiB
Gherkin
204 lines
9.0 KiB
Gherkin
@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
|