FILE / ScuroNeko/Laniakea
tgrich/rich_103_test.go
Исходный файл и его история в репозитории.
Golang lint / lint (push) Failing after 1m37s
(fix): finalize v2 contracts (tests): cover v2 migration (doc): prepare release guidance
143 lines
5.8 KiB
Go
143 lines
5.8 KiB
Go
package tgrich
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"strings"
|
|
"testing"
|
|
|
|
"git.scuroneko.dev/scuroneko/laniakea/v2/tgapi"
|
|
)
|
|
|
|
func TestRich103HTML(t *testing.T) {
|
|
empty := ""
|
|
for _, tc := range []struct {
|
|
name string
|
|
button tgapi.RichMessageButton
|
|
fragment string
|
|
}{
|
|
{"url", tgapi.RichMessageButton{URL: "https://example.com/?a=1&b=2"}, `url="https://example.com/?a=1&b=2"`},
|
|
{"callback", tgapi.RichMessageButton{CallbackData: `a"<&`, Style: tgapi.RichMessageButtonStyleLink}, `data="a"<&"`},
|
|
{"web app", tgapi.RichMessageButton{WebApp: &tgapi.WebAppInfo{URL: "https://example.com"}}, `type="web_app"`},
|
|
{"login", tgapi.RichMessageButton{LoginURL: &tgapi.LoginURL{URL: "https://example.com", ForwardText: "Forward", RequestWriteAccess: true}}, `request-write-access`},
|
|
{"inline", tgapi.RichMessageButton{SwitchInlineQuery: &empty}, `query=""`},
|
|
{"current", tgapi.RichMessageButton{SwitchInlineQueryCurrentChat: &empty}, `type="switch_inline_query_current_chat"`},
|
|
{"chosen", tgapi.RichMessageButton{SwitchInlineQueryChosenChat: &tgapi.SwitchInlineQueryChosenChat{AllowUserChats: true}}, `allow-user-chats`},
|
|
{"copy", tgapi.RichMessageButton{CopyText: &tgapi.CopyTextButton{Text: "copy"}}, `text="copy"`},
|
|
{"disabled", tgapi.RichMessageButton{Disabled: &tgapi.DisabledButton{}}, `type="disabled"`},
|
|
} {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
tc.button.Text = Text("<Go>")
|
|
for _, block := range []tgapi.InputRichBlock{P(Button(tc.button)), ButtonsWithAlign([]tgapi.RichMessageButton{tc.button}, tgapi.RichBlockButtonCenter)} {
|
|
msg, err := BuildHTML(block)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !strings.Contains(msg.HTML, tc.fragment) || !strings.Contains(msg.HTML, "<Go></tg-button>") {
|
|
t.Fatalf("unexpected HTML: %s", msg.HTML)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
msg, err := BuildHTML(ExpandableBlockquoteWithCredit(Bold(Text("Quote")), Text("Author")), DocumentWithCaption(tgapi.InputMedia{Media: "attach://notes"}, Caption(Text("Notes"))), NewTable().SetCompact(true).Build())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, fragment := range []string{"<blockquote expandable><b>Quote</b><cite>Author</cite></blockquote>", `<tg-document src="tg://document?id=media_1"></tg-document>`, "<table compact>"} {
|
|
if !strings.Contains(msg.HTML, fragment) {
|
|
t.Fatalf("missing %s in %s", fragment, msg.HTML)
|
|
}
|
|
}
|
|
if len(msg.Media) != 1 || msg.Media[0].Media.Type != tgapi.InputMediaTypeDocument || msg.Media[0].Media.Media != "attach://notes" {
|
|
t.Fatalf("bad media: %#v", msg.Media)
|
|
}
|
|
if _, err := BuildDraftHTML(Document(tgapi.InputMedia{Media: "attach://notes"})); !errors.Is(err, tgapi.ErrRichMessageDraftUploadUnsupported) {
|
|
t.Fatalf("draft: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestRich103Validation(t *testing.T) {
|
|
good := tgapi.RichMessageButton{Text: Text("Go"), CallbackData: "x"}
|
|
for _, n := range []int{0, 1, 8, 9} {
|
|
buttons := make([]tgapi.RichMessageButton, n)
|
|
for i := range buttons {
|
|
buttons[i] = good
|
|
}
|
|
_, err := BuildHTML(Buttons(buttons))
|
|
if (err == nil) != (n >= 1 && n <= 8) {
|
|
t.Fatalf("row %d: %v", n, err)
|
|
}
|
|
}
|
|
for _, tc := range []struct {
|
|
name string
|
|
change func(*tgapi.RichMessageButton)
|
|
}{
|
|
{"no action", func(b *tgapi.RichMessageButton) { b.CallbackData = "" }},
|
|
{"two actions", func(b *tgapi.RichMessageButton) { b.URL = "https://example.com" }},
|
|
{"long callback", func(b *tgapi.RichMessageButton) { b.CallbackData = strings.Repeat("я", 33) }},
|
|
{"formatting", func(b *tgapi.RichMessageButton) { b.Text = Bold(Text("Go")) }},
|
|
{"style", func(b *tgapi.RichMessageButton) { b.Style = "disable" }},
|
|
{"link url", func(b *tgapi.RichMessageButton) { b.CallbackData = ""; b.URL = "https://example.com"; b.Style = "link" }},
|
|
{"login bot", func(b *tgapi.RichMessageButton) {
|
|
b.CallbackData = ""
|
|
b.LoginURL = &tgapi.LoginURL{URL: "https://example.com", BotUsername: "other"}
|
|
}},
|
|
} {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
b := good
|
|
tc.change(&b)
|
|
if _, err := BuildHTML(P(Button(b))); !errors.Is(err, ErrRichInvalidButton) {
|
|
t.Fatalf("got %v", err)
|
|
}
|
|
})
|
|
}
|
|
good.CallbackData = strings.Repeat("я", 32)
|
|
if _, err := BuildHTML(P(Button(good))); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := BuildHTML(ButtonsWithAlign([]tgapi.RichMessageButton{good}, "bottom")); !errors.Is(err, ErrRichInvalidButton) {
|
|
t.Fatalf("alignment: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestRich103InputJSON(t *testing.T) {
|
|
for _, block := range []tgapi.InputRichBlock{ExpandableBlockquote(Text("quote")), Document(tgapi.InputMedia{Media: "file"}), Buttons([]tgapi.RichMessageButton{{Text: Text("Off"), Disabled: &tgapi.DisabledButton{}}})} {
|
|
data, err := json.Marshal(block)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var fields map[string]json.RawMessage
|
|
if err := json.Unmarshal(data, &fields); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(fields["type"]) == 0 {
|
|
t.Fatalf("missing discriminator: %s", data)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestRichButtonLabelEntitiesAndLimits(t *testing.T) {
|
|
label := tgapi.RichTextArray{
|
|
Text("At "),
|
|
tgapi.RichTextDateTime{Text: Text("noon"), UnixTime: 1000, DateTimeFormat: "t"},
|
|
tgapi.RichTextCustomEmoji{CustomEmojiID: "123", AlternativeText: "!"},
|
|
}
|
|
if _, err := BuildHTML(P(Button(tgapi.RichMessageButton{Text: label, Disabled: &tgapi.DisabledButton{}}))); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, n := range []int{0, 1, 256, 257} {
|
|
_, err := BuildHTML(P(Button(tgapi.RichMessageButton{Text: Text("Copy"), CopyText: &tgapi.CopyTextButton{Text: strings.Repeat("я", n)}})))
|
|
if (err == nil) != (n >= 1 && n <= 256) {
|
|
t.Fatalf("copy length %d: %v", n, err)
|
|
}
|
|
}
|
|
for _, text := range []tgapi.RichText{
|
|
Bold(Text(strings.Repeat("я", maxRichTextChars+1))),
|
|
URL(Text(strings.Repeat("я", maxRichTextChars+1)), "https://example.com"),
|
|
} {
|
|
if _, err := BuildHTML(P(text)); !errors.Is(err, ErrRichTextTooLong) {
|
|
t.Fatalf("nested text bypassed limit: %v", err)
|
|
}
|
|
}
|
|
}
|