230 lines
6.4 KiB
Go
230 lines
6.4 KiB
Go
package stickerlinks
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
|
|
"telesrv/internal/domain"
|
|
)
|
|
|
|
func TestHandlerServesStickerSetLandingPage(t *testing.T) {
|
|
resolver := fakeResolver{
|
|
"fresh_pack": {
|
|
ID: 10,
|
|
ShortName: "fresh_pack",
|
|
Title: "Fresh Pack",
|
|
Count: 2,
|
|
Kind: domain.StickerSetKindStickers,
|
|
},
|
|
}
|
|
rr := httptest.NewRecorder()
|
|
req := httptest.NewRequest(http.MethodGet, "/addstickers/fresh_pack", nil)
|
|
|
|
NewHandler(resolver, "https://telesrv.net/").ServeHTTP(rr, req)
|
|
|
|
if rr.Code != http.StatusOK {
|
|
t.Fatalf("status = %d, want 200; body=%s", rr.Code, rr.Body.String())
|
|
}
|
|
body := rr.Body.String()
|
|
for _, want := range []string{
|
|
"Fresh Pack",
|
|
"https://telesrv.net/addstickers/fresh_pack",
|
|
"telesrv://addstickers?set=fresh_pack",
|
|
"tg://addstickers?set=fresh_pack",
|
|
"Files are still fetched by the app through MTProto.",
|
|
} {
|
|
if !strings.Contains(body, want) {
|
|
t.Fatalf("body missing %q:\n%s", want, body)
|
|
}
|
|
}
|
|
if strings.Contains(body, `window.location.href = "tg://`) {
|
|
t.Fatalf("landing page must not auto-open tg:// and steal official Telegram:\n%s", body)
|
|
}
|
|
if strings.Contains(body, "/upload/getFile") {
|
|
t.Fatalf("landing page should not expose media download paths:\n%s", body)
|
|
}
|
|
}
|
|
|
|
func TestHandlerServesEmojiLandingPage(t *testing.T) {
|
|
resolver := fakeResolver{
|
|
"emoji_pack": {
|
|
ID: 11,
|
|
ShortName: "emoji_pack",
|
|
Title: "Emoji Pack",
|
|
Count: 1,
|
|
Kind: domain.StickerSetKindEmoji,
|
|
Emojis: true,
|
|
},
|
|
}
|
|
rr := httptest.NewRecorder()
|
|
req := httptest.NewRequest(http.MethodGet, "/addemoji/emoji_pack", nil)
|
|
|
|
NewHandler(resolver, "https://example.test/base").ServeHTTP(rr, req)
|
|
|
|
if rr.Code != http.StatusOK {
|
|
t.Fatalf("status = %d, want 200; body=%s", rr.Code, rr.Body.String())
|
|
}
|
|
body := rr.Body.String()
|
|
for _, want := range []string{
|
|
"custom emoji set",
|
|
"https://example.test/base/addemoji/emoji_pack",
|
|
"telesrv://addemoji?set=emoji_pack",
|
|
"tg://addemoji?set=emoji_pack",
|
|
} {
|
|
if !strings.Contains(body, want) {
|
|
t.Fatalf("body missing %q:\n%s", want, body)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestHandlerServesChatlistLandingPage(t *testing.T) {
|
|
rr := httptest.NewRecorder()
|
|
req := httptest.NewRequest(http.MethodGet, "/addlist/zNhytIbwRwjaC2GH", nil)
|
|
|
|
NewHandler(fakeResolver{}, "http://127.0.0.1:2401").ServeHTTP(rr, req)
|
|
|
|
if rr.Code != http.StatusOK {
|
|
t.Fatalf("status = %d, want 200; body=%s", rr.Code, rr.Body.String())
|
|
}
|
|
body := rr.Body.String()
|
|
for _, want := range []string{
|
|
"Shared Folder",
|
|
"http://127.0.0.1:2401/addlist/zNhytIbwRwjaC2GH",
|
|
"telesrv://addlist?slug=zNhytIbwRwjaC2GH",
|
|
"tg://addlist?slug=zNhytIbwRwjaC2GH",
|
|
"preview and add this shared folder",
|
|
} {
|
|
if !strings.Contains(body, want) {
|
|
t.Fatalf("body missing %q:\n%s", want, body)
|
|
}
|
|
}
|
|
if strings.Contains(body, `window.location.href = "tg://`) {
|
|
t.Fatalf("landing page must not auto-open tg:// and steal official Telegram:\n%s", body)
|
|
}
|
|
}
|
|
|
|
func TestHandlerServesBotUsernameLandingPage(t *testing.T) {
|
|
users := fakeUsers{
|
|
"tetrisbot": {
|
|
ID: 1001,
|
|
Username: "TetrisBot",
|
|
FirstName: "Tetris Bot",
|
|
Bot: true,
|
|
},
|
|
}
|
|
rr := httptest.NewRecorder()
|
|
req := httptest.NewRequest(http.MethodGet, "/TetrisBot", nil)
|
|
|
|
NewHandlerWithUsers(fakeResolver{}, users, "http://127.0.0.1:2401").ServeHTTP(rr, req)
|
|
|
|
if rr.Code != http.StatusOK {
|
|
t.Fatalf("status = %d, want 200; body=%s", rr.Code, rr.Body.String())
|
|
}
|
|
body := rr.Body.String()
|
|
for _, want := range []string{
|
|
"Tetris Bot",
|
|
"bot",
|
|
"@TetrisBot",
|
|
"http://127.0.0.1:2401/TetrisBot",
|
|
"telesrv://resolve?domain=TetrisBot",
|
|
"tg://resolve?domain=TetrisBot",
|
|
"start a chat with this bot",
|
|
} {
|
|
if !strings.Contains(body, want) {
|
|
t.Fatalf("body missing %q:\n%s", want, body)
|
|
}
|
|
}
|
|
if strings.Contains(body, `window.location.href = "tg://`) {
|
|
t.Fatalf("landing page must not auto-open tg:// and steal official Telegram:\n%s", body)
|
|
}
|
|
}
|
|
|
|
func TestHandlerRedirectsMismatchedKindToCanonicalURL(t *testing.T) {
|
|
resolver := fakeResolver{
|
|
"emoji_pack": {
|
|
ID: 11,
|
|
ShortName: "emoji_pack",
|
|
Title: "Emoji Pack",
|
|
Kind: domain.StickerSetKindEmoji,
|
|
Emojis: true,
|
|
},
|
|
}
|
|
rr := httptest.NewRecorder()
|
|
req := httptest.NewRequest(http.MethodGet, "/addstickers/emoji_pack", nil)
|
|
|
|
NewHandler(resolver, "https://telesrv.net").ServeHTTP(rr, req)
|
|
|
|
if rr.Code != http.StatusPermanentRedirect {
|
|
t.Fatalf("status = %d, want 308; body=%s", rr.Code, rr.Body.String())
|
|
}
|
|
if got, want := rr.Header().Get("Location"), "https://telesrv.net/addemoji/emoji_pack"; got != want {
|
|
t.Fatalf("Location = %q, want %q", got, want)
|
|
}
|
|
}
|
|
|
|
func TestHandlerNotFoundForMissingOrInvalidShortName(t *testing.T) {
|
|
handler := NewHandlerWithUsers(fakeResolver{}, fakeUsers{
|
|
"alice": {
|
|
ID: 2001,
|
|
Username: "Alice",
|
|
FirstName: "Alice",
|
|
},
|
|
}, "https://telesrv.net")
|
|
for _, path := range []string{
|
|
"/addstickers/missing_pack",
|
|
"/addstickers/bad-name",
|
|
"/addemoji/%E4%B8%AD%E6%96%87",
|
|
"/addlist/bad!slug",
|
|
"/addlist/%E4%B8%AD%E6%96%87",
|
|
"/MissingBot",
|
|
"/Alice",
|
|
"/bad-name-bot",
|
|
"/1stBot",
|
|
} {
|
|
rr := httptest.NewRecorder()
|
|
req := httptest.NewRequest(http.MethodGet, path, nil)
|
|
handler.ServeHTTP(rr, req)
|
|
if rr.Code != http.StatusNotFound {
|
|
t.Fatalf("%s status = %d, want 404", path, rr.Code)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestHandlerLookupErrorIsInternalServerError(t *testing.T) {
|
|
rr := httptest.NewRecorder()
|
|
req := httptest.NewRequest(http.MethodGet, "/addstickers/fresh_pack", nil)
|
|
|
|
NewHandler(errorResolver{}, "https://telesrv.net").ServeHTTP(rr, req)
|
|
|
|
if rr.Code != http.StatusInternalServerError {
|
|
t.Fatalf("status = %d, want 500", rr.Code)
|
|
}
|
|
}
|
|
|
|
type fakeResolver map[string]domain.StickerSet
|
|
|
|
func (f fakeResolver) ResolveStickerSet(_ context.Context, ref domain.StickerSetRef) (domain.StickerSet, []domain.Document, bool, error) {
|
|
set, ok := f[ref.ShortName]
|
|
if !ok {
|
|
return domain.StickerSet{}, nil, false, nil
|
|
}
|
|
docs := make([]domain.Document, set.Count)
|
|
return set, docs, true, nil
|
|
}
|
|
|
|
type errorResolver struct{}
|
|
|
|
func (errorResolver) ResolveStickerSet(context.Context, domain.StickerSetRef) (domain.StickerSet, []domain.Document, bool, error) {
|
|
return domain.StickerSet{}, nil, false, errors.New("boom")
|
|
}
|
|
|
|
type fakeUsers map[string]domain.User
|
|
|
|
func (f fakeUsers) ByUsername(_ context.Context, username string) (domain.User, bool, error) {
|
|
u, ok := f[strings.ToLower(strings.TrimPrefix(username, "@"))]
|
|
return u, ok, nil
|
|
}
|