internal/domain/premium_test.go
Rama main · réplica de lectura del repositorio original.
package domain
import (
"testing"
"time"
)
func TestPremiumActiveAt(t *testing.T) {
now := time.Now().Unix()
cases := []struct {
name string
user User
want bool
}{
{"zero until = non-member", User{}, false},
{"future until = member", User{PremiumUntil: int(now + 3600)}, true},
{"past until = expired", User{PremiumUntil: int(now - 1)}, false},
{"exactly now = expired (boundary excluded)", User{PremiumUntil: int(now)}, false},
{"bot is never Premium (belt and suspenders)", User{Bot: true, BotInfoVersion: 1, PremiumUntil: int(now + 3600)}, false},
}
for _, tc := range cases {
if got := tc.user.PremiumActiveAt(now); got != tc.want {
t.Errorf("%s: PremiumActiveAt = %v, want %v", tc.name, got, tc.want)
}
}
}
func TestEmojiStatusActiveAt(t *testing.T) {
now := time.Now().Unix()
premium := int(now + 3600)
cases := []struct {
name string
user User
want bool
}{
{"not set", User{PremiumUntil: premium}, false},
{"permanent status", User{PremiumUntil: premium, EmojiStatusDocumentID: 7}, true},
{"unexpired status", User{PremiumUntil: premium, EmojiStatusDocumentID: 7, EmojiStatusUntil: int(now + 60)}, true},
{"expired status", User{PremiumUntil: premium, EmojiStatusDocumentID: 7, EmojiStatusUntil: int(now - 60)}, false},
{"residual value not sent after Premium expires", User{PremiumUntil: int(now - 1), EmojiStatusDocumentID: 7}, false},
}
for _, tc := range cases {
if got := tc.user.EmojiStatusActiveAt(now); got != tc.want {
t.Errorf("%s: EmojiStatusActiveAt = %v, want %v", tc.name, got, tc.want)
}
}
}
func TestTrimMessageReactionsToUserMaxTiers(t *testing.T) {
reactions := []MessageReaction{
{Type: MessageReactionEmoji, Emoticon: "👍"},
{Type: MessageReactionEmoji, Emoticon: "❤"},
{Type: MessageReactionEmoji, Emoticon: "🔥"},
{Type: MessageReactionEmoji, Emoticon: "🎉"},
}
// The default tier (including 0 = unfilled by an old caller) trims to 1, keeping the newest at the tail.
for _, max := range []int{0, -1, MaxMessageReactionsPerUser} {
got := TrimMessageReactionsToUserMax(reactions, max)
if len(got) != 1 || got[0].Emoticon != "🎉" {
t.Fatalf("default tier (max=%d) = %+v, want [🎉]", max, got)
}
}
// The Premium tier trims to 3, keeping the newest at the tail.
got := TrimMessageReactionsToUserMax(reactions, MessageReactionsUserMax(true))
if len(got) != 3 || got[0].Emoticon != "❤" || got[2].Emoticon != "🎉" {
t.Fatalf("premium tier = %+v, want [❤ 🔥 🎉]", got)
}
// A requested value beyond the Premium tier is capped.
if got := TrimMessageReactionsToUserMax(reactions, 99); len(got) != MaxMessageReactionsPerUserPremium {
t.Fatalf("over-cap tier = %d entries, want %d", len(got), MaxMessageReactionsPerUserPremium)
}
if MessageReactionsUserMax(false) != MaxMessageReactionsPerUser {
t.Fatalf("MessageReactionsUserMax(false) = %d", MessageReactionsUserMax(false))
}
}
func TestPinnedDialogsLimitTiers(t *testing.T) {
cases := []struct {
folderID int
premium bool
want int
}{
{DialogMainFolderID, false, MaxPinnedDialogsMainFolder},
{DialogMainFolderID, true, MaxPinnedDialogsMainFolderPremium},
{DialogArchiveFolderID, false, MaxPinnedDialogsArchiveFolder},
{DialogArchiveFolderID, true, MaxPinnedDialogsArchiveFolderPremium},
}
for _, tc := range cases {
if got := PinnedDialogsLimit(tc.folderID, tc.premium); got != tc.want {
t.Errorf("PinnedDialogsLimit(%d, %v) = %d, want %d", tc.folderID, tc.premium, got, tc.want)
}
}
}
func TestPremiumGiftMessageValidatesUTF16EntityBounds(t *testing.T) {
valid := PremiumGiftMessage{
Text: "A😀B",
// A=1 UTF-16 unit, 😀=2 units.
Entities: []MessageEntity{{Type: MessageEntityBold, Offset: 1, Length: 2}},
}
if !valid.Valid() {
t.Fatal("valid UTF-16 entity was rejected")
}
for _, invalid := range []PremiumGiftMessage{
{Text: "A😀B", Entities: []MessageEntity{{Type: MessageEntityBold, Offset: 1, Length: 4}}},
{Text: "A😀B", Entities: []MessageEntity{{Type: MessageEntityBold, Offset: 2, Length: 1}}},
{Text: "hello", Entities: []MessageEntity{{Type: MessageEntityBold, Offset: -1, Length: 1}}},
{Text: "hello", Entities: []MessageEntity{{Type: MessageEntityBold, Offset: 0, Length: 0}}},
{Text: "hello", Entities: []MessageEntity{{Type: MessageEntityBold, Offset: 6, Length: 1}}},
{Text: "hello", Entities: []MessageEntity{{Type: MessageEntityURL, Offset: 0, Length: 5}}},
{Text: "hello", Entities: []MessageEntity{{Type: MessageEntityCustomEmoji, Offset: 0, Length: 5}}},
} {
if invalid.Valid() {
t.Fatalf("invalid entity bounds accepted: %+v", invalid)
}
}
}
func TestPremiumPlanBounds(t *testing.T) {
base := PremiumPlan{
Months: 3, DurationDays: 90, AmountStars: 750, Enabled: true,
Label: "3 months", Version: 1,
}
if !base.Valid() {
t.Fatal("normal Premium plan is invalid")
}
for _, mutate := range []func(*PremiumPlan){
func(p *PremiumPlan) { p.Months = MaxPremiumPlanMonths + 1 },
func(p *PremiumPlan) { p.DurationDays = MaxPremiumPlanDurationDays + 1 },
func(p *PremiumPlan) { p.AmountStars = MaxPremiumPlanAmountStars + 1 },
} {
plan := base
mutate(&plan)
if plan.Valid() {
t.Fatalf("out-of-range Premium plan accepted: %+v", plan)
}
}
}