039ab87b52
CI / lint (pull_request) Successful in 15s
CI / typecheck (pull_request) Successful in 31s
CI / security (pull_request) Successful in 22s
CI / quality (pull_request) Successful in 15s
CI / integration_tests (pull_request) Successful in 4m37s
CI / build (pull_request) Successful in 15s
CI / lint (push) Successful in 12s
CI / typecheck (push) Successful in 27s
CI / security (push) Successful in 22s
CI / quality (push) Successful in 15s
CI / unit_tests (pull_request) Successful in 9m56s
CI / integration_tests (push) Successful in 4m41s
CI / build (push) Successful in 15s
CI / unit_tests (push) Successful in 9m58s
CI / coverage (pull_request) Successful in 7m1s
CI / docker (pull_request) Successful in 8s
CI / docker (push) Successful in 8s
CI / coverage (push) Successful in 6m54s
170 lines
6.5 KiB
Gherkin
170 lines
6.5 KiB
Gherkin
Feature: Plan Domain Model
|
|
As a developer
|
|
I want a plan domain model that supports the lifecycle
|
|
So that I can track plans through Strategize -> Execute -> Apply phases
|
|
|
|
# NamespacedName Tests
|
|
|
|
Scenario: Parse simple name defaults to local namespace
|
|
When I parse the namespaced name "my-action"
|
|
Then the parsed namespace should be "local"
|
|
And the parsed item name should be "my-action"
|
|
And the parsed server should be empty
|
|
|
|
Scenario: Parse name with explicit local namespace
|
|
When I parse the namespaced name "local/my-action"
|
|
Then the parsed namespace should be "local"
|
|
And the parsed item name should be "my-action"
|
|
|
|
Scenario: Parse name with organization namespace
|
|
When I parse the namespaced name "myorg/my-action"
|
|
Then the parsed namespace should be "myorg"
|
|
And the parsed item name should be "my-action"
|
|
|
|
Scenario: Parse name with server qualifier
|
|
When I parse the namespaced name "prod:myorg/my-action"
|
|
Then the parsed server should be "prod"
|
|
And the parsed namespace should be "myorg"
|
|
And the parsed item name should be "my-action"
|
|
|
|
Scenario: NamespacedName string representation
|
|
Given I have a namespaced name with server "prod" namespace "myorg" and name "my-action"
|
|
Then the namespaced string representation should be "prod:myorg/my-action"
|
|
|
|
Scenario: NamespacedName without server
|
|
Given I have a namespaced name with namespace "local" and name "test-plan"
|
|
Then the namespaced string representation should be "local/test-plan"
|
|
|
|
Scenario: Invalid namespace with special characters fails
|
|
When I try to create a namespaced name with namespace "my@org" and name "test"
|
|
Then a validation error should be raised
|
|
|
|
Scenario: Empty namespace defaults to local
|
|
Given I create a namespaced name with an empty namespace and name "test-plan"
|
|
Then the parsed namespace should be "local"
|
|
|
|
# PlanPhase Tests
|
|
|
|
Scenario: Plan phases are in correct order
|
|
Then the plan phases should be in order "action, strategize, execute, apply"
|
|
|
|
Scenario: STRATEGIZE phase is the starting phase
|
|
Given I create a new plan
|
|
Then the plan phase should be "strategize"
|
|
|
|
# PlanState Tests
|
|
|
|
Scenario: New plan starts in STRATEGIZE with QUEUED processing state
|
|
Given I create a plan in strategize phase
|
|
Then the plan phase should be "strategize"
|
|
And the plan processing state should be "queued"
|
|
|
|
Scenario: Strategize phase uses ProcessingState
|
|
Given I create a plan in strategize phase
|
|
Then the plan processing state should be "queued"
|
|
|
|
Scenario: Plan in strategize phase defaults to QUEUED processing state
|
|
Given I create a plan in strategize phase
|
|
Then the plan processing state should be "queued"
|
|
And the plan state should be "queued"
|
|
|
|
Scenario: Strategize phase defaults processing_state to QUEUED
|
|
Given I create a plan in strategize phase
|
|
Then the plan processing state should be "queued"
|
|
|
|
# Plan Identity Tests
|
|
|
|
Scenario: Plan requires valid ULID
|
|
When I try to create a plan identity with invalid ULID "not-a-ulid"
|
|
Then a validation error should be raised
|
|
|
|
Scenario: Plan identity with valid ULID succeeds
|
|
When I create a plan identity with ULID "01ARZ3NDEKTSV4RRFFQ69G5FAV"
|
|
Then the plan identity should be valid
|
|
|
|
Scenario: Plan identity supports parent and root plan IDs
|
|
When I create a plan identity with parent "01ARZ3NDEKTSV4RRFFQ69G5FAV" and root "01ARZ3NDEKTSV4RRFFQ69G5FAW"
|
|
Then the parent plan ID should be "01ARZ3NDEKTSV4RRFFQ69G5FAV"
|
|
And the root plan ID should be "01ARZ3NDEKTSV4RRFFQ69G5FAW"
|
|
|
|
# Plan Lifecycle Tests
|
|
|
|
Scenario: New plan starts in STRATEGIZE phase with QUEUED state
|
|
Given I create a new plan with description "Test plan"
|
|
Then the plan phase should be "strategize"
|
|
And the plan processing state should be "queued"
|
|
And the plan should not be terminal
|
|
|
|
Scenario: Plan in STRATEGIZE with QUEUED cannot transition
|
|
Given I create a plan in strategize phase
|
|
Then the plan cannot transition to next phase
|
|
|
|
Scenario: New plan in STRATEGIZE with QUEUED cannot transition
|
|
Given I create a plan in strategize phase
|
|
Then the plan cannot transition to next phase
|
|
|
|
Scenario: Processing complete allows transition
|
|
Given I create a plan in execute phase with complete processing state
|
|
Then the plan can transition to next phase
|
|
|
|
Scenario: Get next phase from STRATEGIZE is EXECUTE
|
|
Given I create a new plan
|
|
Then the next phase should be "execute"
|
|
|
|
Scenario: Get next phase from APPLY is None (terminal phase)
|
|
Given I create a plan in apply phase as terminal
|
|
Then the next phase should be empty
|
|
|
|
Scenario: Unknown phase returns no next phase
|
|
Given I create a plan with an unknown phase value
|
|
Then the next phase should be empty
|
|
|
|
# Phase Transition Validation Tests
|
|
|
|
Scenario: Valid transition from STRATEGIZE to EXECUTE
|
|
Then transition from "strategize" to "execute" should be valid
|
|
|
|
Scenario: Valid transition from EXECUTE to APPLY
|
|
Then transition from "execute" to "apply" should be valid
|
|
|
|
Scenario: Valid transition from APPLY to STRATEGIZE (revert via constrained)
|
|
Then transition from "apply" to "strategize" should be valid
|
|
|
|
Scenario: Invalid transition from STRATEGIZE to APPLY
|
|
Then transition from "strategize" to "apply" should be invalid
|
|
|
|
Scenario: Valid transition from ACTION to STRATEGIZE
|
|
Then transition from "action" to "strategize" should be valid
|
|
|
|
# Error State Tests
|
|
|
|
Scenario: Plan in errored state is_errored returns True
|
|
Given I create a plan in strategize phase with errored state
|
|
Then the plan should be errored
|
|
|
|
Scenario: Plan in processing state is_errored returns False
|
|
Given I create a plan in strategize phase with processing state
|
|
Then the plan should not be errored
|
|
|
|
Scenario: Cancelled plan is terminal
|
|
Given I create a plan in strategize phase with cancelled state
|
|
Then the plan should be terminal
|
|
|
|
# Model Validation Tests
|
|
|
|
Scenario: Plan requires description
|
|
When I try to create a plan without description
|
|
Then a validation error should be raised
|
|
|
|
Scenario: Plan description cannot be empty
|
|
When I try to create a plan with empty description
|
|
Then a validation error should be raised
|
|
|
|
Scenario: Invalid phase value raises validation error
|
|
When I try to create a plan with invalid phase value
|
|
Then a validation error should be raised
|
|
|
|
Scenario: Apply phase cannot transition to next phase
|
|
Given I create a plan in apply phase as terminal
|
|
Then the plan cannot transition to next phase
|