122 lines
4.0 KiB
Go
122 lines
4.0 KiB
Go
package entitlementsvc
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
"time"
|
|
|
|
"galaxy/user/internal/domain/common"
|
|
"galaxy/user/internal/domain/entitlement"
|
|
"galaxy/user/internal/ports"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestReaderGetByUserIDPublishesExpiredRepairEvent(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
userID := common.UserID("user-123")
|
|
startsAt := time.Unix(1_775_240_000, 0).UTC()
|
|
endsAt := startsAt.Add(24 * time.Hour)
|
|
now := endsAt.Add(time.Hour)
|
|
snapshotStore := &fakeSnapshotStore{
|
|
byUserID: map[common.UserID]entitlement.CurrentSnapshot{
|
|
userID: paidSnapshot(
|
|
userID,
|
|
entitlement.PlanCodePaidMonthly,
|
|
startsAt,
|
|
endsAt,
|
|
common.Source("admin"),
|
|
common.ReasonCode("manual_grant"),
|
|
),
|
|
},
|
|
}
|
|
historyStore := &fakeHistoryStore{
|
|
byUserID: map[common.UserID][]entitlement.PeriodRecord{
|
|
userID: {
|
|
paidRecord(
|
|
entitlement.EntitlementRecordID("entitlement-paid"),
|
|
userID,
|
|
entitlement.PlanCodePaidMonthly,
|
|
startsAt,
|
|
endsAt,
|
|
common.Source("admin"),
|
|
common.ReasonCode("manual_grant"),
|
|
),
|
|
},
|
|
},
|
|
}
|
|
lifecycleStore := &fakeLifecycleStore{
|
|
historyStore: historyStore,
|
|
snapshotStore: snapshotStore,
|
|
}
|
|
publisher := &recordingEntitlementPublisher{}
|
|
|
|
reader, err := NewReaderWithObservability(snapshotStore, lifecycleStore, fixedClock{now: now}, fixedIDGenerator{
|
|
recordID: entitlement.EntitlementRecordID("entitlement-free"),
|
|
}, nil, nil, publisher)
|
|
require.NoError(t, err)
|
|
|
|
got, err := reader.GetByUserID(context.Background(), userID)
|
|
require.NoError(t, err)
|
|
require.Equal(t, entitlement.PlanCodeFree, got.PlanCode)
|
|
require.Len(t, publisher.events, 1)
|
|
require.Equal(t, ports.EntitlementChangedOperationExpiredRepaired, publisher.events[0].Operation)
|
|
require.Equal(t, common.Source("entitlement_expiry_repair"), publisher.events[0].Source)
|
|
}
|
|
|
|
func TestGrantServiceExecutePublisherFailureDoesNotRollbackResult(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
now := time.Unix(1_775_240_000, 0).UTC()
|
|
userID := common.UserID("user-123")
|
|
currentFreeStartsAt := now.Add(-24 * time.Hour)
|
|
currentSnapshot := freeSnapshot(userID, currentFreeStartsAt, common.Source("auth_registration"), common.ReasonCode("initial_free_entitlement"))
|
|
currentRecord := freeRecord(entitlement.EntitlementRecordID("entitlement-free"), userID, currentFreeStartsAt, common.Source("auth_registration"), common.ReasonCode("initial_free_entitlement"))
|
|
lifecycleStore := &fakeLifecycleStore{}
|
|
publisher := &recordingEntitlementPublisher{err: errors.New("publisher unavailable")}
|
|
|
|
service, err := NewGrantServiceWithObservability(
|
|
fakeAccountStore{existsByUserID: map[common.UserID]bool{userID: true}},
|
|
&fakeHistoryStore{byUserID: map[common.UserID][]entitlement.PeriodRecord{userID: {currentRecord}}},
|
|
fakeEffectiveReader{byUserID: map[common.UserID]entitlement.CurrentSnapshot{userID: currentSnapshot}},
|
|
lifecycleStore,
|
|
fixedClock{now: now},
|
|
fixedIDGenerator{recordID: entitlement.EntitlementRecordID("entitlement-paid")},
|
|
nil,
|
|
nil,
|
|
publisher,
|
|
)
|
|
require.NoError(t, err)
|
|
|
|
result, err := service.Execute(context.Background(), GrantInput{
|
|
UserID: userID.String(),
|
|
PlanCode: string(entitlement.PlanCodePaidMonthly),
|
|
Source: "admin",
|
|
ReasonCode: "manual_grant",
|
|
Actor: ActorInput{Type: "admin", ID: "admin-1"},
|
|
StartsAt: now.Format(time.RFC3339Nano),
|
|
EndsAt: now.Add(30 * 24 * time.Hour).Format(time.RFC3339Nano),
|
|
})
|
|
require.NoError(t, err)
|
|
require.Equal(t, entitlement.PlanCodePaidMonthly, result.Entitlement.PlanCode)
|
|
require.Len(t, publisher.events, 1)
|
|
require.Equal(t, ports.EntitlementChangedOperationGranted, publisher.events[0].Operation)
|
|
}
|
|
|
|
type recordingEntitlementPublisher struct {
|
|
err error
|
|
events []ports.EntitlementChangedEvent
|
|
}
|
|
|
|
func (publisher *recordingEntitlementPublisher) PublishEntitlementChanged(_ context.Context, event ports.EntitlementChangedEvent) error {
|
|
if err := event.Validate(); err != nil {
|
|
return err
|
|
}
|
|
publisher.events = append(publisher.events, event)
|
|
return publisher.err
|
|
}
|
|
|
|
var _ ports.EntitlementChangedPublisher = (*recordingEntitlementPublisher)(nil)
|