a4581663f4
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 10s
CI / integration (pull_request) Successful in 18s
CI / ui (pull_request) Successful in 56s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m22s
The promo message body now renders "@<bot>" as an HTML text_link to the same ?startapp deep link the button uses (ParseMode HTML), so tapping the mention opens the seeded Mini App instead of the bot profile. Same payload (campaign start-param, else the forwarded /start payload) backs both the button and the mention.
127 lines
4.3 KiB
Go
127 lines
4.3 KiB
Go
package promobot
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/go-telegram/bot/models"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
func TestPromoTextLocalization(t *testing.T) {
|
|
const url = "https://t.me/bot/app?startapp=verudit_ru-scrabble_en"
|
|
// The @username is rendered as a clickable deep link (the same target as the button),
|
|
// not a plain mention, so tapping it opens the seeded Mini App.
|
|
wantLink := `<a href="` + url + `">@ScrabbleBot</a>`
|
|
|
|
en, enBtn := promoText("en", "ScrabbleBot", url)
|
|
if !strings.Contains(en, wantLink) || !strings.Contains(en, "profile settings") {
|
|
t.Errorf("en text = %q", en)
|
|
}
|
|
if enBtn != "🤩 I want to play!" {
|
|
t.Errorf("en button = %q", enBtn)
|
|
}
|
|
|
|
ru, ruBtn := promoText("ru-RU", "ScrabbleBot", url)
|
|
if !strings.Contains(ru, wantLink) || !strings.Contains(ru, "Откройте") {
|
|
t.Errorf("ru text = %q", ru)
|
|
}
|
|
if ruBtn != "🤩 Хочу играть!" {
|
|
t.Errorf("ru button = %q", ruBtn)
|
|
}
|
|
|
|
// An unknown language falls back to English, still with the linked mention.
|
|
if got, _ := promoText("de", "B", url); !strings.Contains(got, "Open ") || !strings.Contains(got, `">@B</a>`) {
|
|
t.Errorf("fallback text = %q, want English with a linked mention", got)
|
|
}
|
|
}
|
|
|
|
func TestLaunchURLAppendsStartapp(t *testing.T) {
|
|
b := &Bot{linkURL: "https://t.me/bot/app"}
|
|
if got := b.launchURL(""); got != "https://t.me/bot/app" {
|
|
t.Errorf("empty payload = %q, want the base link unchanged", got)
|
|
}
|
|
if got := b.launchURL("g123"); got != "https://t.me/bot/app?startapp=g123" {
|
|
t.Errorf("launchURL = %q, want startapp=g123 appended", got)
|
|
}
|
|
}
|
|
|
|
func TestLaunchMarkupIsURLButton(t *testing.T) {
|
|
b := &Bot{linkURL: "https://t.me/bot/app"}
|
|
btn := b.launchMarkup("Play", "f99").InlineKeyboard[0][0]
|
|
if btn.WebApp != nil {
|
|
t.Error("the promo button must not be a web_app button (it would sign initData with the promo token, which the main bot rejects)")
|
|
}
|
|
if !strings.Contains(btn.URL, "startapp=f99") {
|
|
t.Errorf("button URL = %q, want startapp=f99", btn.URL)
|
|
}
|
|
}
|
|
|
|
// fakeAPI answers getMe (so New succeeds offline) and records the last sendMessage.
|
|
type fakeAPI struct {
|
|
chatID, text, replyMarkup string
|
|
}
|
|
|
|
func (f *fakeAPI) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
switch {
|
|
case strings.HasSuffix(r.URL.Path, "/getMe"):
|
|
io.WriteString(w, `{"ok":true,"result":{"id":1,"is_bot":true,"first_name":"t","username":"promo"}}`)
|
|
case strings.HasSuffix(r.URL.Path, "/sendMessage"):
|
|
f.chatID = r.FormValue("chat_id")
|
|
f.text = r.FormValue("text")
|
|
f.replyMarkup = r.FormValue("reply_markup")
|
|
io.WriteString(w, `{"ok":true,"result":{"message_id":1}}`)
|
|
default:
|
|
io.WriteString(w, `{"ok":true,"result":true}`)
|
|
}
|
|
}
|
|
|
|
func TestHandleStartReplies(t *testing.T) {
|
|
api := &fakeAPI{}
|
|
srv := httptest.NewServer(api)
|
|
t.Cleanup(srv.Close)
|
|
b, err := New(Config{Token: "1:2", APIBaseURL: srv.URL, BotUsername: "ScrabbleBot", BotLinkURL: "https://t.me/bot/app"}, zap.NewNop())
|
|
if err != nil {
|
|
t.Fatalf("new: %v", err)
|
|
}
|
|
|
|
b.handleStart(context.Background(), b.api, &models.Update{Message: &models.Message{
|
|
Chat: models.Chat{ID: 42, Type: models.ChatTypePrivate},
|
|
From: &models.User{LanguageCode: "ru"},
|
|
Text: "/start f99",
|
|
}})
|
|
|
|
if api.chatID != "42" {
|
|
t.Errorf("chat_id = %q, want 42", api.chatID)
|
|
}
|
|
if !strings.Contains(api.text, `<a href="https://t.me/bot/app?startapp=f99">@ScrabbleBot</a>`) {
|
|
t.Errorf("text = %q, want the @mention linked to the startapp deep link", api.text)
|
|
}
|
|
if strings.Contains(api.replyMarkup, "web_app") {
|
|
t.Errorf("reply_markup = %q has a web_app button; want a url button", api.replyMarkup)
|
|
}
|
|
if !strings.Contains(api.replyMarkup, "startapp=f99") {
|
|
t.Errorf("reply_markup = %q, want startapp=f99 (the /start payload forwarded)", api.replyMarkup)
|
|
}
|
|
}
|
|
|
|
func TestHandleStartIgnoresGroup(t *testing.T) {
|
|
api := &fakeAPI{}
|
|
srv := httptest.NewServer(api)
|
|
t.Cleanup(srv.Close)
|
|
b, err := New(Config{Token: "1:2", APIBaseURL: srv.URL, BotUsername: "B", BotLinkURL: "https://t.me/b/a"}, zap.NewNop())
|
|
if err != nil {
|
|
t.Fatalf("new: %v", err)
|
|
}
|
|
b.handleStart(context.Background(), b.api, &models.Update{Message: &models.Message{
|
|
Chat: models.Chat{ID: -100, Type: models.ChatTypeSupergroup}, Text: "/start",
|
|
}})
|
|
if api.chatID != "" {
|
|
t.Errorf("replied to a group message (chat=%q); want none", api.chatID)
|
|
}
|
|
}
|