Files
glchat/internal/push/rules_test.go
T

135 lines
4.5 KiB
Go
Raw Normal View History

package push
import (
"strings"
"testing"
"glchat/internal/store"
)
// input — сообщение по умолчанию: обычное сообщение в комнате сервера.
// Набор проверок повторяет web/tests/desktopNotifications.test.ts: правила
// push и нативных уведомлений обязаны совпадать.
func input(overrides func(*NotificationInput)) NotificationInput {
value := NotificationInput{
MessageType: store.MessageDefault,
Content: "привет",
Mentions: nil,
AuthorID: 2,
MeID: 1,
IsDirect: false,
ChannelName: "общий",
ChannelID: 10,
MessageID: 99,
GuildID: 1,
GuildName: "Сервер",
AuthorName: "Аня",
}
if overrides != nil {
overrides(&value)
}
return value
}
func TestNotificationForMention(t *testing.T) {
payload := NotificationFor(input(func(in *NotificationInput) { in.Mentions = []uint64{1} }))
if payload == nil {
t.Fatal("упоминание не дало уведомления")
}
if payload.Title != "Упоминание в #общий" || payload.Body != "привет" {
t.Fatalf("неожиданный текст: %+v", payload)
}
if payload.Kind != "mention" || payload.ChannelID != "10" || payload.Tag != "channel-10" {
t.Fatalf("неожиданные поля: %+v", payload)
}
if payload.URL != "/app/1/10" {
t.Fatalf("ссылка = %q, ожидалось /app/1/10", payload.URL)
}
}
func TestNotificationForDirect(t *testing.T) {
payload := NotificationFor(input(func(in *NotificationInput) {
in.IsDirect = true
in.GuildID = 0
in.GuildName = ""
in.ChannelName = "Аня"
}))
if payload == nil {
t.Fatal("личное сообщение не дало уведомления")
}
if payload.Title != "Личное сообщение — Аня" || payload.Kind != "direct" {
t.Fatalf("неожиданный текст: %+v", payload)
}
if payload.URL != "/app/friends/10" {
t.Fatalf("ссылка = %q, ожидалось /app/friends/10", payload.URL)
}
}
func TestNotificationForSilentCases(t *testing.T) {
cases := map[string]NotificationInput{
"обычное сообщение в комнате": input(nil),
"своё сообщение": input(func(in *NotificationInput) {
in.IsDirect = true
in.AuthorID = in.MeID
}),
"системное сообщение": input(func(in *NotificationInput) {
in.IsDirect = true
in.MessageType = store.MessageSystem
}),
"получатель в клиенте": input(func(in *NotificationInput) {
in.IsDirect = true
in.Mentions = []uint64{1}
in.Online = true
}),
"упоминание другого пользователя": input(func(in *NotificationInput) {
in.Mentions = []uint64{777}
}),
"пустое сообщение без упоминаний": input(func(in *NotificationInput) {
in.IsDirect = true
in.Content = ""
}),
}
for name, value := range cases {
if payload := NotificationFor(value); payload != nil {
t.Errorf("%s: уведомление не должно отправляться (%+v)", name, payload)
}
}
}
// Упоминание с пустым текстом (одно вложение) — как в клиенте: «Вложение».
func TestNotificationForAttachmentOnly(t *testing.T) {
payload := NotificationFor(input(func(in *NotificationInput) {
in.IsDirect = true
in.Content = ""
in.Mentions = []uint64{1}
}))
if payload == nil || payload.Body != "Вложение" {
t.Fatalf("ожидалось «Вложение», получили %+v", payload)
}
}
func TestPreviewText(t *testing.T) {
if got := previewText("**жирный**\n\n[ссылка](https://example.com) `код`"); got != "жирный ссылка код" {
t.Fatalf("previewText = %q", got)
}
if got := previewText("```go\nfunc main() {}\n``` после"); got != "[код] после" {
t.Fatalf("блок кода = %q", got)
}
long := previewText(strings.Repeat("а", 400))
if len([]rune(long)) > previewLimit {
t.Fatalf("длина превью %d превышает лимит %d", len([]rune(long)), previewLimit)
}
if !strings.HasSuffix(long, "…") {
t.Fatalf("длинный текст не обрезан: %q", long)
}
}
func TestFormatOptionalID(t *testing.T) {
if got := formatOptionalID(0); got != "" {
t.Fatalf("нулевой идентификатор = %q, ожидалась пустая строка", got)
}
if got := formatOptionalID(42); got != "42" {
t.Fatalf("идентификатор = %q", got)
}
}