mirror of
https://github.com/larksuite/cli.git
synced 2026-07-08 10:08:02 +08:00
test: cover Execute clipboard branch via injectable readClipboardImage
Makes readClipboardImageBytes swappable in tests by routing the call through a package-level variable readClipboardImage. Tests inject a synthetic PNG payload so the full Execute clipboard flow (resolve → create block → upload in-memory bytes → bind) runs under unit test without a real pasteboard. Covers: - TestDocMediaInsertExecuteFromClipboard: end-to-end happy path - TestDocMediaInsertExecuteClipboardReadError: early-return on readClipboardImage() failure
This commit is contained in:
@@ -21,6 +21,10 @@ var alignMap = map[string]int{
|
|||||||
"right": 3,
|
"right": 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// readClipboardImage is the clipboard read function, swappable in tests to
|
||||||
|
// inject synthetic image bytes without depending on the host pasteboard.
|
||||||
|
var readClipboardImage = readClipboardImageBytes
|
||||||
|
|
||||||
var DocMediaInsert = common.Shortcut{
|
var DocMediaInsert = common.Shortcut{
|
||||||
Service: "docs",
|
Service: "docs",
|
||||||
Command: "+media-insert",
|
Command: "+media-insert",
|
||||||
@@ -112,7 +116,7 @@ var DocMediaInsert = common.Shortcut{
|
|||||||
if runtime.Bool("from-clipboard") {
|
if runtime.Bool("from-clipboard") {
|
||||||
fmt.Fprintf(runtime.IO().ErrOut, "Reading image from clipboard...\n")
|
fmt.Fprintf(runtime.IO().ErrOut, "Reading image from clipboard...\n")
|
||||||
var err error
|
var err error
|
||||||
clipboardContent, err = readClipboardImageBytes()
|
clipboardContent, err = readClipboardImage()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -350,6 +351,112 @@ func TestUploadDocMediaFileWithContentUsesMultipart(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDocMediaInsertExecuteFromClipboard(t *testing.T) {
|
||||||
|
// Covers the Execute clipboard branch end-to-end: read synthetic bytes,
|
||||||
|
// resolve docx root, create block, upload in-memory content, bind to block.
|
||||||
|
prev := readClipboardImage
|
||||||
|
t.Cleanup(func() { readClipboardImage = prev })
|
||||||
|
payload := []byte{0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0xAA, 0xBB}
|
||||||
|
readClipboardImage = func() ([]byte, error) { return payload, nil }
|
||||||
|
|
||||||
|
f, stdout, stderr, reg := cmdutil.TestFactory(t, docsTestConfigWithAppID("docs-clipboard-exec-app"))
|
||||||
|
documentID := "doxcnClipboardExec1"
|
||||||
|
|
||||||
|
// Step 1: GET root block
|
||||||
|
reg.Register(&httpmock.Stub{
|
||||||
|
Method: "GET",
|
||||||
|
URL: "/open-apis/docx/v1/documents/" + documentID + "/blocks/" + documentID,
|
||||||
|
Body: map[string]interface{}{
|
||||||
|
"code": 0, "msg": "ok",
|
||||||
|
"data": map[string]interface{}{
|
||||||
|
"block": map[string]interface{}{
|
||||||
|
"block_id": documentID,
|
||||||
|
"children": []interface{}{"existing_block"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
// Step 2: POST create child block
|
||||||
|
reg.Register(&httpmock.Stub{
|
||||||
|
Method: "POST",
|
||||||
|
URL: "/open-apis/docx/v1/documents/" + documentID + "/blocks/" + documentID + "/children",
|
||||||
|
Body: map[string]interface{}{
|
||||||
|
"code": 0, "msg": "ok",
|
||||||
|
"data": map[string]interface{}{
|
||||||
|
"children": []interface{}{
|
||||||
|
map[string]interface{}{"block_id": "new_image_block"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
// Step 3: POST upload_all for in-memory bytes
|
||||||
|
uploadStub := &httpmock.Stub{
|
||||||
|
Method: "POST",
|
||||||
|
URL: "/open-apis/drive/v1/medias/upload_all",
|
||||||
|
Body: map[string]interface{}{
|
||||||
|
"code": 0,
|
||||||
|
"data": map[string]interface{}{"file_token": "file_clip_abc"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
reg.Register(uploadStub)
|
||||||
|
// Step 4: PATCH batch_update
|
||||||
|
reg.Register(&httpmock.Stub{
|
||||||
|
Method: "PATCH",
|
||||||
|
URL: "/open-apis/docx/v1/documents/" + documentID + "/blocks/batch_update",
|
||||||
|
Body: map[string]interface{}{"code": 0, "msg": "ok"},
|
||||||
|
})
|
||||||
|
|
||||||
|
err := mountAndRunDocs(t, DocMediaInsert, []string{
|
||||||
|
"+media-insert",
|
||||||
|
"--doc", documentID,
|
||||||
|
"--from-clipboard",
|
||||||
|
"--as", "bot",
|
||||||
|
}, f, stdout)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v — stderr: %s", err, stderr.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// stderr should show clipboard read + file name "clipboard.png"
|
||||||
|
if !strings.Contains(stderr.String(), "Reading image from clipboard") {
|
||||||
|
t.Errorf("stderr missing clipboard-read log: %s", stderr.String())
|
||||||
|
}
|
||||||
|
if !strings.Contains(stderr.String(), "clipboard.png") {
|
||||||
|
t.Errorf("stderr missing clipboard.png file name: %s", stderr.String())
|
||||||
|
}
|
||||||
|
// stdout should include the file_token
|
||||||
|
if !strings.Contains(stdout.String(), "file_clip_abc") {
|
||||||
|
t.Errorf("stdout missing file_token: %s", stdout.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Upload multipart body should contain the synthetic payload bytes.
|
||||||
|
if !bytes.Contains(uploadStub.CapturedBody, payload) {
|
||||||
|
t.Errorf("upload body missing clipboard payload bytes")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDocMediaInsertExecuteClipboardReadError(t *testing.T) {
|
||||||
|
// Covers the early-return when clipboard read fails (no osascript etc).
|
||||||
|
prev := readClipboardImage
|
||||||
|
t.Cleanup(func() { readClipboardImage = prev })
|
||||||
|
readClipboardImage = func() ([]byte, error) {
|
||||||
|
return nil, fmt.Errorf("clipboard image upload is not supported on test")
|
||||||
|
}
|
||||||
|
|
||||||
|
f, _, _, _ := cmdutil.TestFactory(t, docsTestConfigWithAppID("docs-clipboard-err-app"))
|
||||||
|
err := mountAndRunDocs(t, DocMediaInsert, []string{
|
||||||
|
"+media-insert",
|
||||||
|
"--doc", "doxcnXXXXXXXXXXXXXXXXXX",
|
||||||
|
"--from-clipboard",
|
||||||
|
"--as", "bot",
|
||||||
|
}, f, nil)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expected clipboard read error, got nil")
|
||||||
|
}
|
||||||
|
if !strings.Contains(err.Error(), "clipboard image upload is not supported") {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestDocMediaInsertExecuteResolvesWikiBeforeFileCheck(t *testing.T) {
|
func TestDocMediaInsertExecuteResolvesWikiBeforeFileCheck(t *testing.T) {
|
||||||
f, _, stderr, reg := cmdutil.TestFactory(t, docsTestConfigWithAppID("docs-insert-exec-app"))
|
f, _, stderr, reg := cmdutil.TestFactory(t, docsTestConfigWithAppID("docs-insert-exec-app"))
|
||||||
reg.Register(&httpmock.Stub{
|
reg.Register(&httpmock.Stub{
|
||||||
|
|||||||
Reference in New Issue
Block a user