Skip to content

Commit ff3a162

Browse files
ernadoclaude
andcommitted
test: cover edit-media, command scopes, leave-chat and option builders
Exercise EditMessageMedia (photo/doc by URL), LeaveChat, every BotCommandScope via SetMyCommands, and the remaining option builders (callback URL/cache-time, profile-photo offset/limit, ban until/revoke, force/no-edit game score). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 2b1d7f3 commit ff3a162

1 file changed

Lines changed: 149 additions & 0 deletions

File tree

methods_misc_test.go

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
package botapi
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"github.com/gotd/td/tg"
8+
)
9+
10+
func TestEditMessageMediaPhotoURL(t *testing.T) {
11+
inv := newMockInvoker()
12+
inv.reply(tg.MessagesEditMessageRequestTypeID, editUpdates(&tg.Message{ID: 5, PeerID: &tg.PeerUser{UserID: 10}}))
13+
b := newMockBot(inv)
14+
15+
media := &InputMediaPhoto{Media: FileURL("https://e/p.jpg"), Caption: "cap"}
16+
if _, err := b.EditMessageMedia(context.Background(), userRef(10, 20), 5, media); err != nil {
17+
t.Fatalf("EditMessageMedia: %v", err)
18+
}
19+
var req tg.MessagesEditMessageRequest
20+
inv.decode(t, tg.MessagesEditMessageRequestTypeID, &req)
21+
if _, ok := req.Media.(*tg.InputMediaPhotoExternal); !ok {
22+
t.Fatalf("media = %#v", req.Media)
23+
}
24+
}
25+
26+
func TestEditMessageMediaDocumentURL(t *testing.T) {
27+
inv := newMockInvoker()
28+
inv.reply(tg.MessagesEditMessageRequestTypeID, editUpdates(&tg.Message{ID: 5, PeerID: &tg.PeerUser{UserID: 10}}))
29+
b := newMockBot(inv)
30+
31+
media := &InputMediaDocument{Media: FileURL("https://e/f.pdf")}
32+
if _, err := b.EditMessageMedia(context.Background(), userRef(10, 20), 5, media); err != nil {
33+
t.Fatalf("EditMessageMedia doc: %v", err)
34+
}
35+
}
36+
37+
func TestLeaveChat(t *testing.T) {
38+
inv := newMockInvoker()
39+
inv.reply(tg.ChannelsLeaveChannelRequestTypeID, okUpdates())
40+
b := newMockBot(inv)
41+
42+
if err := b.LeaveChat(context.Background(), tdlibChannel(50)); err != nil {
43+
t.Fatalf("LeaveChat: %v", err)
44+
}
45+
if !inv.called(tg.ChannelsLeaveChannelRequestTypeID) {
46+
t.Fatal("expected channels.leaveChannel")
47+
}
48+
}
49+
50+
func TestSetMyCommandsScopes(t *testing.T) {
51+
scopes := []BotCommandScope{
52+
BotCommandScopeDefault(),
53+
BotCommandScopeAllPrivateChats(),
54+
BotCommandScopeAllGroupChats(),
55+
BotCommandScopeAllChatAdministrators(),
56+
BotCommandScopeChat(tdlibChannel(50)),
57+
BotCommandScopeChatAdministrators(tdlibChannel(50)),
58+
BotCommandScopeChatMember(tdlibChannel(50), 99),
59+
}
60+
for _, scope := range scopes {
61+
inv := newMockInvoker()
62+
inv.reply(tg.BotsSetBotCommandsRequestTypeID, &tg.BoolTrue{})
63+
b := newMockBot(inv)
64+
cmds := []BotCommand{{Command: "start", Description: "Start"}}
65+
err := b.SetMyCommands(context.Background(), cmds,
66+
WithCommandScope(scope), WithLanguageCode("en"))
67+
if err != nil {
68+
t.Fatalf("SetMyCommands(%T): %v", scope, err)
69+
}
70+
var req tg.BotsSetBotCommandsRequest
71+
inv.decode(t, tg.BotsSetBotCommandsRequestTypeID, &req)
72+
if req.LangCode != "en" {
73+
t.Fatalf("lang = %q", req.LangCode)
74+
}
75+
}
76+
}
77+
78+
// TestOptionBuildersApply exercises the option constructors that other tests do
79+
// not cover, by checking their effect on the produced MTProto request.
80+
func TestCallbackOptionBuilders(t *testing.T) {
81+
inv := newMockInvoker()
82+
inv.reply(tg.MessagesSetBotCallbackAnswerRequestTypeID, &tg.BoolTrue{})
83+
b := newMockBot(inv)
84+
85+
err := b.AnswerCallbackQuery(context.Background(), "12",
86+
WithCallbackURL("https://t.me/x"), WithCallbackCacheTime(30))
87+
if err != nil {
88+
t.Fatalf("AnswerCallbackQuery: %v", err)
89+
}
90+
var req tg.MessagesSetBotCallbackAnswerRequest
91+
inv.decode(t, tg.MessagesSetBotCallbackAnswerRequestTypeID, &req)
92+
if req.URL != "https://t.me/x" || req.CacheTime != 30 {
93+
t.Fatalf("req = %#v", req)
94+
}
95+
}
96+
97+
func TestGetUserProfilePhotosOptions(t *testing.T) {
98+
inv := newMockInvoker()
99+
inv.reply(tg.PhotosGetUserPhotosRequestTypeID, &tg.PhotosPhotos{
100+
Users: []tg.UserClass{&tg.User{ID: 99, AccessHash: 1}},
101+
})
102+
b := newMockBot(inv)
103+
104+
_, err := b.GetUserProfilePhotos(context.Background(), 99,
105+
WithProfilePhotosOffset(5), WithProfilePhotosLimit(10))
106+
if err != nil {
107+
t.Fatalf("GetUserProfilePhotos: %v", err)
108+
}
109+
var req tg.PhotosGetUserPhotosRequest
110+
inv.decode(t, tg.PhotosGetUserPhotosRequestTypeID, &req)
111+
if req.Offset != 5 || req.Limit != 10 {
112+
t.Fatalf("req = %#v", req)
113+
}
114+
}
115+
116+
func TestBanChatMemberOptions(t *testing.T) {
117+
inv := newMockInvoker()
118+
inv.reply(tg.ChannelsEditBannedRequestTypeID, okUpdates())
119+
inv.reply(tg.ChannelsDeleteParticipantHistoryRequestTypeID, &tg.MessagesAffectedHistory{})
120+
b := newMockBot(inv)
121+
122+
err := b.BanChatMember(context.Background(), tdlibChannel(50), 99,
123+
WithBanUntil(1700000000), WithRevokeMessages())
124+
if err != nil {
125+
t.Fatalf("BanChatMember: %v", err)
126+
}
127+
var req tg.ChannelsEditBannedRequest
128+
inv.decode(t, tg.ChannelsEditBannedRequestTypeID, &req)
129+
if req.BannedRights.UntilDate != 1700000000 {
130+
t.Fatalf("until = %d", req.BannedRights.UntilDate)
131+
}
132+
}
133+
134+
func TestSetGameScoreOptions(t *testing.T) {
135+
inv := newMockInvoker()
136+
inv.reply(tg.MessagesSetGameScoreRequestTypeID, editUpdates(&tg.Message{ID: 5, PeerID: &tg.PeerUser{UserID: 10}}))
137+
b := newMockBot(inv)
138+
139+
_, err := b.SetGameScore(context.Background(), userRef(10, 20), 5, 99, 1000,
140+
WithForceScore(), WithoutEditMessage())
141+
if err != nil {
142+
t.Fatalf("SetGameScore: %v", err)
143+
}
144+
var req tg.MessagesSetGameScoreRequest
145+
inv.decode(t, tg.MessagesSetGameScoreRequestTypeID, &req)
146+
if !req.Force || req.EditMessage {
147+
t.Fatalf("req = %#v", req)
148+
}
149+
}

0 commit comments

Comments
 (0)