Files
larksuite-cli/shortcuts/apps/plugin_common_test.go
2026-06-30 11:50:13 +08:00

254 lines
6.8 KiB
Go

// Copyright (c) 2026 Lark Technologies Pte. Ltd.
// SPDX-License-Identifier: MIT
package apps
import (
"encoding/json"
"os"
"path/filepath"
"testing"
"github.com/larksuite/cli/errs"
)
// --- pluginResolveProjectPath ---
func TestPluginResolveProjectPath_DefaultToCwd(t *testing.T) {
got, err := pluginResolveProjectPath("")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
cwd, _ := os.Getwd() //nolint:forbidigo
if got != cwd {
t.Errorf("got %q, want cwd %q", got, cwd)
}
}
func TestPluginResolveProjectPath_ExplicitPath(t *testing.T) {
got, err := pluginResolveProjectPath("/tmp/myapp")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if got != "/tmp/myapp" {
t.Errorf("got %q, want /tmp/myapp", got)
}
}
// --- pluginCheckProjectDir ---
func TestPluginCheckProjectDir_OK(t *testing.T) {
dir := t.TempDir()
if err := os.WriteFile(filepath.Join(dir, "package.json"), []byte("{}"), 0o644); err != nil { //nolint:forbidigo
t.Fatal(err)
}
if err := pluginCheckProjectDir(dir); err != nil {
t.Fatalf("unexpected error: %v", err)
}
}
func TestPluginCheckProjectDir_Missing(t *testing.T) {
dir := t.TempDir()
err := pluginCheckProjectDir(dir)
if err == nil {
t.Fatal("expected error")
}
p, ok := errs.ProblemOf(err)
if !ok {
t.Fatalf("expected typed error, got %T: %v", err, err)
}
if p.Subtype != errs.SubtypeFailedPrecondition {
t.Errorf("subtype = %q, want failed_precondition", p.Subtype)
}
}
// --- pluginResolveCapDir ---
func TestPluginResolveCapDir_EnvVar(t *testing.T) {
t.Setenv("MIAODA_CAPABILITIES_DIR", "envdir/caps")
got, err := pluginResolveCapDir("/proj")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if want := filepath.Join("/proj", "envdir/caps"); got != want {
t.Errorf("got %q, want %q", got, want)
}
}
func TestPluginResolveCapDir_AppTypeEnv(t *testing.T) {
t.Setenv("MIAODA_APP_TYPE", "2")
got, err := pluginResolveCapDir("/proj")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if want := filepath.Join("/proj", "server", "capabilities"); got != want {
t.Errorf("got %q, want %q", got, want)
}
}
func TestPluginResolveCapDir_AppTypeEnvShared(t *testing.T) {
t.Setenv("MIAODA_APP_TYPE", "6")
got, err := pluginResolveCapDir("/proj")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if want := filepath.Join("/proj", "shared", "capabilities"); got != want {
t.Errorf("got %q, want %q", got, want)
}
}
func TestPluginResolveCapDir_EnvLocal(t *testing.T) {
dir := t.TempDir()
if err := os.WriteFile(filepath.Join(dir, ".env.local"), []byte("MIAODA_APP_TYPE=2\n"), 0o644); err != nil { //nolint:forbidigo
t.Fatal(err)
}
got, err := pluginResolveCapDir(dir)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if want := filepath.Join(dir, "server", "capabilities"); got != want {
t.Errorf("got %q, want %q", got, want)
}
}
func TestPluginResolveCapDir_DetectServer(t *testing.T) {
dir := t.TempDir()
if err := os.MkdirAll(filepath.Join(dir, "server", "capabilities"), 0o755); err != nil { //nolint:forbidigo
t.Fatal(err)
}
got, err := pluginResolveCapDir(dir)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if want := filepath.Join(dir, "server", "capabilities"); got != want {
t.Errorf("got %q, want %q", got, want)
}
}
func TestPluginResolveCapDir_DetectShared(t *testing.T) {
dir := t.TempDir()
if err := os.MkdirAll(filepath.Join(dir, "shared", "capabilities"), 0o755); err != nil { //nolint:forbidigo
t.Fatal(err)
}
got, err := pluginResolveCapDir(dir)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if want := filepath.Join(dir, "shared", "capabilities"); got != want {
t.Errorf("got %q, want %q", got, want)
}
}
func TestPluginResolveCapDir_Ambiguous(t *testing.T) {
dir := t.TempDir()
if err := os.MkdirAll(filepath.Join(dir, "server", "capabilities"), 0o755); err != nil { //nolint:forbidigo
t.Fatal(err)
}
if err := os.MkdirAll(filepath.Join(dir, "shared", "capabilities"), 0o755); err != nil { //nolint:forbidigo
t.Fatal(err)
}
_, err := pluginResolveCapDir(dir)
if err == nil {
t.Fatal("expected ambiguous error")
}
p, ok := errs.ProblemOf(err)
if !ok {
t.Fatalf("expected typed error, got %T: %v", err, err)
}
if p.Subtype != errs.SubtypeFailedPrecondition {
t.Errorf("subtype = %q, want failed_precondition", p.Subtype)
}
}
func TestPluginResolveCapDir_NeitherExists_DefaultsToServer(t *testing.T) {
dir := t.TempDir()
got, err := pluginResolveCapDir(dir)
if err != nil {
t.Fatalf("should default to server/capabilities, got error: %v", err)
}
if want := filepath.Join(dir, "server", "capabilities"); got != want {
t.Errorf("got %q, want %q", got, want)
}
}
func TestPluginResolveCapDir_AppType3_UsesServer(t *testing.T) {
t.Setenv("MIAODA_APP_TYPE", "3")
got, err := pluginResolveCapDir("/proj")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if want := filepath.Join("/proj", "server", "capabilities"); got != want {
t.Errorf("got %q, want %q (appType=3 should use server)", got, want)
}
}
// --- pluginListCapabilities ---
func TestPluginListCapabilities_Empty(t *testing.T) {
dir := t.TempDir()
caps, err := pluginListCapabilities(dir)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if len(caps) != 0 {
t.Errorf("got %d caps, want 0", len(caps))
}
}
func TestPluginListCapabilities_DirNotExist(t *testing.T) {
caps, err := pluginListCapabilities("/nonexistent/path")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if caps != nil {
t.Errorf("got %v, want nil", caps)
}
}
func TestPluginListCapabilities_WithFiles(t *testing.T) {
dir := t.TempDir()
writeTestCapJSON(t, dir, "cap1.json", map[string]interface{}{"id": "cap1", "name": "Cap One"})
writeTestCapJSON(t, dir, "cap2.json", map[string]interface{}{"id": "cap2", "name": "Cap Two"})
// non-JSON file should be skipped
if err := os.WriteFile(filepath.Join(dir, "readme.txt"), []byte("ignore"), 0o644); err != nil { //nolint:forbidigo
t.Fatal(err)
}
caps, err := pluginListCapabilities(dir)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if len(caps) != 2 {
t.Fatalf("got %d caps, want 2", len(caps))
}
}
func TestPluginListCapabilities_SkipsMalformed(t *testing.T) {
dir := t.TempDir()
writeTestCapJSON(t, dir, "good.json", map[string]interface{}{"id": "good"})
if err := os.WriteFile(filepath.Join(dir, "bad.json"), []byte("not json"), 0o644); err != nil { //nolint:forbidigo
t.Fatal(err)
}
caps, err := pluginListCapabilities(dir)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if len(caps) != 1 {
t.Fatalf("got %d caps, want 1", len(caps))
}
}
// --- helpers ---
func writeTestCapJSON(t *testing.T, dir, filename string, data map[string]interface{}) {
t.Helper()
b, err := json.Marshal(data)
if err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(dir, filename), b, 0o644); err != nil { //nolint:forbidigo
t.Fatal(err)
}
}