mirror of
https://github.com/larksuite/cli.git
synced 2026-07-07 09:11:44 +08:00
154 lines
3.7 KiB
Go
154 lines
3.7 KiB
Go
// Copyright (c) 2026 Lark Technologies Pte. Ltd.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package doctor
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"testing"
|
|
|
|
"github.com/spf13/cobra"
|
|
|
|
"github.com/larksuite/cli/internal/cmdutil"
|
|
"github.com/larksuite/cli/internal/core"
|
|
)
|
|
|
|
func TestNewCmdDoctor_FlagParsing(t *testing.T) {
|
|
f, _, _, _ := cmdutil.TestFactory(t, &core.CliConfig{
|
|
AppID: "test-app", AppSecret: "test-secret", Brand: core.BrandFeishu,
|
|
})
|
|
|
|
cmd := NewCmdDoctor(f)
|
|
cmd.SetArgs([]string{"--offline"})
|
|
|
|
// We only test flag parsing; skip actual execution by intercepting RunE.
|
|
var gotOffline bool
|
|
origRunE := cmd.RunE
|
|
cmd.RunE = func(cmd2 *cobra.Command, args []string) error {
|
|
v, _ := cmd2.Flags().GetBool("offline")
|
|
gotOffline = v
|
|
return nil
|
|
}
|
|
_ = origRunE
|
|
|
|
if err := cmd.Execute(); err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if !gotOffline {
|
|
t.Error("expected --offline to be true")
|
|
}
|
|
}
|
|
|
|
func TestFinishDoctor(t *testing.T) {
|
|
t.Run("all pass returns nil", func(t *testing.T) {
|
|
f, stdout, _, _ := cmdutil.TestFactory(t, nil)
|
|
checks := []checkResult{
|
|
pass("check1", "ok"),
|
|
skip("check2", "skipped"),
|
|
}
|
|
err := finishDoctor(f, checks)
|
|
if err != nil {
|
|
t.Fatalf("expected nil, got %v", err)
|
|
}
|
|
|
|
var result struct {
|
|
OK bool `json:"ok"`
|
|
}
|
|
json.Unmarshal(stdout.Bytes(), &result)
|
|
if !result.OK {
|
|
t.Error("expected ok=true")
|
|
}
|
|
})
|
|
|
|
t.Run("any fail returns error", func(t *testing.T) {
|
|
f, stdout, _, _ := cmdutil.TestFactory(t, nil)
|
|
checks := []checkResult{
|
|
pass("check1", "ok"),
|
|
fail("check2", "bad", "fix it"),
|
|
}
|
|
err := finishDoctor(f, checks)
|
|
if err == nil {
|
|
t.Fatal("expected error, got nil")
|
|
}
|
|
|
|
var result struct {
|
|
OK bool `json:"ok"`
|
|
}
|
|
json.Unmarshal(stdout.Bytes(), &result)
|
|
if result.OK {
|
|
t.Error("expected ok=false")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestNetworkChecks_Offline(t *testing.T) {
|
|
ep := core.Endpoints{Open: "https://open.feishu.cn", MCP: "https://mcp.feishu.cn"}
|
|
opts := &DoctorOptions{Ctx: context.Background(), Offline: true}
|
|
checks := networkChecks(opts.Ctx, opts, ep)
|
|
if len(checks) != 2 {
|
|
t.Fatalf("expected 2 checks, got %d", len(checks))
|
|
}
|
|
for _, c := range checks {
|
|
if c.Status != "skip" {
|
|
t.Errorf("expected skip, got %s for %s", c.Status, c.Name)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestDoctorRun_SplitsBotAndMissingUserIdentity(t *testing.T) {
|
|
t.Setenv("LARKSUITE_CLI_CONFIG_DIR", t.TempDir())
|
|
if err := core.SaveMultiAppConfig(&core.MultiAppConfig{
|
|
CurrentApp: "default",
|
|
Apps: []core.AppConfig{
|
|
{
|
|
Name: "default",
|
|
AppId: "test-app",
|
|
AppSecret: core.PlainSecret("secret"),
|
|
Brand: core.BrandFeishu,
|
|
},
|
|
},
|
|
}); err != nil {
|
|
t.Fatalf("SaveMultiAppConfig() error = %v", err)
|
|
}
|
|
|
|
f, stdout, _, _ := cmdutil.TestFactory(t, &core.CliConfig{
|
|
AppID: "test-app", AppSecret: "secret", Brand: core.BrandFeishu,
|
|
})
|
|
err := doctorRun(&DoctorOptions{
|
|
Factory: f,
|
|
Ctx: context.Background(),
|
|
Offline: true,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("doctorRun() error = %v", err)
|
|
}
|
|
|
|
var got struct {
|
|
OK bool `json:"ok"`
|
|
Checks []checkResult `json:"checks"`
|
|
}
|
|
if err := json.Unmarshal(stdout.Bytes(), &got); err != nil {
|
|
t.Fatalf("json.Unmarshal() error = %v", err)
|
|
}
|
|
if !got.OK {
|
|
t.Fatalf("ok = false, want true; checks = %#v", got.Checks)
|
|
}
|
|
assertCheck(t, got.Checks, "bot_identity", "pass")
|
|
assertCheck(t, got.Checks, "user_identity", "warn")
|
|
assertCheck(t, got.Checks, "identity_ready", "pass")
|
|
}
|
|
|
|
func assertCheck(t *testing.T, checks []checkResult, name, status string) {
|
|
t.Helper()
|
|
for _, check := range checks {
|
|
if check.Name == name {
|
|
if check.Status != status {
|
|
t.Fatalf("%s status = %q, want %q", name, check.Status, status)
|
|
}
|
|
return
|
|
}
|
|
}
|
|
t.Fatalf("check %q not found in %#v", name, checks)
|
|
}
|