f528d6c3a8
CI / lint (pull_request) Successful in 15s
CI / typecheck (pull_request) Successful in 26s
CI / security (pull_request) Successful in 21s
CI / quality (pull_request) Successful in 15s
CI / integration_tests (pull_request) Successful in 4m23s
CI / build (pull_request) Successful in 16s
CI / unit_tests (pull_request) Successful in 8m7s
CI / docker (pull_request) Successful in 39s
CI / coverage (pull_request) Successful in 6m21s
Step A2.beta
175 lines
8.7 KiB
Gherkin
175 lines
8.7 KiB
Gherkin
@phase1 @database @models @lifecycle
|
|
Feature: Lifecycle Data Persistence and Retrieval
|
|
As a system operator
|
|
I want lifecycle actions and plans to survive database round-trips faithfully
|
|
So that no data is lost or corrupted when storing and loading lifecycle records
|
|
|
|
Background:
|
|
Given the lifecycle database is ready
|
|
And a lifecycle database session is open
|
|
|
|
@lifecycle_action @to_domain
|
|
Scenario: A stored action retains its identity and naming when loaded
|
|
Given an action record exists with valid attributes and tags
|
|
When the action record is loaded as a domain object
|
|
Then the loaded action should preserve its original identifier
|
|
And the loaded action should preserve its namespace and short name
|
|
And the loaded action should preserve its description fields
|
|
And the loaded action should preserve its actor assignments
|
|
And the loaded action should preserve its state and flags
|
|
And the loaded action should preserve its timestamps
|
|
And the loaded action should preserve its tags
|
|
|
|
@lifecycle_action @to_domain
|
|
Scenario: A stored action with input arguments loads them correctly
|
|
Given an action record exists with a structured arguments schema
|
|
When the action record is loaded as a domain object
|
|
Then the loaded action should contain the expected argument entries
|
|
And each argument entry should have the correct name and type
|
|
|
|
@lifecycle_action @to_domain
|
|
Scenario: A stored action with no inputs or tags loads empty collections
|
|
Given an action record exists with no inputs and no tags
|
|
When the action record is loaded as a domain object
|
|
Then the loaded action should have an empty arguments collection
|
|
And the loaded action should have an empty tags collection
|
|
|
|
@lifecycle_action @from_domain
|
|
Scenario: A fully populated action domain object is stored correctly
|
|
Given a complete action domain object is prepared
|
|
When the action domain object is stored as a database record
|
|
Then the stored record should preserve the action identifier
|
|
And the stored record should preserve the name components
|
|
And the stored record should preserve the description fields
|
|
And the stored record should preserve the actor assignments
|
|
And the stored record should serialize the arguments as JSON
|
|
And the stored record should serialize the tags as JSON
|
|
And the stored record should preserve the state value
|
|
And the stored record should format timestamps as ISO strings
|
|
|
|
@lifecycle_action @from_domain
|
|
Scenario: An action with an enumerated state stores the enum value
|
|
Given an action domain object is prepared with an enumerated state
|
|
When the action domain object is stored as a database record
|
|
Then the stored record state should equal the enum value
|
|
|
|
@lifecycle_action @from_domain
|
|
Scenario: An action with a custom string state stores it verbatim
|
|
Given an action-like object is prepared with a custom string state
|
|
When the custom-state action is stored as a database record
|
|
Then the stored record state should equal the custom string
|
|
|
|
@lifecycle_plan @parse_iso
|
|
Scenario: A valid ISO-8601 timestamp string is parsed to a datetime
|
|
When a valid ISO-8601 string is parsed as a timestamp
|
|
Then the parsed timestamp should be the expected datetime value
|
|
|
|
@lifecycle_plan @parse_iso
|
|
Scenario: A missing timestamp value parses to nothing
|
|
When an absent value is parsed as a timestamp
|
|
Then the parsed timestamp should be absent
|
|
|
|
@lifecycle_plan @to_iso
|
|
Scenario: A datetime is formatted as an ISO-8601 string
|
|
When a datetime value is formatted as an ISO string
|
|
Then the formatted string should match ISO-8601 format
|
|
|
|
@lifecycle_plan @to_iso
|
|
Scenario: An absent datetime formats to nothing
|
|
When an absent datetime is formatted as an ISO string
|
|
Then the formatted value should be absent
|
|
|
|
@lifecycle_plan @to_domain
|
|
Scenario: A plan in the strategize phase with queued state loads correctly
|
|
Given a plan record exists in the strategize phase with queued state
|
|
When the plan record is loaded as a domain object
|
|
Then the loaded plan should preserve its identity
|
|
And the loaded plan should be in the strategize phase
|
|
And the loaded plan processing state should be queued
|
|
And the loaded plan should preserve its description
|
|
And the loaded plan should preserve its timestamps
|
|
And the loaded plan should preserve its metadata
|
|
|
|
@lifecycle_plan @to_domain
|
|
Scenario: A plan in the strategize phase with processing state loads correctly
|
|
Given a plan record exists in the strategize phase with processing state
|
|
When the plan record is loaded as a domain object
|
|
Then the loaded plan should be in the strategize phase
|
|
And the loaded plan processing state should be processing
|
|
|
|
@lifecycle_plan @to_domain
|
|
Scenario: A completed plan loads all phase timestamps correctly
|
|
Given a plan record exists with all phase timestamps populated
|
|
When the plan record is loaded as a domain object
|
|
Then the loaded plan timestamps should include the strategize window
|
|
And the loaded plan timestamps should include the execute window
|
|
And the loaded plan timestamps should include the apply window
|
|
|
|
@lifecycle_plan @to_domain
|
|
Scenario: A plan with associated projects and tags loads them as lists
|
|
Given a plan record exists with associated project identifiers and tags
|
|
When the plan record is loaded as a domain object
|
|
Then the loaded plan should contain the expected project identifiers
|
|
And the loaded plan should contain the expected tags
|
|
|
|
@lifecycle_plan @from_domain
|
|
Scenario: A plan in STRATEGIZE phase stores the state correctly
|
|
Given a plan domain object is prepared in the strategize phase with a queued state
|
|
When the plan domain object is stored as a database record
|
|
Then the stored plan record should have state "queued"
|
|
And the stored plan record should preserve the plan identifier
|
|
And the stored plan record should preserve the phase
|
|
And the stored plan record should serialize the project identifiers as JSON
|
|
And the stored plan record should serialize the plan tags as JSON
|
|
And the stored plan record should format plan timestamps as ISO strings
|
|
And the stored plan record automation level should be "manual"
|
|
|
|
@lifecycle_plan @from_domain
|
|
Scenario: A plan with a processing state stores the state correctly
|
|
Given a plan domain object is prepared in the strategize phase with a queued state
|
|
When the plan domain object is stored as a database record
|
|
Then the stored plan record should have state "queued"
|
|
And the stored plan record phase should be "strategize"
|
|
|
|
@lifecycle_plan @from_domain
|
|
Scenario: A plan with no explicit state defaults to queued
|
|
Given a plan domain object is prepared with neither action nor processing state
|
|
When the stateless plan domain object is stored as a database record
|
|
Then the stored plan record should have state "queued"
|
|
|
|
@lifecycle_plan @from_domain
|
|
Scenario: A plan with all phase timestamps stores them as ISO strings
|
|
Given a plan domain object is prepared with all phase timestamps
|
|
When the plan domain object is stored as a database record
|
|
Then the stored plan record should have all phase timestamps as ISO strings
|
|
|
|
@lifecycle_plan @from_domain
|
|
Scenario: A plan with non-default automation level stores the real value
|
|
Given a plan domain object is prepared with automation level "full_automation"
|
|
When the plan domain object is stored as a database record
|
|
Then the stored plan record automation level should be "full_automation"
|
|
|
|
@lifecycle_plan @from_domain
|
|
Scenario: A plan with review-before-apply automation level stores correctly
|
|
Given a plan domain object is prepared with automation level "review_before_apply"
|
|
When the plan domain object is stored as a database record
|
|
Then the stored plan record automation level should be "review_before_apply"
|
|
|
|
@lifecycle_plan @from_domain
|
|
Scenario: A plan stored with an explicit action_id preserves it
|
|
Given a plan domain object is prepared in the strategize phase with a queued state
|
|
When the plan domain object is stored with an explicit action identifier
|
|
Then the stored plan record should preserve the supplied action identifier
|
|
|
|
@lifecycle_action @round_trip
|
|
Scenario: An action survives a full save-and-reload cycle unchanged
|
|
Given a complete action domain object is prepared
|
|
When the action is saved to the database and reloaded as a domain object
|
|
Then the reloaded action should match the original action
|
|
|
|
@lifecycle_plan @round_trip
|
|
Scenario: A plan survives a full save-and-reload cycle unchanged
|
|
Given a plan record exists in the strategize phase with queued state
|
|
When the plan record is saved and then reloaded as a domain object
|
|
Then the reloaded plan should preserve its identity and phase
|