package bot import ( "context" "io" "net/http" "net/http/httptest" "strings" "testing" "go.uber.org/zap" ) // fakeBotAPI answers getMe (so bot.New succeeds offline) and records the last // sendMessage form fields. type fakeBotAPI struct { chatID string text string replyMarkup string } func (f *fakeBotAPI) 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":"test","username":"testbot"}}`) 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 newTestBot(t *testing.T, api http.Handler) *Bot { t.Helper() srv := httptest.NewServer(api) t.Cleanup(srv.Close) b, err := New(Config{Token: "123:ABC", APIBaseURL: srv.URL, MiniAppURL: "https://example.com/telegram/"}, zap.NewNop()) if err != nil { t.Fatalf("new bot: %v", err) } return b } func TestNotifyBuildsLaunchButton(t *testing.T) { api := &fakeBotAPI{} b := newTestBot(t, api) if err := b.Notify(context.Background(), 12345, "It's your turn.", "Open game", "g7c9e"); err != nil { t.Fatalf("notify: %v", err) } if api.chatID != "12345" { t.Errorf("chat_id = %q, want 12345", api.chatID) } if api.text != "It's your turn." { t.Errorf("text = %q", api.text) } if !strings.Contains(api.replyMarkup, "web_app") || !strings.Contains(api.replyMarkup, "startapp=g7c9e") { t.Errorf("reply_markup = %q, want a web_app button with startapp=g7c9e", api.replyMarkup) } } func TestSendTextHasNoMarkup(t *testing.T) { api := &fakeBotAPI{} b := newTestBot(t, api) if err := b.SendText(context.Background(), 999, "plain"); err != nil { t.Fatalf("send text: %v", err) } if api.chatID != "999" || api.text != "plain" { t.Errorf("chat_id=%q text=%q, want 999/plain", api.chatID, api.text) } if api.replyMarkup != "" { t.Errorf("reply_markup = %q, want empty", api.replyMarkup) } } func TestStartPayload(t *testing.T) { cases := map[string]string{ "/start g123": "g123", "/start": "", "/start f99 ": "f99", "hello": "", } for in, want := range cases { if got := startPayload(in); got != want { t.Errorf("startPayload(%q) = %q, want %q", in, got, want) } } } func TestLaunchURL(t *testing.T) { b := &Bot{miniAppURL: "https://example.com/telegram/"} if got := b.launchURL(""); got != "https://example.com/telegram/" { t.Errorf("empty start param = %q, want the base URL", got) } if got := b.launchURL("g123"); !strings.Contains(got, "startapp=g123") { t.Errorf("launchURL = %q, want startapp=g123", got) } }