package ports import ( "testing" "time" "galaxy/gamemaster/internal/domain/runtime" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func validSnapshotUpdate() RuntimeSnapshotUpdate { return RuntimeSnapshotUpdate{ GameID: "game-1", CurrentTurn: 3, RuntimeStatus: runtime.StatusRunning, EngineHealthSummary: "healthy", PlayerTurnStats: []PlayerTurnStats{ {UserID: "user-1", Planets: 1, Population: 100}, {UserID: "user-2", Planets: 2, Population: 200}, }, OccurredAt: time.Date(2026, 4, 27, 12, 0, 0, 0, time.UTC), } } func validGameFinished() GameFinished { return GameFinished{ GameID: "game-1", FinalTurnNumber: 42, RuntimeStatus: runtime.StatusFinished, PlayerTurnStats: []PlayerTurnStats{ {UserID: "user-1", Planets: 5, Population: 500}, }, FinishedAt: time.Date(2026, 4, 27, 18, 30, 0, 0, time.UTC), } } func TestRuntimeSnapshotUpdateValidateHappy(t *testing.T) { require.NoError(t, validSnapshotUpdate().Validate()) } func TestRuntimeSnapshotUpdateValidateAcceptsEmptyStats(t *testing.T) { msg := validSnapshotUpdate() msg.PlayerTurnStats = nil assert.NoError(t, msg.Validate()) } func TestRuntimeSnapshotUpdateValidateRejects(t *testing.T) { tests := []struct { name string mutate func(*RuntimeSnapshotUpdate) }{ {"empty game id", func(m *RuntimeSnapshotUpdate) { m.GameID = "" }}, {"negative turn", func(m *RuntimeSnapshotUpdate) { m.CurrentTurn = -1 }}, {"unknown status", func(m *RuntimeSnapshotUpdate) { m.RuntimeStatus = "exotic" }}, {"zero occurred at", func(m *RuntimeSnapshotUpdate) { m.OccurredAt = time.Time{} }}, {"bad stats entry", func(m *RuntimeSnapshotUpdate) { m.PlayerTurnStats = append(m.PlayerTurnStats, PlayerTurnStats{ UserID: "", Planets: 0, Population: 0, }) }}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { msg := validSnapshotUpdate() tt.mutate(&msg) assert.Error(t, msg.Validate()) }) } } func TestGameFinishedValidateHappy(t *testing.T) { require.NoError(t, validGameFinished().Validate()) } func TestGameFinishedValidateRejects(t *testing.T) { tests := []struct { name string mutate func(*GameFinished) }{ {"empty game id", func(m *GameFinished) { m.GameID = "" }}, {"negative final turn", func(m *GameFinished) { m.FinalTurnNumber = -1 }}, {"non-finished status", func(m *GameFinished) { m.RuntimeStatus = runtime.StatusRunning }}, {"zero finished at", func(m *GameFinished) { m.FinishedAt = time.Time{} }}, {"bad stats entry", func(m *GameFinished) { m.PlayerTurnStats = append(m.PlayerTurnStats, PlayerTurnStats{ UserID: "user-bad", Planets: -1, Population: 0, }) }}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { msg := validGameFinished() tt.mutate(&msg) assert.Error(t, msg.Validate()) }) } } func TestPlayerTurnStatsValidateRejects(t *testing.T) { bad := PlayerTurnStats{UserID: "", Planets: 0, Population: 0} assert.Error(t, bad.Validate()) bad = PlayerTurnStats{UserID: "u", Planets: -1, Population: 0} assert.Error(t, bad.Validate()) bad = PlayerTurnStats{UserID: "u", Planets: 0, Population: -1} assert.Error(t, bad.Validate()) }