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 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 := NewHandler(fakeResolver{}, "https://telesrv.net") for _, path := range []string{ "/addstickers/missing_pack", "/addstickers/bad-name", "/addemoji/%E4%B8%AD%E6%96%87", } { 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") }