Move cmdcore to corecmd, declare attendance ContractFinal in helpers, keep Sheet destructive commands --yes-only, and align catalog/policy provenance. Co-authored-by: Cursor <cursoragent@cursor.com>
228 lines
7.7 KiB
Go
228 lines
7.7 KiB
Go
package helpers
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/DingTalk-Real-AI/dingtalk-workspace-cli/pkg/edition"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
type depthArgsRecordingCaller struct {
|
|
steps []scriptedToolStep
|
|
index int
|
|
calls []map[string]any
|
|
}
|
|
|
|
func (c *depthArgsRecordingCaller) CallTool(_ context.Context, _, _ string, args map[string]any) (*edition.ToolResult, error) {
|
|
c.calls = append(c.calls, args)
|
|
index := c.index
|
|
if index >= len(c.steps) {
|
|
index = len(c.steps) - 1
|
|
}
|
|
c.index++
|
|
return textToolResult(c.steps[index].text), nil
|
|
}
|
|
|
|
func (*depthArgsRecordingCaller) Format() string { return "json" }
|
|
func (*depthArgsRecordingCaller) DryRun() bool { return false }
|
|
func (*depthArgsRecordingCaller) Fields() string { return "" }
|
|
func (*depthArgsRecordingCaller) JQ() string { return "" }
|
|
|
|
func executeDriveCommand(t *testing.T, caller edition.ToolCaller, args ...string) error {
|
|
t.Helper()
|
|
previousDeps := deps
|
|
t.Cleanup(func() { deps = previousDeps })
|
|
InitDeps(caller)
|
|
deps.Out.w = io.Discard
|
|
deps.Out.errW = io.Discard
|
|
root := newDriveCommand()
|
|
root.SilenceErrors = true
|
|
root.SilenceUsage = true
|
|
root.SetArgs(args)
|
|
return root.Execute()
|
|
}
|
|
|
|
func TestCrossPlatformCoverageDriveListVersionsMode(t *testing.T) {
|
|
caller := &guardedMutationCaller{}
|
|
err := executeGuardedMutationCommand(t, caller, newDriveCommand,
|
|
"list", "--versions", "--node", "node-1", "--limit", "5", "--cursor", "cur-1")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(caller.calls) != 1 {
|
|
t.Fatalf("calls = %#v", caller.calls)
|
|
}
|
|
call := caller.calls[0]
|
|
if call.productID != "drive" || call.toolName != "list_file_versions" {
|
|
t.Fatalf("call = %#v", call)
|
|
}
|
|
if call.args["nodeId"] != "node-1" || call.args["maxResults"] != 5 || call.args["nextCursor"] != "cur-1" {
|
|
t.Fatalf("args = %#v", call.args)
|
|
}
|
|
}
|
|
|
|
func TestCrossPlatformCoverageDriveListVersionsModeRequiresNode(t *testing.T) {
|
|
caller := &guardedMutationCaller{}
|
|
err := executeGuardedMutationCommand(t, caller, newDriveCommand, "list", "--versions")
|
|
if err == nil {
|
|
t.Fatal("versions without --node returned nil")
|
|
}
|
|
if len(caller.calls) != 0 {
|
|
t.Fatalf("calls = %#v", caller.calls)
|
|
}
|
|
}
|
|
|
|
func TestCrossPlatformCoverageDriveListWorkspaceDepthRoutesDocBFS(t *testing.T) {
|
|
caller := &depthArgsRecordingCaller{steps: []scriptedToolStep{
|
|
{text: `{"nodes":[{"nodeId":"n1","name":"doc1","nodeType":"doc"}],"hasMore":false}`},
|
|
}}
|
|
err := executeDriveCommand(t, caller,
|
|
"list", "--workspace", "ws-1", "--depth", "2", "--node", "folder-1")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(caller.calls) != 1 {
|
|
t.Fatalf("calls = %#v, want 1", caller.calls)
|
|
}
|
|
args := caller.calls[0]
|
|
if args["workspaceId"] != "ws-1" || args["folderId"] != "folder-1" || args["pageSize"] != float64(docDepthPageSize) {
|
|
t.Fatalf("doc BFS args = %#v", args)
|
|
}
|
|
}
|
|
|
|
func TestCrossPlatformCoverageDriveListWorkspaceDepthRejectsNumericFolder(t *testing.T) {
|
|
caller := &guardedMutationCaller{}
|
|
err := executeGuardedMutationCommand(t, caller, newDriveCommand,
|
|
"list", "--workspace", "ws-1", "--depth", "2", "--node", "12345")
|
|
if err == nil {
|
|
t.Fatal("numeric doc folder returned nil")
|
|
}
|
|
}
|
|
|
|
func TestCrossPlatformCoverageDriveListPanDepthBuildsBaseArgs(t *testing.T) {
|
|
useDriveDepthArgs(t)
|
|
caller := &depthArgsRecordingCaller{steps: []scriptedToolStep{
|
|
{text: `{"items":[{"fileId":"f1","name":"a.txt","type":"FILE"}]}`},
|
|
}}
|
|
err := executeDriveCommand(t, caller,
|
|
"list", "--depth", "2", "--space-id", "sp-1", "--order-by", "name", "--order", "asc", "--thumbnail", "--folder", "root-folder")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(caller.calls) != 1 {
|
|
t.Fatalf("calls = %#v, want 1", caller.calls)
|
|
}
|
|
args := caller.calls[0]
|
|
if args["spaceId"] != "sp-1" || args["orderBy"] != "name" || args["order"] != "asc" ||
|
|
args["withThumbnail"] != true || args["parentId"] != "root-folder" || args["maxResults"] != float64(driveDepthPageSize) {
|
|
t.Fatalf("pan BFS args = %#v", args)
|
|
}
|
|
}
|
|
|
|
func TestCrossPlatformCoverageDriveListPanDepthRejectsNumericFolder(t *testing.T) {
|
|
caller := &guardedMutationCaller{}
|
|
err := executeGuardedMutationCommand(t, caller, newDriveCommand,
|
|
"list", "--depth", "2", "--folder", "12345")
|
|
if err == nil {
|
|
t.Fatal("numeric drive folder returned nil")
|
|
}
|
|
}
|
|
|
|
func TestCrossPlatformCoverageDriveTransferOwnerDryRun(t *testing.T) {
|
|
caller := &guardedMutationCaller{dryRun: true}
|
|
err := executeGuardedMutationCommand(t, caller, newDriveCommand,
|
|
"permission", "transfer-owner", "--node", "node-1", "--new-owner", "user-1", "--dry-run")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(caller.calls) != 0 {
|
|
t.Fatalf("dry-run calls = %#v", caller.calls)
|
|
}
|
|
}
|
|
|
|
func TestCrossPlatformCoverageDriveTransferOwnerYesRequiresRecursive(t *testing.T) {
|
|
caller := &guardedMutationCaller{}
|
|
err := executeGuardedMutationCommand(t, caller, newDriveCommand,
|
|
"permission", "transfer-owner", "--node", "node-1", "--new-owner", "user-1", "--reserve-role", "EDITOR", "--yes")
|
|
if err == nil || !strings.Contains(err.Error(), "--recursive is required") {
|
|
t.Fatalf("err = %v, want --recursive required", err)
|
|
}
|
|
}
|
|
|
|
func TestCrossPlatformCoverageDriveTransferOwnerWorkspaceTarget(t *testing.T) {
|
|
caller := &guardedMutationCaller{}
|
|
err := executeGuardedMutationCommand(t, caller, newDriveCommand,
|
|
"permission", "transfer-owner", "--workspace", "ws-1", "--new-owner", "user-1", "--reserve-role", "EDITOR", "--recursive", "--yes")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(caller.calls) != 1 {
|
|
t.Fatalf("calls = %#v", caller.calls)
|
|
}
|
|
call := caller.calls[0]
|
|
if call.productID != "doc" || call.toolName != "transfer_owner" {
|
|
t.Fatalf("call = %#v", call)
|
|
}
|
|
if call.args["workspaceId"] != "ws-1" || call.args["newOwnerId"] != "user-1" ||
|
|
call.args["reserveOldOwnerRole"] != "EDITOR" || call.args["recursiveChange"] != true {
|
|
t.Fatalf("args = %#v", call.args)
|
|
}
|
|
if _, ok := call.args["nodeId"]; ok {
|
|
t.Fatalf("unexpected nodeId in %#v", call.args)
|
|
}
|
|
}
|
|
|
|
func TestCrossPlatformCoverageDriveTransferOwnerDeclined(t *testing.T) {
|
|
caller := &guardedMutationCaller{}
|
|
root := newDriveCommand()
|
|
root.SetIn(strings.NewReader("no\n"))
|
|
err := executeGuardedMutationCommand(t, caller, func() *cobra.Command { return root },
|
|
"permission", "transfer-owner", "--node", "node-1", "--new-owner", "user-1")
|
|
if err == nil || !strings.Contains(err.Error(), "用户取消了操作") {
|
|
t.Fatalf("declined transfer error = %v, want 用户取消了操作", err)
|
|
}
|
|
if len(caller.calls) != 0 {
|
|
t.Fatalf("declined calls = %#v", caller.calls)
|
|
}
|
|
}
|
|
|
|
func TestCrossPlatformCoverageDriveCoverRequiresNode(t *testing.T) {
|
|
caller := &guardedMutationCaller{}
|
|
err := executeGuardedMutationCommand(t, caller, newDriveCommand, "cover")
|
|
if err == nil {
|
|
t.Fatal("cover without --node returned nil")
|
|
}
|
|
if len(caller.calls) != 0 {
|
|
t.Fatalf("calls = %#v", caller.calls)
|
|
}
|
|
}
|
|
|
|
func TestCrossPlatformCoverageDriveRevertDeclined(t *testing.T) {
|
|
caller := &guardedMutationCaller{}
|
|
root := newDriveCommand()
|
|
root.SetIn(strings.NewReader("no\n"))
|
|
err := executeGuardedMutationCommand(t, caller, func() *cobra.Command { return root },
|
|
"revert", "--node", "node-1", "--version", "3")
|
|
if err == nil || !strings.Contains(err.Error(), "用户取消了操作") {
|
|
t.Fatalf("declined revert error = %v, want 用户取消了操作", err)
|
|
}
|
|
if len(caller.calls) != 0 {
|
|
t.Fatalf("declined revert calls = %#v", caller.calls)
|
|
}
|
|
}
|
|
|
|
func TestCrossPlatformCoverageDriveTransferOwnerRejectsBothTargets(t *testing.T) {
|
|
caller := &guardedMutationCaller{}
|
|
err := executeGuardedMutationCommand(t, caller, newDriveCommand,
|
|
"permission", "transfer-owner", "--node", "node-1", "--workspace", "ws-1", "--new-owner", "user-1", "--yes")
|
|
if err == nil || !strings.Contains(err.Error(), "mutually exclusive") {
|
|
t.Fatalf("err = %v, want mutual exclusion", err)
|
|
}
|
|
if len(caller.calls) != 0 {
|
|
t.Fatalf("calls = %#v, want none", caller.calls)
|
|
}
|
|
}
|