Skip to content

TST-34: Domain entity state machine exhaustive tests — CommandRun, ArchiveItem, ChatSession #701

@Chris0Jeky

Description

@Chris0Jeky

Context

Several domain entities have rich state machines with transition guards that are completely untested. These are the core business rules of the system.

Entities and Their State Machines

CommandRun (6 states, 5 transitions, 0 tests)

State machine: Queued → Running → Completed/Failed/TimedOut/Cancelled

Test matrix:

From Action Expected
Queued Start() Running
Queued Fail("msg") Failed
Queued Cancel() Cancelled
Running Complete(0) Completed
Running Complete(1) Completed (non-zero exit)
Running Fail("msg") Failed
Running Timeout() TimedOut
Running Cancel() Cancelled
Completed Start() throws
Completed Complete(0) throws
Failed Start() throws
TimedOut Cancel() throws
Cancelled Start() throws

Also test:

  • Constructor rejects empty templateName, Guid.Empty userId, empty correlationId
  • Fail("") throws (empty error message)
  • SetOutputPreview with string > 1000 chars throws
  • SetOutputPreview(null) succeeds (nullable)
  • SetTruncated() is idempotent
  • AddLog() adds to Logs collection and calls Touch()

ArchiveItem (4 states, 4 transitions, 0 tests)

State machine: Available → Restored/Expired/Conflict

Test matrix:

From Action Expected
Available MarkAsRestored(userId) Restored
Available MarkAsExpired() Expired
Available MarkAsConflict() Conflict
Restored ResetToAvailable() throws
Expired ResetToAvailable() Available
Conflict ResetToAvailable() Available
Restored MarkAsExpired() throws
Expired MarkAsRestored(userId) throws

Also test:

  • Constructor validates entityType must be "board", "column", or "card" — test "task", "", null
  • name.Length > 200 throws
  • Guid.Empty for various ID parameters throws
  • Empty snapshotJson throws
  • MarkAsRestored(Guid.Empty) throws

UserPreference (untested)

  • DismissOnboarding() / ReplayOnboarding() / RecordOnboardingCompletion() idempotent guard
  • Verify RecordOnboardingCompletion can only be called once

NotificationPreference (untested)

  • Update() method validates new values

ChatSession (untested)

  • Session lifecycle and message accumulation
  • Any state-dependent behavior

CardLabel and CardCommentMention (untested)

  • Construction invariants

Implementation Notes

  • These are pure domain tests — no mocking needed, just construct entities and assert
  • Follow existing pattern in Taskdeck.Domain.Tests (e.g., BoardTests, CardTests)
  • One test class per entity
  • Use [Theory] with [InlineData] for the transition matrix
  • Verify Touch() is called (UpdatedAt changes) on every mutation

Metadata

Metadata

Assignees

No one assigned

    Projects

    Status

    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions