148 lines
5.8 KiB
Go
148 lines
5.8 KiB
Go
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))
|
|
})
|
|
})
|
|
}
|