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:
baiqing
2026-04-18 20:55:09 +08:00
parent 210fb5c7af
commit 9dedb7ab2c
2 changed files with 112 additions and 1 deletions

View File

@@ -21,6 +21,10 @@ var alignMap = map[string]int{
"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{
Service: "docs",
Command: "+media-insert",
@@ -112,7 +116,7 @@ var DocMediaInsert = common.Shortcut{
if runtime.Bool("from-clipboard") {
fmt.Fprintf(runtime.IO().ErrOut, "Reading image from clipboard...\n")
var err error
clipboardContent, err = readClipboardImageBytes()
clipboardContent, err = readClipboardImage()
if err != nil {
return err
}

View File

@@ -7,6 +7,7 @@ import (
"bytes"
"context"
"encoding/json"
"fmt"
"net/http"
"os"
"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) {
f, _, stderr, reg := cmdutil.TestFactory(t, docsTestConfigWithAppID("docs-insert-exec-app"))
reg.Register(&httpmock.Stub{