Files
scrabble-game/platform/telegram/internal/bot/welcome_test.go
T
Ilia Denisov aa330b726e
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 10s
CI / integration (pull_request) Successful in 15s
CI / ui (pull_request) Has been skipped
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m17s
feat(telegram): localized /start welcome with channel & chat follow links
The main bot answered /start with a single English line ("Tap to open Scrabble.").
Localize it: Russian or English by the sender's reported Telegram language
(Message.from.language_code, which the Bot API carries on the message itself — there is
no separate user-update event — English fallback), with the longer welcome copy and a
localized launch button ("Открыть «Эрудит»" / "Open “Erudite”").

The welcome links the game channel and the discussion chat by their public @username,
resolved once at startup from the configured TELEGRAM_GAME_CHANNEL_ID / TELEGRAM_CHAT_ID
via getChat and cached. A handle that is unset, private, or unreadable degrades to a
generic noun ("the channel" / "our chat") rather than a dangling "@", so the paragraph
always reads cleanly (the bot's info screen still lists the real links). Adds
GameChannelID to bot.Config (wired from the existing config) for the channel handle.

Tests: startText localization + handle embedding + per-slot generic fallback; handleStart
language selection; resolveWelcomeHandles. README updated.
2026-06-22 19:39:00 +02:00

74 lines
2.7 KiB
Go

package bot
import (
"strings"
"testing"
)
func TestStartTextLocalizesByLanguage(t *testing.T) {
cases := []struct {
name string
lang string
wantButton string
wantSubstr string // a phrase unique to the chosen language body
}{
{"russian", "ru", "Открыть «Эрудит»", "Привет!"},
{"russian region tag", "ru-RU", "Открыть «Эрудит»", "Первая партия"},
{"english", "en", "Open “Erudite”", "Hi!"},
{"other language falls back to english", "de", "Open “Erudite”", "Hi!"},
{"absent language falls back to english", "", "Open “Erudite”", "no more talking"},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
text, button := startText(tc.lang, "erudit", "erudite_chat")
if button != tc.wantButton {
t.Errorf("button = %q, want %q", button, tc.wantButton)
}
if !strings.Contains(text, tc.wantSubstr) {
t.Errorf("text %q does not contain %q", text, tc.wantSubstr)
}
})
}
}
func TestStartTextEmbedsFollowHandles(t *testing.T) {
for _, lang := range []string{"ru", "en"} {
text, _ := startText(lang, "erudit", "erudite_chat")
if !strings.Contains(text, "@erudit") || !strings.Contains(text, "@erudite_chat") {
t.Errorf("lang %q: follow paragraph missing the handles: %q", lang, text)
}
}
}
func TestStartTextFallsBackToGenericWhenHandleMissing(t *testing.T) {
// An unresolved handle degrades to a generic noun rather than a dangling "@" — and
// only that slot degrades; a resolved sibling still shows its "@username".
t.Run("both missing leaves no @", func(t *testing.T) {
for _, lang := range []string{"ru", "en"} {
text, _ := startText(lang, "", "")
if strings.Contains(text, "@") {
t.Errorf("lang %q: text shows a dangling @: %q", lang, text)
}
}
// The generic nouns are present in each language.
ru, _ := startText("ru", "", "")
if !strings.Contains(ru, "на канал") || !strings.Contains(ru, "в нашем чате") {
t.Errorf("russian generic fallback missing: %q", ru)
}
en, _ := startText("en", "", "")
if !strings.Contains(en, "Follow the channel") || !strings.Contains(en, "in our group chat") {
t.Errorf("english generic fallback missing: %q", en)
}
})
t.Run("only the missing slot degrades", func(t *testing.T) {
// Channel resolved, chat missing: the channel keeps its @handle, the chat is generic.
en, _ := startText("en", "erudit", "")
if !strings.Contains(en, "@erudit") || strings.Contains(en, "@erudite") {
t.Errorf("channel handle not shown / chat handle leaked: %q", en)
}
if !strings.Contains(en, "in our group chat") {
t.Errorf("chat slot did not degrade to a generic noun: %q", en)
}
})
}