package attempt import ( "testing" "time" "galaxy/mail/internal/domain/common" "github.com/stretchr/testify/require" ) func TestStatusCanTransitionTo(t *testing.T) { t.Parallel() tests := []struct { name string from Status to Status want bool }{ {name: "scheduled to in progress", from: StatusScheduled, to: StatusInProgress, want: true}, {name: "scheduled to render failed", from: StatusScheduled, to: StatusRenderFailed, want: true}, {name: "scheduled to accepted", from: StatusScheduled, to: StatusProviderAccepted, want: false}, {name: "in progress to accepted", from: StatusInProgress, to: StatusProviderAccepted, want: true}, {name: "in progress to rejected", from: StatusInProgress, to: StatusProviderRejected, want: true}, {name: "in progress to transport failed", from: StatusInProgress, to: StatusTransportFailed, want: true}, {name: "in progress to timed out", from: StatusInProgress, to: StatusTimedOut, want: true}, {name: "accepted terminal", from: StatusProviderAccepted, to: StatusTimedOut, want: false}, } for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() require.Equal(t, tt.want, tt.from.CanTransitionTo(tt.to)) }) } } func TestStatusIsTerminal(t *testing.T) { t.Parallel() require.False(t, StatusScheduled.IsTerminal()) require.False(t, StatusInProgress.IsTerminal()) require.True(t, StatusProviderAccepted.IsTerminal()) require.True(t, StatusProviderRejected.IsTerminal()) require.True(t, StatusTransportFailed.IsTerminal()) require.True(t, StatusTimedOut.IsTerminal()) require.True(t, StatusRenderFailed.IsTerminal()) } func TestAttemptValidate(t *testing.T) { t.Parallel() scheduledFor := time.Unix(1_775_121_700, 0).UTC() startedAt := scheduledFor.Add(time.Minute) finishedAt := startedAt.Add(2 * time.Second) tests := []struct { name string record Attempt wantErr bool }{ { name: "valid scheduled", record: Attempt{ DeliveryID: common.DeliveryID("delivery-123"), AttemptNo: 1, ScheduledFor: scheduledFor, Status: StatusScheduled, }, }, { name: "valid in progress", record: Attempt{ DeliveryID: common.DeliveryID("delivery-123"), AttemptNo: 2, ScheduledFor: scheduledFor, StartedAt: &startedAt, Status: StatusInProgress, }, }, { name: "valid terminal", record: Attempt{ DeliveryID: common.DeliveryID("delivery-123"), AttemptNo: 3, ScheduledFor: scheduledFor, StartedAt: &startedAt, FinishedAt: &finishedAt, Status: StatusProviderAccepted, }, }, { name: "valid render failed", record: Attempt{ DeliveryID: common.DeliveryID("delivery-123"), AttemptNo: 4, ScheduledFor: scheduledFor, StartedAt: &startedAt, FinishedAt: &finishedAt, Status: StatusRenderFailed, ProviderClassification: "missing_required_variable", ProviderSummary: "missing required variables: player.name", }, }, { name: "attempt number must be positive", record: Attempt{ DeliveryID: common.DeliveryID("delivery-123"), ScheduledFor: scheduledFor, Status: StatusScheduled, }, wantErr: true, }, { name: "in progress missing started at", record: Attempt{ DeliveryID: common.DeliveryID("delivery-123"), AttemptNo: 1, ScheduledFor: scheduledFor, Status: StatusInProgress, }, wantErr: true, }, { name: "terminal missing finished at", record: Attempt{ DeliveryID: common.DeliveryID("delivery-123"), AttemptNo: 1, ScheduledFor: scheduledFor, StartedAt: &startedAt, Status: StatusProviderRejected, }, wantErr: true, }, { name: "finished before started", record: Attempt{ DeliveryID: common.DeliveryID("delivery-123"), AttemptNo: 1, ScheduledFor: scheduledFor, StartedAt: &startedAt, FinishedAt: &scheduledFor, Status: StatusTimedOut, }, wantErr: true, }, } for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() err := tt.record.Validate() if tt.wantErr { require.Error(t, err) return } require.NoError(t, err) }) } }