Ctrl K
ComunidadGuías…

internal/domain/premium_test.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
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)
		}
	}
}