feat: return real tenant URLs for drive +upload and markdown +create (#992)

Change-Id: I6b513eef57a3479c8971b3bb6cbf005cad3f8040
This commit is contained in:
wangweiming-01
2026-05-21 11:07:37 +08:00
committed by GitHub
parent 3bab9a0692
commit e19e09019c
9 changed files with 263 additions and 54 deletions

View File

@@ -3,29 +3,61 @@
package common
// FetchDriveMetaTitle looks up the document title via the drive metas batch_query API.
func FetchDriveMetaTitle(runtime *RuntimeContext, token, docType string) (string, error) {
// DriveMeta is the subset of drive metas/batch_query fields used by shortcuts.
type DriveMeta struct {
Title string
URL string
}
// FetchDriveMeta looks up document metadata via the drive metas batch_query API.
func FetchDriveMeta(runtime *RuntimeContext, token, docType string, withURL bool) (DriveMeta, error) {
body := map[string]interface{}{
"request_docs": []map[string]interface{}{
{
"doc_token": token,
"doc_type": docType,
},
},
}
if withURL {
body["with_url"] = true
}
data, err := runtime.CallAPI(
"POST",
"/open-apis/drive/v1/metas/batch_query",
nil,
map[string]interface{}{
"request_docs": []map[string]interface{}{
{
"doc_token": token,
"doc_type": docType,
},
},
},
body,
)
if err != nil {
return "", err
return DriveMeta{}, err
}
metas := GetSlice(data, "metas")
if len(metas) == 0 {
return "", nil
return DriveMeta{}, nil
}
meta, _ := metas[0].(map[string]interface{})
return GetString(meta, "title"), nil
return DriveMeta{
Title: GetString(meta, "title"),
URL: GetString(meta, "url"),
}, nil
}
// FetchDriveMetaTitle looks up the document title via the drive metas batch_query API.
func FetchDriveMetaTitle(runtime *RuntimeContext, token, docType string) (string, error) {
meta, err := FetchDriveMeta(runtime, token, docType, false)
if err != nil {
return "", err
}
return meta.Title, nil
}
// FetchDriveMetaURL looks up the document access URL via the drive metas batch_query API.
func FetchDriveMetaURL(runtime *RuntimeContext, token, docType string) (string, error) {
meta, err := FetchDriveMeta(runtime, token, docType, true)
if err != nil {
return "", err
}
return meta.URL, nil
}

View File

@@ -5,6 +5,7 @@ package common
import (
"context"
"encoding/json"
"fmt"
"sync/atomic"
"testing"
@@ -105,6 +106,44 @@ func TestFetchDriveMetaTitle(t *testing.T) {
})
}
func TestFetchDriveMetaURL(t *testing.T) {
runtime, reg := newDriveMetaTestRuntime(t)
stub := &httpmock.Stub{
Method: "POST",
URL: "/open-apis/drive/v1/metas/batch_query",
Body: map[string]interface{}{
"code": 0,
"data": map[string]interface{}{
"metas": []map[string]interface{}{
{
"doc_token": "boxcnABC",
"doc_type": "file",
"title": "report.pdf",
"url": "https://tenant.example.com/file/boxcnABC",
},
},
},
},
}
reg.Register(stub)
got, err := FetchDriveMetaURL(runtime, "boxcnABC", "file")
if err != nil {
t.Fatalf("FetchDriveMetaURL() error: %v", err)
}
if got != "https://tenant.example.com/file/boxcnABC" {
t.Fatalf("url = %q, want tenant URL", got)
}
var body map[string]interface{}
if err := json.Unmarshal(stub.CapturedBody, &body); err != nil {
t.Fatalf("decode captured body: %v", err)
}
if body["with_url"] != true {
t.Fatalf("with_url = %#v, want true", body["with_url"])
}
}
func newDriveMetaTestRuntime(t *testing.T) (*RuntimeContext, *httpmock.Registry) {
t.Helper()
t.Setenv("LARKSUITE_CLI_CONFIG_DIR", t.TempDir())

View File

@@ -604,9 +604,9 @@ func TestDriveUploadSmallFileToWiki(t *testing.T) {
}
}
func TestDriveUploadFallbackURLForExplorerParent(t *testing.T) {
func TestDriveUploadUsesMetaURLForExplorerParent(t *testing.T) {
uploadTestConfig := &core.CliConfig{
AppID: "drive-upload-explorer-fallback-url", AppSecret: "test-secret", Brand: core.BrandFeishu,
AppID: "drive-upload-explorer-meta-url", AppSecret: "test-secret", Brand: core.BrandFeishu,
}
f, stdout, _, reg := cmdutil.TestFactory(t, uploadTestConfig)
@@ -615,12 +615,21 @@ func TestDriveUploadFallbackURLForExplorerParent(t *testing.T) {
URL: "/open-apis/drive/v1/files/upload_all",
Body: map[string]interface{}{
"code": 0, "msg": "ok",
// upload_all only ever returns file_token; url is never present —
// this exercises the fallback path unconditionally for explorer
// parents.
"data": map[string]interface{}{"file_token": "file_explorer_small"},
},
})
reg.Register(&httpmock.Stub{
Method: "POST",
URL: "/open-apis/drive/v1/metas/batch_query",
Body: map[string]interface{}{
"code": 0, "msg": "ok",
"data": map[string]interface{}{
"metas": []map[string]interface{}{
{"doc_token": "file_explorer_small", "doc_type": "file", "url": "https://tenant.example.com/file/file_explorer_small"},
},
},
},
})
tmpDir := t.TempDir()
origDir, _ := os.Getwd()
@@ -641,14 +650,14 @@ func TestDriveUploadFallbackURLForExplorerParent(t *testing.T) {
}
data := decodeDriveEnvelope(t, stdout)
if got, want := data["url"], "https://www.feishu.cn/file/file_explorer_small"; got != want {
t.Fatalf("data.url = %#v, want %q (brand-standard fallback)", got, want)
if got, want := data["url"], "https://tenant.example.com/file/file_explorer_small"; got != want {
t.Fatalf("data.url = %#v, want %q (metadata URL)", got, want)
}
}
func TestDriveUploadOmitsURLForWikiParent(t *testing.T) {
func TestDriveUploadUsesMetaURLForWikiParent(t *testing.T) {
uploadTestConfig := &core.CliConfig{
AppID: "drive-upload-wiki-no-url", AppSecret: "test-secret", Brand: core.BrandFeishu,
AppID: "drive-upload-wiki-meta-url", AppSecret: "test-secret", Brand: core.BrandFeishu,
}
f, stdout, _, reg := cmdutil.TestFactory(t, uploadTestConfig)
@@ -660,6 +669,18 @@ func TestDriveUploadOmitsURLForWikiParent(t *testing.T) {
"data": map[string]interface{}{"file_token": "file_wiki_small"},
},
})
reg.Register(&httpmock.Stub{
Method: "POST",
URL: "/open-apis/drive/v1/metas/batch_query",
Body: map[string]interface{}{
"code": 0, "msg": "ok",
"data": map[string]interface{}{
"metas": []map[string]interface{}{
{"doc_token": "file_wiki_small", "doc_type": "file", "url": "https://tenant.example.com/file/file_wiki_small"},
},
},
},
})
tmpDir := t.TempDir()
withDriveWorkingDir(t, tmpDir)
@@ -677,8 +698,8 @@ func TestDriveUploadOmitsURLForWikiParent(t *testing.T) {
}
data := decodeDriveEnvelope(t, stdout)
if _, ok := data["url"]; ok {
t.Fatalf("data.url should be omitted for wiki-hosted files (no standalone URL); got %#v", data["url"])
if got, want := data["url"], "https://tenant.example.com/file/file_wiki_small"; got != want {
t.Fatalf("data.url = %#v, want %q (metadata URL)", got, want)
}
}
@@ -1078,14 +1099,15 @@ func TestDriveUploadDryRunUsesWikiTarget(t *testing.T) {
var got struct {
API []struct {
URL string `json:"url"`
Body map[string]interface{} `json:"body"`
} `json:"api"`
}
if err := json.Unmarshal(data, &got); err != nil {
t.Fatalf("unmarshal dry run json: %v", err)
}
if len(got.API) != 1 {
t.Fatalf("expected 1 API call, got %d", len(got.API))
if len(got.API) != 2 {
t.Fatalf("expected 2 API calls, got %d", len(got.API))
}
if got.API[0].Body["parent_type"] != driveUploadParentTypeWiki {
t.Fatalf("parent_type = %#v, want %q", got.API[0].Body["parent_type"], driveUploadParentTypeWiki)
@@ -1093,6 +1115,12 @@ func TestDriveUploadDryRunUsesWikiTarget(t *testing.T) {
if got.API[0].Body["parent_node"] != "wikcn_dryrun_upload_target" {
t.Fatalf("parent_node = %#v, want %q", got.API[0].Body["parent_node"], "wikcn_dryrun_upload_target")
}
if got.API[1].URL != "/open-apis/drive/v1/metas/batch_query" {
t.Fatalf("metadata URL = %q, want metas/batch_query", got.API[1].URL)
}
if got.API[1].Body["with_url"] != true {
t.Fatalf("metadata with_url = %#v, want true", got.API[1].Body["with_url"])
}
}
func TestNewDriveUploadSpecPreservesPathAndName(t *testing.T) {
@@ -1168,18 +1196,25 @@ func TestDriveUploadDryRunIncludesFileToken(t *testing.T) {
var got struct {
API []struct {
URL string `json:"url"`
Body map[string]interface{} `json:"body"`
} `json:"api"`
}
if err := json.Unmarshal(data, &got); err != nil {
t.Fatalf("unmarshal dry run json: %v", err)
}
if len(got.API) != 1 {
t.Fatalf("expected 1 API call, got %d", len(got.API))
if len(got.API) != 2 {
t.Fatalf("expected 2 API calls, got %d", len(got.API))
}
if got.API[0].Body["file_token"] != "boxcn_dryrun_overwrite" {
t.Fatalf("file_token = %#v, want %q", got.API[0].Body["file_token"], "boxcn_dryrun_overwrite")
}
if got.API[1].URL != "/open-apis/drive/v1/metas/batch_query" {
t.Fatalf("metadata URL = %q, want metas/batch_query", got.API[1].URL)
}
if got.API[1].Body["with_url"] != true {
t.Fatalf("metadata with_url = %#v, want true", got.API[1].Body["with_url"])
}
}
func TestDriveUploadDryRunBotOverwriteSkipsPermissionGrantHint(t *testing.T) {
@@ -1222,8 +1257,8 @@ func TestDriveUploadDryRunBotOverwriteSkipsPermissionGrantHint(t *testing.T) {
if err := json.Unmarshal(data, &got); err != nil {
t.Fatalf("unmarshal dry run json: %v", err)
}
if len(got.API) != 1 {
t.Fatalf("expected 1 API call, got %d", len(got.API))
if len(got.API) != 2 {
t.Fatalf("expected 2 API calls, got %d", len(got.API))
}
if got.API[0].Body["file_token"] != "boxcn_dryrun_overwrite" {
t.Fatalf("file_token = %#v, want %q", got.API[0].Body["file_token"], "boxcn_dryrun_overwrite")

View File

@@ -92,7 +92,7 @@ var DriveUpload = common.Shortcut{
Command: "+upload",
Description: "Upload a local file to Drive",
Risk: "write",
Scopes: []string{"drive:file:upload"},
Scopes: []string{"drive:file:upload", "drive:drive.metadata:readonly"},
AuthTypes: []string{"user", "bot"},
Flags: []common.Flag{
{Name: "file", Desc: "local file path (files > 20MB use multipart upload automatically)", Required: true},
@@ -124,11 +124,22 @@ var DriveUpload = common.Shortcut{
body["file_token"] = spec.FileToken
}
d := common.NewDryRunAPI().
Desc("multipart/form-data upload (files > 20MB use chunked 3-step upload)").
Desc("multipart/form-data upload (files > 20MB use chunked 3-step upload), then fetch the real Drive URL via metadata").
POST("/open-apis/drive/v1/files/upload_all").
Body(body)
d.POST("/open-apis/drive/v1/metas/batch_query").
Desc("Fetch the uploaded file's real access URL").
Body(map[string]interface{}{
"request_docs": []map[string]interface{}{
{
"doc_token": "<file_token from upload response>",
"doc_type": "file",
},
},
"with_url": true,
})
if runtime.IsBot() && !isOverwrite {
d.Desc("After file upload succeeds in bot mode, the CLI will also try to grant the current CLI user full_access (可管理权限) on the new file.")
d.Set("post_upload_note", "After file upload succeeds in bot mode, the CLI will also try to grant the current CLI user full_access (可管理权限) on the new file.")
}
return d
},
@@ -165,13 +176,10 @@ var DriveUpload = common.Shortcut{
if uploadResult.Version != "" {
out["version"] = uploadResult.Version
}
// wiki-hosted files have no standalone /file/<token> URL — only the
// wiki node URL, which the upload response doesn't carry. Skip the
// fallback for parent_type=wiki rather than emit a link that 404s.
if target.ParentType == driveUploadParentTypeExplorer {
if u := common.BuildResourceURL(runtime.Config.Brand, "file", uploadResult.FileToken); u != "" {
out["url"] = u
}
if u, metaErr := common.FetchDriveMetaURL(runtime, uploadResult.FileToken, "file"); metaErr == nil && strings.TrimSpace(u) != "" {
out["url"] = u
} else if metaErr != nil {
fmt.Fprintf(runtime.IO().ErrOut, "warning: uploaded file URL lookup failed: %v\n", metaErr)
}
if !isOverwrite {
if grant := common.AutoGrantCurrentUserDrivePermission(runtime, uploadResult.FileToken, "file"); grant != nil {

View File

@@ -5,6 +5,7 @@ package markdown
import (
"context"
"fmt"
"io"
"strings"
@@ -16,7 +17,7 @@ var MarkdownCreate = common.Shortcut{
Command: "+create",
Description: "Create a Markdown file in Drive",
Risk: "write",
Scopes: []string{"drive:file:upload"},
Scopes: []string{"drive:file:upload", "drive:drive.metadata:readonly"},
AuthTypes: []string{"user", "bot"},
HasFormat: true,
Flags: []common.Flag{
@@ -55,7 +56,19 @@ var MarkdownCreate = common.Shortcut{
if err != nil {
return common.NewDryRunAPI().Set("error", err.Error())
}
return markdownUploadDryRun(spec, fileSize, fileSize > markdownSinglePartSizeLimit)
dry := markdownUploadDryRun(spec, fileSize, fileSize > markdownSinglePartSizeLimit)
dry.POST("/open-apis/drive/v1/metas/batch_query").
Desc("Fetch the created Markdown file's real access URL").
Body(map[string]interface{}{
"request_docs": []map[string]interface{}{
{
"doc_token": "<file_token from upload response>",
"doc_type": "file",
},
},
"with_url": true,
})
return dry
},
Execute: func(ctx context.Context, runtime *common.RuntimeContext) error {
spec := markdownUploadSpec{
@@ -87,10 +100,10 @@ var MarkdownCreate = common.Shortcut{
"file_name": finalMarkdownFileName(spec),
"size_bytes": fileSize,
}
if target := spec.Target(); target.ParentType == markdownUploadParentTypeExplorer {
if u := common.BuildResourceURL(runtime.Config.Brand, "file", result.FileToken); u != "" {
out["url"] = u
}
if u, metaErr := common.FetchDriveMetaURL(runtime, result.FileToken, "file"); metaErr == nil && strings.TrimSpace(u) != "" {
out["url"] = u
} else if metaErr != nil {
fmt.Fprintf(runtime.IO().ErrOut, "warning: created Markdown file URL lookup failed: %v\n", metaErr)
}
if grant := common.AutoGrantCurrentUserDrivePermission(runtime, result.FileToken, "file"); grant != nil {
out["permission_grant"] = grant

View File

@@ -403,6 +403,9 @@ func TestMarkdownCreateDryRunWithInlineContent(t *testing.T) {
if !strings.Contains(out, "/open-apis/drive/v1/files/upload_all") {
t.Fatalf("dry-run missing upload_all: %s", out)
}
if !strings.Contains(out, "/open-apis/drive/v1/metas/batch_query") || !strings.Contains(out, `"with_url": true`) {
t.Fatalf("dry-run missing metadata URL lookup: %s", out)
}
if !strings.Contains(out, "markdown content") {
t.Fatalf("dry-run missing content marker: %s", out)
}
@@ -429,6 +432,9 @@ func TestMarkdownCreateDryRunWithWikiToken(t *testing.T) {
if !strings.Contains(out, `"parent_node": "wikcn_markdown_dryrun_target"`) {
t.Fatalf("dry-run missing wiki parent_node: %s", out)
}
if !strings.Contains(out, "/open-apis/drive/v1/metas/batch_query") || !strings.Contains(out, `"with_url": true`) {
t.Fatalf("dry-run missing metadata URL lookup: %s", out)
}
}
func TestMarkdownCreateDryRunReportsSourceFileError(t *testing.T) {
@@ -470,6 +476,9 @@ func TestMarkdownCreateDryRunWithFileUsesStatOnly(t *testing.T) {
if !strings.Contains(out, "/open-apis/drive/v1/files/upload_prepare") {
t.Fatalf("dry-run missing multipart prepare step: %s", out)
}
if !strings.Contains(out, "/open-apis/drive/v1/metas/batch_query") || !strings.Contains(out, `"with_url": true`) {
t.Fatalf("dry-run missing metadata URL lookup: %s", out)
}
if strings.Contains(out, "open should not be called in dry-run") {
t.Fatalf("dry-run unexpectedly tried to open the source file: %s", out)
}
@@ -489,6 +498,18 @@ func TestMarkdownCreateSuccessUploadAll(t *testing.T) {
},
}
reg.Register(uploadStub)
reg.Register(&httpmock.Stub{
Method: "POST",
URL: "/open-apis/drive/v1/metas/batch_query",
Body: map[string]interface{}{
"code": 0,
"data": map[string]interface{}{
"metas": []map[string]interface{}{
{"doc_token": "box_md_create", "doc_type": "file", "url": "https://tenant.example.com/file/box_md_create"},
},
},
},
})
err := mountAndRunMarkdown(t, MarkdownCreate, []string{
"+create",
@@ -521,12 +542,12 @@ func TestMarkdownCreateSuccessUploadAll(t *testing.T) {
if !strings.Contains(stdout.String(), `"file_name": "README.md"`) {
t.Fatalf("stdout missing file_name: %s", stdout.String())
}
if !strings.Contains(stdout.String(), `"url": "https://www.feishu.cn/file/box_md_create"`) {
if !strings.Contains(stdout.String(), `"url": "https://tenant.example.com/file/box_md_create"`) {
t.Fatalf("stdout missing url: %s", stdout.String())
}
}
func TestMarkdownCreateSuccessUploadAllToWikiOmitsURL(t *testing.T) {
func TestMarkdownCreateSuccessUploadAllToWikiReturnsMetaURL(t *testing.T) {
f, stdout, _, reg := cmdutil.TestFactory(t, markdownTestConfig())
uploadStub := &httpmock.Stub{
Method: "POST",
@@ -540,6 +561,18 @@ func TestMarkdownCreateSuccessUploadAllToWikiOmitsURL(t *testing.T) {
},
}
reg.Register(uploadStub)
reg.Register(&httpmock.Stub{
Method: "POST",
URL: "/open-apis/drive/v1/metas/batch_query",
Body: map[string]interface{}{
"code": 0,
"data": map[string]interface{}{
"metas": []map[string]interface{}{
{"doc_token": "box_md_create_wiki", "doc_type": "file", "url": "https://tenant.example.com/file/box_md_create_wiki"},
},
},
},
})
err := mountAndRunMarkdown(t, MarkdownCreate, []string{
"+create",
@@ -558,8 +591,8 @@ func TestMarkdownCreateSuccessUploadAllToWikiOmitsURL(t *testing.T) {
if got := body.Fields["parent_node"]; got != "wikcn_markdown_create_target" {
t.Fatalf("parent_node = %q, want %q", got, "wikcn_markdown_create_target")
}
if strings.Contains(stdout.String(), `"url":`) {
t.Fatalf("stdout should omit url for wiki-hosted markdown files: %s", stdout.String())
if !strings.Contains(stdout.String(), `"url": "https://tenant.example.com/file/box_md_create_wiki"`) {
t.Fatalf("stdout missing metadata url for wiki-hosted markdown file: %s", stdout.String())
}
}
@@ -575,6 +608,18 @@ func TestMarkdownCreatePrettyOutputIncludesPermissionGrant(t *testing.T) {
},
},
})
reg.Register(&httpmock.Stub{
Method: "POST",
URL: "/open-apis/drive/v1/metas/batch_query",
Body: map[string]interface{}{
"code": 0,
"data": map[string]interface{}{
"metas": []map[string]interface{}{
{"doc_token": "box_md_create_pretty", "doc_type": "file", "url": "https://tenant.example.com/file/box_md_create_pretty"},
},
},
},
})
err := mountAndRunMarkdown(t, MarkdownCreate, []string{
"+create",
@@ -591,7 +636,7 @@ func TestMarkdownCreatePrettyOutputIncludesPermissionGrant(t *testing.T) {
if !strings.Contains(out, "file_token: box_md_create_pretty") {
t.Fatalf("pretty output missing file_token: %s", out)
}
if !strings.Contains(out, "url: https://www.feishu.cn/file/box_md_create_pretty") {
if !strings.Contains(out, "url: https://tenant.example.com/file/box_md_create_pretty") {
t.Fatalf("pretty output missing url: %s", out)
}
if !strings.Contains(out, "permission_grant.status: skipped") {
@@ -649,6 +694,18 @@ func TestMarkdownCreateMultipartUploadSuccess(t *testing.T) {
},
},
})
reg.Register(&httpmock.Stub{
Method: "POST",
URL: "/open-apis/drive/v1/metas/batch_query",
Body: map[string]interface{}{
"code": 0,
"data": map[string]interface{}{
"metas": []map[string]interface{}{
{"doc_token": "box_md_multipart", "doc_type": "file", "url": "https://tenant.example.com/file/box_md_multipart"},
},
},
},
})
tmpDir := t.TempDir()
withMarkdownWorkingDir(t, tmpDir)
@@ -677,6 +734,9 @@ func TestMarkdownCreateMultipartUploadSuccess(t *testing.T) {
if !strings.Contains(stdout.String(), `"file_token": "box_md_multipart"`) {
t.Fatalf("stdout missing multipart file_token: %s", stdout.String())
}
if !strings.Contains(stdout.String(), `"url": "https://tenant.example.com/file/box_md_multipart"`) {
t.Fatalf("stdout missing multipart metadata url: %s", stdout.String())
}
}
func TestMarkdownCreateMultipartUploadToWikiUsesWikiParent(t *testing.T) {
@@ -715,6 +775,18 @@ func TestMarkdownCreateMultipartUploadToWikiUsesWikiParent(t *testing.T) {
},
},
})
reg.Register(&httpmock.Stub{
Method: "POST",
URL: "/open-apis/drive/v1/metas/batch_query",
Body: map[string]interface{}{
"code": 0,
"data": map[string]interface{}{
"metas": []map[string]interface{}{
{"doc_token": "box_md_multipart_wiki", "doc_type": "file", "url": "https://tenant.example.com/file/box_md_multipart_wiki"},
},
},
},
})
tmpDir := t.TempDir()
withMarkdownWorkingDir(t, tmpDir)
@@ -749,8 +821,8 @@ func TestMarkdownCreateMultipartUploadToWikiUsesWikiParent(t *testing.T) {
if got := body["parent_node"]; got != "wikcn_markdown_multipart_target" {
t.Fatalf("parent_node = %#v, want %q", got, "wikcn_markdown_multipart_target")
}
if strings.Contains(stdout.String(), `"url":`) {
t.Fatalf("stdout should omit url for wiki-hosted multipart markdown files: %s", stdout.String())
if !strings.Contains(stdout.String(), `"url": "https://tenant.example.com/file/box_md_multipart_wiki"`) {
t.Fatalf("stdout missing metadata url for wiki-hosted multipart markdown file: %s", stdout.String())
}
}

View File

@@ -34,6 +34,8 @@ func TestDriveUploadDryRun_WikiTarget(t *testing.T) {
output := strings.TrimSpace(result.Stdout)
assert.Contains(t, output, "/open-apis/drive/v1/files/upload_all")
assert.Contains(t, output, "/open-apis/drive/v1/metas/batch_query")
assert.Contains(t, output, `"with_url": true`)
assert.Contains(t, output, "parent_type")
assert.Contains(t, output, "parent_node")
assert.Contains(t, output, "wikcnDryRunUploadTarget")
@@ -61,6 +63,8 @@ func TestDriveUploadDryRun_WithFileToken(t *testing.T) {
output := strings.TrimSpace(result.Stdout)
assert.Contains(t, output, "/open-apis/drive/v1/files/upload_all")
assert.Contains(t, output, "/open-apis/drive/v1/metas/batch_query")
assert.Contains(t, output, `"with_url": true`)
assert.Contains(t, output, `"parent_node": "fldDryRunUploadTarget"`)
assert.Contains(t, output, `"file_token": "boxcnDryRunOverwriteTarget"`)
}

View File

@@ -37,6 +37,8 @@ func TestMarkdownCreateDryRun_Content(t *testing.T) {
output := strings.TrimSpace(result.Stdout)
assert.Contains(t, output, "/open-apis/drive/v1/files/upload_all")
assert.Contains(t, output, "/open-apis/drive/v1/metas/batch_query")
assert.Contains(t, output, `"with_url": true`)
assert.Contains(t, output, `"file_name": "README.md"`)
assert.Contains(t, output, `"parent_node": "fldcnMarkdownDryRun"`)
assert.Contains(t, output, `"parent_type": "explorer"`)
@@ -64,6 +66,8 @@ func TestMarkdownCreateDryRun_WikiTarget(t *testing.T) {
output := strings.TrimSpace(result.Stdout)
assert.Contains(t, output, "/open-apis/drive/v1/files/upload_all")
assert.Contains(t, output, "/open-apis/drive/v1/metas/batch_query")
assert.Contains(t, output, `"with_url": true`)
assert.Contains(t, output, `"file_name": "README.md"`)
assert.Contains(t, output, `"parent_node": "wikcnMarkdownDryRun"`)
assert.Contains(t, output, `"parent_type": "wiki"`)
@@ -94,6 +98,8 @@ func TestMarkdownCreateDryRun_FileShowsConcreteSize(t *testing.T) {
output := strings.TrimSpace(result.Stdout)
assert.Contains(t, output, "/open-apis/drive/v1/files/upload_all")
assert.Contains(t, output, "/open-apis/drive/v1/metas/batch_query")
assert.Contains(t, output, `"with_url": true`)
assert.Contains(t, output, `"file": "@note.md"`)
assert.Contains(t, output, `"size": 5`)
}

View File

@@ -217,7 +217,7 @@ func TestMarkdownCreateWorkflow_WikiParent(t *testing.T) {
fileToken := gjson.Get(createResult.Stdout, "data.file_token").String()
require.NotEmpty(t, fileToken, "stdout:\n%s", createResult.Stdout)
require.False(t, gjson.Get(createResult.Stdout, "data.url").Exists(), "stdout:\n%s", createResult.Stdout)
require.NotEmpty(t, gjson.Get(createResult.Stdout, "data.url").String(), "stdout:\n%s", createResult.Stdout)
parentT.Cleanup(func() {
requireDeleteWikiHostedMarkdownFile(parentT, fileToken)