Files
galaxy-game/notification/internal/service/publishpush/encoder_test.go
T
2026-04-25 23:20:55 +02:00

211 lines
7.4 KiB
Go

package publishpush
import (
"testing"
"time"
"galaxy/notification/internal/api/intentstream"
"galaxy/notification/internal/service/acceptintent"
"galaxy/transcoder"
"github.com/stretchr/testify/require"
)
func TestEncoderEncodesSupportedPushNotificationTypes(t *testing.T) {
t.Parallel()
now := time.UnixMilli(1775121700000).UTC()
tests := []struct {
name string
notificationType intentstream.NotificationType
payloadJSON string
assertPayload func(*testing.T, []byte)
}{
{
name: "game turn ready",
notificationType: intentstream.NotificationTypeGameTurnReady,
payloadJSON: `{"game_id":"game-1","game_name":"Nebula Clash","turn_number":54}`,
assertPayload: func(t *testing.T, payload []byte) {
t.Helper()
event, err := transcoder.PayloadToGameTurnReadyEvent(payload)
require.NoError(t, err)
require.Equal(t, "game-1", event.GameID)
require.Equal(t, int64(54), event.TurnNumber)
},
},
{
name: "game finished",
notificationType: intentstream.NotificationTypeGameFinished,
payloadJSON: `{"final_turn_number":81,"game_id":"game-2","game_name":"Nova"}`,
assertPayload: func(t *testing.T, payload []byte) {
t.Helper()
event, err := transcoder.PayloadToGameFinishedEvent(payload)
require.NoError(t, err)
require.Equal(t, "game-2", event.GameID)
require.Equal(t, int64(81), event.FinalTurnNumber)
},
},
{
name: "lobby application submitted",
notificationType: intentstream.NotificationTypeLobbyApplicationSubmitted,
payloadJSON: `{"applicant_name":"Nova Pilot","applicant_user_id":"user-2","game_id":"game-3","game_name":"Orion Front"}`,
assertPayload: func(t *testing.T, payload []byte) {
t.Helper()
event, err := transcoder.PayloadToLobbyApplicationSubmittedEvent(payload)
require.NoError(t, err)
require.Equal(t, "game-3", event.GameID)
require.Equal(t, "user-2", event.ApplicantUserID)
},
},
{
name: "lobby membership approved",
notificationType: intentstream.NotificationTypeLobbyMembershipApproved,
payloadJSON: `{"game_id":"game-4","game_name":"Ares"}`,
assertPayload: func(t *testing.T, payload []byte) {
t.Helper()
event, err := transcoder.PayloadToLobbyMembershipApprovedEvent(payload)
require.NoError(t, err)
require.Equal(t, "game-4", event.GameID)
},
},
{
name: "lobby membership rejected",
notificationType: intentstream.NotificationTypeLobbyMembershipRejected,
payloadJSON: `{"game_id":"game-5","game_name":"Atlas"}`,
assertPayload: func(t *testing.T, payload []byte) {
t.Helper()
event, err := transcoder.PayloadToLobbyMembershipRejectedEvent(payload)
require.NoError(t, err)
require.Equal(t, "game-5", event.GameID)
},
},
{
name: "lobby invite created",
notificationType: intentstream.NotificationTypeLobbyInviteCreated,
payloadJSON: `{"game_id":"game-6","game_name":"Vega","inviter_name":"Nova Pilot","inviter_user_id":"user-9"}`,
assertPayload: func(t *testing.T, payload []byte) {
t.Helper()
event, err := transcoder.PayloadToLobbyInviteCreatedEvent(payload)
require.NoError(t, err)
require.Equal(t, "game-6", event.GameID)
require.Equal(t, "user-9", event.InviterUserID)
},
},
{
name: "lobby invite redeemed",
notificationType: intentstream.NotificationTypeLobbyInviteRedeemed,
payloadJSON: `{"game_id":"game-7","game_name":"Lyra","invitee_name":"Skipper","invitee_user_id":"user-10"}`,
assertPayload: func(t *testing.T, payload []byte) {
t.Helper()
event, err := transcoder.PayloadToLobbyInviteRedeemedEvent(payload)
require.NoError(t, err)
require.Equal(t, "game-7", event.GameID)
require.Equal(t, "user-10", event.InviteeUserID)
},
},
{
name: "lobby race name registration eligible",
notificationType: intentstream.NotificationTypeLobbyRaceNameRegistrationEligible,
payloadJSON: `{"eligible_until_ms":1775208100000,"game_id":"game-8","game_name":"Aurora","race_name":"Skylancer"}`,
assertPayload: func(t *testing.T, payload []byte) {
t.Helper()
event, err := transcoder.PayloadToLobbyRaceNameRegistrationEligibleEvent(payload)
require.NoError(t, err)
require.Equal(t, "game-8", event.GameID)
require.Equal(t, "Skylancer", event.RaceName)
require.Equal(t, int64(1775208100000), event.EligibleUntilMs)
},
},
{
name: "lobby race name registered",
notificationType: intentstream.NotificationTypeLobbyRaceNameRegistered,
payloadJSON: `{"race_name":"Skylancer"}`,
assertPayload: func(t *testing.T, payload []byte) {
t.Helper()
event, err := transcoder.PayloadToLobbyRaceNameRegisteredEvent(payload)
require.NoError(t, err)
require.Equal(t, "Skylancer", event.RaceName)
},
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
event, err := Encoder{}.Encode(
acceptintent.NotificationRecord{
NotificationID: "1775121700000-0",
NotificationType: tt.notificationType,
Producer: tt.notificationType.ExpectedProducer(),
AudienceKind: intentstream.AudienceKindUser,
RecipientUserIDs: []string{"user-1"},
PayloadJSON: tt.payloadJSON,
IdempotencyKey: "idem-1",
RequestFingerprint: "sha256:deadbeef",
RequestID: "request-1",
TraceID: "trace-1",
OccurredAt: now,
AcceptedAt: now,
UpdatedAt: now,
},
acceptintent.NotificationRoute{
NotificationID: "1775121700000-0",
RouteID: "push:user:user-1",
Channel: intentstream.ChannelPush,
RecipientRef: "user:user-1",
Status: acceptintent.RouteStatusPending,
MaxAttempts: 3,
NextAttemptAt: now,
CreatedAt: now,
UpdatedAt: now,
},
)
require.NoError(t, err)
require.Equal(t, "user-1", event.UserID)
require.Equal(t, string(tt.notificationType), event.EventType)
require.Equal(t, "1775121700000-0/push:user:user-1", event.EventID)
require.Equal(t, "request-1", event.RequestID)
require.Equal(t, "trace-1", event.TraceID)
require.NotEmpty(t, event.PayloadBytes)
tt.assertPayload(t, event.PayloadBytes)
})
}
}
func TestEncoderRejectsInvalidStoredPayload(t *testing.T) {
t.Parallel()
now := time.UnixMilli(1775121700000).UTC()
_, err := Encoder{}.Encode(
acceptintent.NotificationRecord{
NotificationID: "1775121700000-0",
NotificationType: intentstream.NotificationTypeGameTurnReady,
Producer: intentstream.ProducerGameMaster,
AudienceKind: intentstream.AudienceKindUser,
RecipientUserIDs: []string{"user-1"},
PayloadJSON: `{"game_id":"","game_name":"Nebula Clash","turn_number":0}`,
IdempotencyKey: "idem-1",
RequestFingerprint: "sha256:deadbeef",
OccurredAt: now,
AcceptedAt: now,
UpdatedAt: now,
},
acceptintent.NotificationRoute{
NotificationID: "1775121700000-0",
RouteID: "push:user:user-1",
Channel: intentstream.ChannelPush,
RecipientRef: "user:user-1",
Status: acceptintent.RouteStatusPending,
MaxAttempts: 3,
NextAttemptAt: now,
CreatedAt: now,
UpdatedAt: now,
},
)
require.Error(t, err)
require.ErrorContains(t, err, "payload_encoding_failed")
}