mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-06-12 18:08:54 +00:00
test(message): cover pico and weixin media text semantics
This commit is contained in:
@@ -835,6 +835,75 @@ func TestSendMedia_DismissesTrackedToolFeedbackMessage(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSendMedia_IncludesCaptionAndAttachmentsInSinglePayload(t *testing.T) {
|
||||
ch := newTestPicoChannel(t)
|
||||
store := media.NewFileMediaStore()
|
||||
ch.SetMediaStore(store)
|
||||
|
||||
if err := ch.Start(context.Background()); err != nil {
|
||||
t.Fatalf("Start() error = %v", err)
|
||||
}
|
||||
defer ch.Stop(context.Background())
|
||||
|
||||
clientConn, received, cleanup := newTestPicoWebSocket(t)
|
||||
defer cleanup()
|
||||
ch.addConnForTest(&picoConn{id: "conn-1", conn: clientConn, sessionID: "sess-1"})
|
||||
|
||||
localPath := filepath.Join(t.TempDir(), "photo.png")
|
||||
if err := os.WriteFile(localPath, []byte("png-body"), 0o600); err != nil {
|
||||
t.Fatalf("WriteFile() error = %v", err)
|
||||
}
|
||||
|
||||
ref, err := store.Store(localPath, media.MediaMeta{
|
||||
Filename: "photo.png",
|
||||
ContentType: "image/png",
|
||||
}, "test-scope")
|
||||
if err != nil {
|
||||
t.Fatalf("Store() error = %v", err)
|
||||
}
|
||||
|
||||
_, err = ch.SendMedia(context.Background(), bus.OutboundMediaMessage{
|
||||
ChatID: "pico:sess-1",
|
||||
Parts: []bus.MediaPart{{
|
||||
Ref: ref,
|
||||
Type: "image",
|
||||
Filename: "photo.png",
|
||||
ContentType: "image/png",
|
||||
Caption: "recipe translation",
|
||||
}},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("SendMedia() error = %v", err)
|
||||
}
|
||||
|
||||
select {
|
||||
case msg := <-received:
|
||||
if msg.Type != TypeMessageCreate {
|
||||
t.Fatalf("message type = %q, want %q", msg.Type, TypeMessageCreate)
|
||||
}
|
||||
payload := msg.Payload
|
||||
if got := payload[PayloadKeyContent]; got != "recipe translation" {
|
||||
t.Fatalf("content = %#v, want %q", got, "recipe translation")
|
||||
}
|
||||
rawAttachments, ok := payload["attachments"].([]any)
|
||||
if !ok || len(rawAttachments) != 1 {
|
||||
t.Fatalf("attachments = %#v, want 1 attachment", payload["attachments"])
|
||||
}
|
||||
attachment, ok := rawAttachments[0].(map[string]any)
|
||||
if !ok {
|
||||
t.Fatalf("attachment = %#v, want map", rawAttachments[0])
|
||||
}
|
||||
if got := attachment["type"]; got != "image" {
|
||||
t.Fatalf("attachment type = %#v, want image", got)
|
||||
}
|
||||
if got := attachment["filename"]; got != "photo.png" {
|
||||
t.Fatalf("attachment filename = %#v, want photo.png", got)
|
||||
}
|
||||
case <-time.After(time.Second):
|
||||
t.Fatal("expected media payload to be delivered")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPicoDownloadURLForRef(t *testing.T) {
|
||||
got, err := picoDownloadURLForRef("media://attachment-1")
|
||||
if err != nil {
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"net/http"
|
||||
@@ -319,3 +320,61 @@ func TestSelectInboundMediaItemFallsBackToRefMessage(t *testing.T) {
|
||||
t.Fatalf("selectInboundMediaItem().Type = %d, want %d", item.Type, MessageItemTypeImage)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSendUploadedMedia_SendsCaptionAsSeparateTextBeforeMedia(t *testing.T) {
|
||||
var requests []SendMessageReq
|
||||
ch := &WeixinChannel{
|
||||
api: &ApiClient{
|
||||
BaseURL: "https://ilinkai.weixin.qq.com/",
|
||||
HttpClient: &http.Client{Transport: roundTripFunc(func(r *http.Request) (*http.Response, error) {
|
||||
if r.URL.Path != "/ilink/bot/sendmessage" {
|
||||
t.Fatalf("sendmessage path = %q, want /ilink/bot/sendmessage", r.URL.Path)
|
||||
}
|
||||
var req SendMessageReq
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
t.Fatalf("decode sendmessage req: %v", err)
|
||||
}
|
||||
requests = append(requests, req)
|
||||
return &http.Response{
|
||||
StatusCode: http.StatusOK,
|
||||
Body: io.NopCloser(bytes.NewReader([]byte(`{"ret":0,"errcode":0}`))),
|
||||
Header: make(http.Header),
|
||||
}, nil
|
||||
})},
|
||||
},
|
||||
typingCache: make(map[string]typingTicketCacheEntry),
|
||||
}
|
||||
|
||||
err := ch.sendUploadedMedia(
|
||||
context.Background(),
|
||||
"user-1",
|
||||
"ctx-1",
|
||||
"recipe translation",
|
||||
UploadMediaTypeImage,
|
||||
&uploadedFileInfo{
|
||||
downloadParam: "download-token",
|
||||
aesKeyHex: "31323334353637383930616263646566",
|
||||
fileSize: 11,
|
||||
cipherSize: 16,
|
||||
filename: "photo.png",
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("sendUploadedMedia() error = %v", err)
|
||||
}
|
||||
if len(requests) != 2 {
|
||||
t.Fatalf("sendUploadedMedia() sent %d requests, want 2", len(requests))
|
||||
}
|
||||
if len(requests[0].Msg.ItemList) != 1 || requests[0].Msg.ItemList[0].Type != MessageItemTypeText {
|
||||
t.Fatalf("first request item = %+v, want text item", requests[0].Msg.ItemList)
|
||||
}
|
||||
if got := requests[0].Msg.ItemList[0].TextItem.Text; got != "recipe translation" {
|
||||
t.Fatalf("first request text = %q, want recipe translation", got)
|
||||
}
|
||||
if len(requests[1].Msg.ItemList) != 1 || requests[1].Msg.ItemList[0].Type != MessageItemTypeImage {
|
||||
t.Fatalf("second request item = %+v, want image item", requests[1].Msg.ItemList)
|
||||
}
|
||||
if requests[1].Msg.ItemList[0].ImageItem == nil || requests[1].Msg.ItemList[0].ImageItem.Media == nil {
|
||||
t.Fatalf("second request image media = %+v, want media ref", requests[1].Msg.ItemList[0].ImageItem)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user