Files
Enterprise-Knowledge-Base/cli/cmd/kb/list_test.go
T
nullkey cf84bf2a38 feat(cli): add whoami / doctor / kb / context commands (PR-7)
5 new leaf commands wired into the root tree:
  whoami      — simplified `auth status` (user_id + tenant_id only)
  doctor      — 4-item self-check (base_url / auth / server_version / cred_storage)
                with --offline / --no-cache flags + skip cascade + summary.all_passed
                防 agent 看到 envelope.ok=true 误判命令整体 success
  kb list     — list KBs (default updated_at desc; 0 KB → "(no knowledge bases)")
                tabwriter 4-col (ID/NAME/DOCS/UPDATED), display-width truncation
  kb get      — show single KB details (KEY: VALUE, suppress empty fields)
  context use — switch default context (writes config.current_context),
                带 levenshtein distance ≤ 2 的 did-you-mean hint

Each command uses the v0.0 narrow Service interface pattern (testable via
fakes), agent.SetAgentHelp for AI-friendly hints, and ClassifyHTTPError
for stable error code mapping.

cmdutil/errors.go: 新增 CodeLocalContextNotFound for `context use`,加入 AllCodes() 注册集.

cli/cmd/root.go: NewRootCmd 改为 exported (acceptance/contract 测试需要),
                 注册 4 个新命令 + 1 parent group; root_test.go 跟随更新.
2026-05-09 12:18:01 +08:00

63 lines
1.8 KiB
Go

package kb
import (
"context"
"strings"
"testing"
"time"
"github.com/Tencent/WeKnora/cli/internal/iostreams"
sdk "github.com/Tencent/WeKnora/client"
)
type fakeListSvc struct {
items []sdk.KnowledgeBase
err error
}
func (f *fakeListSvc) ListKnowledgeBases(ctx context.Context) ([]sdk.KnowledgeBase, error) {
return f.items, f.err
}
func TestList_Empty_Human(t *testing.T) {
out, _ := iostreams.SetForTest(t)
if err := runList(context.Background(), &ListOptions{}, &fakeListSvc{items: []sdk.KnowledgeBase{}}); err != nil {
t.Fatalf("runList: %v", err)
}
if !strings.Contains(out.String(), "(no knowledge bases)") {
t.Errorf("empty output expected '(no knowledge bases)', got %q", out.String())
}
}
func TestList_Empty_JSON(t *testing.T) {
out, _ := iostreams.SetForTest(t)
if err := runList(context.Background(), &ListOptions{JSONOut: true}, &fakeListSvc{items: []sdk.KnowledgeBase{}}); err != nil {
t.Fatalf("runList: %v", err)
}
got := out.String()
if !strings.Contains(got, `"items":[]`) {
t.Errorf("empty JSON should contain items:[], got %q", got)
}
if strings.Contains(got, `"items":null`) {
t.Error("items must be [] not null")
}
}
func TestList_NonEmpty_Human_RenderColumns(t *testing.T) {
out, _ := iostreams.SetForTest(t)
now := time.Now()
items := []sdk.KnowledgeBase{
{ID: "kb1", Name: "Marketing", KnowledgeCount: 5, UpdatedAt: now.Add(-3 * time.Hour)},
{ID: "kb2", Name: "Engineering", KnowledgeCount: 1, UpdatedAt: now.Add(-2 * 24 * time.Hour)},
}
if err := runList(context.Background(), &ListOptions{}, &fakeListSvc{items: items}); err != nil {
t.Fatalf("runList: %v", err)
}
got := out.String()
for _, want := range []string{"ID", "NAME", "DOCS", "UPDATED", "kb1", "Marketing", "5 docs", "kb2", "Engineering", "1 doc"} {
if !strings.Contains(got, want) {
t.Errorf("output missing %q in:\n%s", want, got)
}
}
}