Files
dingtalk-workspace-cli/internal/helpers/framework2_changed_lines_coverage_test.go

180 lines
6.4 KiB
Go

// Copyright 2026 Alibaba Group
// Licensed under the Apache License, Version 2.0 (the "License");
package helpers
import (
"bytes"
"context"
"errors"
"os"
"path/filepath"
"strings"
"testing"
"github.com/DingTalk-Real-AI/dingtalk-workspace-cli/internal/output"
"github.com/DingTalk-Real-AI/dingtalk-workspace-cli/pkg/edition"
"github.com/spf13/cobra"
)
func TestCrossPlatformCoverageFramework2HelperOutputEdges(t *testing.T) {
if err := writeCommandPayload(nil, map[string]any{"ok": true}); err != nil {
t.Fatalf("nil command payload: %v", err)
}
cmd := &cobra.Command{Use: "output"}
var stdout, stderr bytes.Buffer
cmd.SetOut(&stdout)
cmd.SetErr(&stderr)
if err := writeEnvelope(cmd, output.NewSuccessEnvelope(map[string]any{"id": "x"})); err != nil {
t.Fatalf("success envelope: %v", err)
}
if !strings.Contains(stdout.String(), `"outcome": "success"`) {
t.Fatalf("stdout=%q", stdout.String())
}
if err := writeEnvelope(nil, nil); err != nil {
t.Fatalf("nil failure envelope: %v", err)
}
f := NewFormatterWithWriters(nil, nil)
if f.w != os.Stdout || f.errW != os.Stderr {
t.Fatalf("nil writers did not use process defaults")
}
var nextOut, nextErr bytes.Buffer
f.SetWriters(&nextOut, nil)
f.SetWriters(nil, &nextErr)
if f.w != &nextOut || f.errW != &nextErr {
t.Fatalf("SetWriters did not replace each non-nil side")
}
}
func TestCrossPlatformCoverageFramework2MCPDataEdges(t *testing.T) {
original := deps
t.Cleanup(func() { deps = original })
InitDeps(&coverageErrorCaller{result: &edition.ToolResult{Content: []edition.ContentBlock{{Type: "text", Text: `{"id":"x"}`}}}})
data, err := CallMCPToolDataOnServer(nil, "dev", "get_thing", nil)
if err != nil || data.(map[string]any)["id"] != "x" {
t.Fatalf("decoded data=%#v err=%v", data, err)
}
InitDeps(&coverageErrorCaller{result: &edition.ToolResult{Content: []edition.ContentBlock{{Type: "text", Text: `{"count":7}`}}}})
data, err = CallMCPToolDataOnServer(context.Background(), "dev", "get_thing", nil)
if err != nil || data.(map[string]any)["count"] != float64(7) {
t.Fatalf("legacy float64 number data=%#v err=%v", data, err)
}
InitDeps(&coverageErrorCaller{err: errors.New("transport failed")})
if _, err := CallMCPToolDataOnServer(context.Background(), "dev", "get_thing", nil); err == nil {
t.Fatal("expected transport error")
}
InitDeps(&coverageErrorCaller{result: &edition.ToolResult{Content: []edition.ContentBlock{{Type: "text", Text: " "}}}})
data, err = CallMCPToolDataOnServer(context.Background(), "dev", "get_thing", nil)
if err != nil || len(data.(map[string]any)) != 0 {
t.Fatalf("empty response data=%#v err=%v", data, err)
}
InitDeps(&coverageErrorCaller{result: &edition.ToolResult{Content: []edition.ContentBlock{{Type: "text", Text: "{"}}}})
if _, err := CallMCPToolDataOnServer(context.Background(), "dev", "get_thing", nil); err == nil {
t.Fatal("expected invalid JSON error")
}
InitDeps(&coverageErrorCaller{result: &edition.ToolResult{Content: []edition.ContentBlock{{Type: "text", Text: `{} {}`}}}})
if _, err := CallMCPToolDataOnServer(context.Background(), "dev", "get_thing", nil); err == nil || !strings.Contains(err.Error(), "存在多个 JSON 值") {
t.Fatalf("multiple JSON values error = %v", err)
}
InitDeps(&coverageErrorCaller{result: &edition.ToolResult{Content: []edition.ContentBlock{{Type: "text", Text: `{} {`}}}})
if _, err := CallMCPToolDataOnServer(context.Background(), "dev", "get_thing", nil); err == nil || !strings.Contains(err.Error(), "解析 get_thing 返回失败") {
t.Fatalf("trailing invalid JSON error = %v", err)
}
}
func TestCrossPlatformCoverageFramework2LegacyTextAdapter(t *testing.T) {
original := deps
t.Cleanup(func() { deps = original })
caller := &coverageErrorCaller{}
InitDeps(caller)
var stdout bytes.Buffer
deps.Out = NewFormatterWithWriters(&stdout, &bytes.Buffer{})
if err := RenderLegacyMCPText("get_thing", `{"id":"x"}`); err != nil {
t.Fatalf("RenderLegacyMCPText: %v", err)
}
if !strings.Contains(stdout.String(), `"id": "x"`) {
t.Fatalf("stdout=%q", stdout.String())
}
}
func TestCrossPlatformCoverageFramework2LeafResultEdges(t *testing.T) {
mustPanic := func(name string, fn func()) {
t.Helper()
defer func() {
if recover() == nil {
t.Fatalf("%s: expected panic", name)
}
}()
fn()
}
resultCall := func(*cobra.Command, string, map[string]any) (output.CommandResult, error) {
return output.Success(map[string]any{"ok": true}), nil
}
mustPanic("metadata result call", func() {
DeclareLeafMetadata(&cobra.Command{Use: "meta"}, LeafSpec{ResultCall: resultCall})
})
mustPanic("two call styles", func() {
FromLeafSpec(LeafSpec{Use: "both", Call: func(*cobra.Command, string, map[string]any) error { return nil }, ResultCall: resultCall})
})
cmd := prepareUnifiedTestCommand(NewLeafCommand(LeafSpec{
Use: "result", Tool: "get_thing", OutputRollout: output.RolloutUnifiedActive, ResultCall: resultCall,
}))
cmd.SetOut(&bytes.Buffer{})
if err := cmd.Execute(); err != nil {
t.Fatalf("ResultCall command: %v", err)
}
}
func TestCrossPlatformCoverageFramework2DevDocRemainsLegacy(t *testing.T) {
cmd := newDevDocSearchCommand()
if got := output.CommandRollout(cmd); got != output.RolloutLegacyOnly {
t.Fatalf("dev doc rollout=%s, want legacy_only", got)
}
}
func TestCrossPlatformCoverageFramework2ConnectLegacyEdges(t *testing.T) {
original := connectDaemonDirOverride
t.Cleanup(func() { connectDaemonDirOverride = original })
blocked := filepath.Join(t.TempDir(), "blocked")
if err := os.WriteFile(blocked, []byte("x"), 0o600); err != nil {
t.Fatal(err)
}
connectDaemonDirOverride = blocked
stop := newDevAppRobotConnectStopCommand()
stop.Flags().Bool("yes", true, "")
if err := stop.Flags().Set("robot-client-id", "ding-test"); err != nil {
t.Fatal(err)
}
if err := stop.RunE(stop, nil); err == nil {
t.Fatal("expected daemon directory error")
}
connectDaemonDirOverride = t.TempDir()
list := newDevAppRobotConnectListCommand(nil)
output.SetCommandRollout(list, output.RolloutLegacyOnly)
if list.Flags().Lookup("format") == nil {
list.Flags().String("format", "table", "")
} else if err := list.Flags().Set("format", "table"); err != nil {
t.Fatal(err)
}
var stdout bytes.Buffer
list.SetOut(&stdout)
if err := list.RunE(list, nil); err != nil {
t.Fatalf("legacy list: %v", err)
}
if !strings.Contains(stdout.String(), "no connectors found") {
t.Fatalf("stdout=%q", stdout.String())
}
}