feat: gamemaster
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
package gamemaster
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"galaxy/notificationintent"
|
||||
)
|
||||
|
||||
// TestNotificationIntentConstructorsForGameMaster freezes the producer-side
|
||||
// surface of the three GM-owned notification types against
|
||||
// `pkg/notificationintent`. It complements the YAML-level catalog freeze in
|
||||
// `notification/contract_asyncapi_test.go` by binding the contract at compile
|
||||
// time: any rename of a constant, constructor, payload struct, or struct field
|
||||
// breaks this file's build before it can reach a YAML edit.
|
||||
//
|
||||
// The three types frozen here are documented in `gamemaster/README.md`
|
||||
// §Notification Contracts as the GM-owned producer catalog.
|
||||
func TestNotificationIntentConstructorsForGameMaster(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
metadata := notificationintent.Metadata{
|
||||
IdempotencyKey: "gm-stage07-freeze",
|
||||
OccurredAt: time.UnixMilli(1775121700000).UTC(),
|
||||
}
|
||||
recipientUserIDs := []string{"user-1", "user-2"}
|
||||
|
||||
t.Run("game.turn.ready", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
intent, err := notificationintent.NewGameTurnReadyIntent(
|
||||
metadata,
|
||||
recipientUserIDs,
|
||||
notificationintent.GameTurnReadyPayload{
|
||||
GameID: "game-1",
|
||||
GameName: "Nebula Clash",
|
||||
TurnNumber: 7,
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, notificationintent.NotificationTypeGameTurnReady, intent.NotificationType)
|
||||
require.Equal(t, "game.turn.ready", intent.NotificationType.String())
|
||||
require.Equal(t, notificationintent.ProducerGameMaster, intent.Producer)
|
||||
require.Equal(t, notificationintent.AudienceKindUser, intent.AudienceKind)
|
||||
require.Equal(t, []string{"user-1", "user-2"}, intent.RecipientUserIDs)
|
||||
require.Equal(t, metadata.IdempotencyKey, intent.IdempotencyKey)
|
||||
require.True(t, intent.OccurredAt.Equal(metadata.OccurredAt))
|
||||
require.NoError(t, intent.Validate())
|
||||
|
||||
require.Contains(t, intent.PayloadJSON, `"game_id":"game-1"`)
|
||||
require.Contains(t, intent.PayloadJSON, `"game_name":"Nebula Clash"`)
|
||||
require.Contains(t, intent.PayloadJSON, `"turn_number":7`)
|
||||
})
|
||||
|
||||
t.Run("game.finished", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
intent, err := notificationintent.NewGameFinishedIntent(
|
||||
metadata,
|
||||
recipientUserIDs,
|
||||
notificationintent.GameFinishedPayload{
|
||||
GameID: "game-1",
|
||||
GameName: "Nebula Clash",
|
||||
FinalTurnNumber: 7,
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, notificationintent.NotificationTypeGameFinished, intent.NotificationType)
|
||||
require.Equal(t, "game.finished", intent.NotificationType.String())
|
||||
require.Equal(t, notificationintent.ProducerGameMaster, intent.Producer)
|
||||
require.Equal(t, notificationintent.AudienceKindUser, intent.AudienceKind)
|
||||
require.Equal(t, []string{"user-1", "user-2"}, intent.RecipientUserIDs)
|
||||
require.NoError(t, intent.Validate())
|
||||
|
||||
require.Contains(t, intent.PayloadJSON, `"game_id":"game-1"`)
|
||||
require.Contains(t, intent.PayloadJSON, `"game_name":"Nebula Clash"`)
|
||||
require.Contains(t, intent.PayloadJSON, `"final_turn_number":7`)
|
||||
})
|
||||
|
||||
t.Run("game.generation_failed", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
intent, err := notificationintent.NewGameGenerationFailedIntent(
|
||||
metadata,
|
||||
notificationintent.GameGenerationFailedPayload{
|
||||
GameID: "game-1",
|
||||
GameName: "Nebula Clash",
|
||||
FailureReason: "engine_timeout",
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, notificationintent.NotificationTypeGameGenerationFailed, intent.NotificationType)
|
||||
require.Equal(t, "game.generation_failed", intent.NotificationType.String())
|
||||
require.Equal(t, notificationintent.ProducerGameMaster, intent.Producer)
|
||||
require.Equal(t, notificationintent.AudienceKindAdminEmail, intent.AudienceKind)
|
||||
require.Empty(t, intent.RecipientUserIDs)
|
||||
require.NoError(t, intent.Validate())
|
||||
|
||||
require.Contains(t, intent.PayloadJSON, `"game_id":"game-1"`)
|
||||
require.Contains(t, intent.PayloadJSON, `"game_name":"Nebula Clash"`)
|
||||
require.Contains(t, intent.PayloadJSON, `"failure_reason":"engine_timeout"`)
|
||||
})
|
||||
|
||||
t.Run("audience and channel matrix", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
userTypes := []notificationintent.NotificationType{
|
||||
notificationintent.NotificationTypeGameTurnReady,
|
||||
notificationintent.NotificationTypeGameFinished,
|
||||
}
|
||||
for _, notificationType := range userTypes {
|
||||
notificationType := notificationType
|
||||
t.Run(notificationType.String(), func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
require.Equal(t, notificationintent.ProducerGameMaster, notificationType.ExpectedProducer())
|
||||
|
||||
require.True(t, notificationType.SupportsAudience(notificationintent.AudienceKindUser))
|
||||
require.False(t, notificationType.SupportsAudience(notificationintent.AudienceKindAdminEmail))
|
||||
|
||||
require.True(t, notificationType.SupportsChannel(notificationintent.AudienceKindUser, notificationintent.ChannelPush))
|
||||
require.True(t, notificationType.SupportsChannel(notificationintent.AudienceKindUser, notificationintent.ChannelEmail))
|
||||
require.False(t, notificationType.SupportsChannel(notificationintent.AudienceKindAdminEmail, notificationintent.ChannelEmail))
|
||||
})
|
||||
}
|
||||
|
||||
t.Run("game.generation_failed", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
notificationType := notificationintent.NotificationTypeGameGenerationFailed
|
||||
|
||||
require.Equal(t, notificationintent.ProducerGameMaster, notificationType.ExpectedProducer())
|
||||
|
||||
require.True(t, notificationType.SupportsAudience(notificationintent.AudienceKindAdminEmail))
|
||||
require.False(t, notificationType.SupportsAudience(notificationintent.AudienceKindUser))
|
||||
|
||||
require.True(t, notificationType.SupportsChannel(notificationintent.AudienceKindAdminEmail, notificationintent.ChannelEmail))
|
||||
require.False(t, notificationType.SupportsChannel(notificationintent.AudienceKindAdminEmail, notificationintent.ChannelPush))
|
||||
require.False(t, notificationType.SupportsChannel(notificationintent.AudienceKindUser, notificationintent.ChannelEmail))
|
||||
})
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user