Files
2026-06-02 23:14:41 +08:00

258 lines
6.6 KiB
Go

package config_matrix
import (
"os"
"path/filepath"
"strings"
"testing"
"github.com/chenhg5/cc-connect/config"
)
func writeConfig(t *testing.T, body string) string {
t.Helper()
path := filepath.Join(t.TempDir(), "config.toml")
if err := os.WriteFile(path, []byte(body), 0o644); err != nil {
t.Fatalf("write config: %v", err)
}
return path
}
func baseProjectTOML(extra string) string {
return `
data_dir = "` + filepath.ToSlash(os.TempDir()) + `/cc-connect-release-test"
` + extra + `
[[projects]]
name = "release"
[projects.agent]
type = "claudecode"
work_dir = "/tmp/cc-connect-release-work"
[[projects.platforms]]
type = "feishu"
app_id = "cli_release"
app_secret = "secret"
`
}
func TestReleaseConfig_ProjectDisplayOverridesGlobalFromLoadedConfig(t *testing.T) {
path := writeConfig(t, `
attachment_send = "off"
[display]
mode = "quiet"
card_mode = "rich"
thinking_messages = true
tool_messages = false
[[projects]]
name = "release"
reset_on_idle_mins = 0
[projects.display]
mode = "full"
card_mode = "legacy"
thinking_messages = false
tool_messages = true
thinking_max_len = 111
tool_max_len = 222
[projects.agent]
type = "claudecode"
work_dir = "/tmp/cc-connect-release-work"
[[projects.platforms]]
type = "feishu"
app_id = "cli_release"
app_secret = "secret"
`)
cfg, err := config.Load(path)
if err != nil {
t.Fatalf("Load() error = %v", err)
}
if cfg.AttachmentSend != "off" {
t.Fatalf("AttachmentSend = %q, want off", cfg.AttachmentSend)
}
if len(cfg.Projects) != 1 {
t.Fatalf("projects = %d, want 1", len(cfg.Projects))
}
proj := &cfg.Projects[0]
if proj.ResetOnIdleMins == nil || *proj.ResetOnIdleMins != 0 {
t.Fatalf("ResetOnIdleMins = %#v, want explicit 0", proj.ResetOnIdleMins)
}
mode, thinking, tools, thinkingMax, toolMax, _, _ := config.EffectiveDisplay(cfg, proj)
if mode != config.DisplayModeFull {
t.Fatalf("mode = %q, want project full override", mode)
}
if thinking {
t.Fatal("thinking_messages = true, want project override false")
}
if !tools {
t.Fatal("tool_messages = false, want project override true")
}
if thinkingMax != 111 || toolMax != 222 {
t.Fatalf("max lens = %d/%d, want 111/222", thinkingMax, toolMax)
}
if got := config.EffectiveCardMode(cfg, proj); got != "legacy" {
t.Fatalf("card mode = %q, want project legacy override", got)
}
}
func TestReleaseConfig_DefaultsKeepAttachmentsAndFullDisplayEnabled(t *testing.T) {
path := writeConfig(t, baseProjectTOML(""))
cfg, err := config.Load(path)
if err != nil {
t.Fatalf("Load() error = %v", err)
}
if cfg.AttachmentSend != "on" {
t.Fatalf("AttachmentSend = %q, want default on", cfg.AttachmentSend)
}
mode, thinking, tools, _, _, _, _ := config.EffectiveDisplay(cfg, &cfg.Projects[0])
if mode != config.DisplayModeFull || !thinking || !tools {
t.Fatalf("display = mode:%s thinking:%v tools:%v, want full/true/true", mode, thinking, tools)
}
if got := config.EffectiveCardMode(cfg, &cfg.Projects[0]); got != "legacy" {
t.Fatalf("card mode = %q, want default legacy", got)
}
}
func TestReleaseConfig_BehaviorControlSwitchesParseFromLoadedConfig(t *testing.T) {
path := writeConfig(t, `
[stream_preview]
enabled = false
disabled_platforms = ["feishu", "telegram"]
interval_ms = 250
min_delta_chars = 12
max_chars = 777
[[projects]]
name = "release"
show_context_indicator = false
reply_footer = false
disabled_commands = ["restart", "shell"]
[projects.display]
mode = "quiet"
card_mode = "rich"
thinking_messages = false
tool_messages = false
[projects.agent]
type = "claudecode"
work_dir = "/tmp/cc-connect-release-work"
[[projects.platforms]]
type = "feishu"
app_id = "cli_release"
app_secret = "secret"
`)
cfg, err := config.Load(path)
if err != nil {
t.Fatalf("Load() error = %v", err)
}
if cfg.StreamPreview.Enabled == nil || *cfg.StreamPreview.Enabled {
t.Fatalf("stream_preview.enabled = %#v, want false", cfg.StreamPreview.Enabled)
}
if got := strings.Join(cfg.StreamPreview.DisabledPlatforms, ","); got != "feishu,telegram" {
t.Fatalf("stream_preview.disabled_platforms = %#v", cfg.StreamPreview.DisabledPlatforms)
}
if cfg.StreamPreview.IntervalMs == nil || *cfg.StreamPreview.IntervalMs != 250 {
t.Fatalf("stream_preview.interval_ms = %#v, want 250", cfg.StreamPreview.IntervalMs)
}
if cfg.StreamPreview.MinDeltaChars == nil || *cfg.StreamPreview.MinDeltaChars != 12 {
t.Fatalf("stream_preview.min_delta_chars = %#v, want 12", cfg.StreamPreview.MinDeltaChars)
}
if cfg.StreamPreview.MaxChars == nil || *cfg.StreamPreview.MaxChars != 777 {
t.Fatalf("stream_preview.max_chars = %#v, want 777", cfg.StreamPreview.MaxChars)
}
proj := &cfg.Projects[0]
if proj.ShowContextIndicator == nil || *proj.ShowContextIndicator {
t.Fatalf("show_context_indicator = %#v, want false", proj.ShowContextIndicator)
}
if proj.ReplyFooter == nil || *proj.ReplyFooter {
t.Fatalf("reply_footer = %#v, want false", proj.ReplyFooter)
}
if strings.Join(proj.DisabledCommands, ",") != "restart,shell" {
t.Fatalf("disabled_commands = %#v", proj.DisabledCommands)
}
mode, thinking, tools, _, _, _, _ := config.EffectiveDisplay(cfg, proj)
if mode != config.DisplayModeQuiet || thinking || tools {
t.Fatalf("display = mode:%s thinking:%v tools:%v, want quiet/false/false", mode, thinking, tools)
}
if got := config.EffectiveCardMode(cfg, proj); got != "rich" {
t.Fatalf("card mode = %q, want rich", got)
}
}
func TestReleaseConfig_InvalidCriticalOptionsFailFast(t *testing.T) {
tests := []struct {
name string
toml string
wantErr string
}{
{
name: "invalid attachment send",
toml: baseProjectTOML(`
attachment_send = "maybe"
`),
wantErr: `attachment_send must be "on" or "off"`,
},
{
name: "invalid project display mode",
toml: `
[[projects]]
name = "release"
[projects.display]
mode = "verbose"
[projects.agent]
type = "claudecode"
work_dir = "/tmp/cc-connect-release-work"
[[projects.platforms]]
type = "feishu"
app_id = "cli_release"
app_secret = "secret"
`,
wantErr: `projects[0].display.mode must be "full", "compact", or "quiet"`,
},
{
name: "negative reset on idle",
toml: `
[[projects]]
name = "release"
reset_on_idle_mins = -1
[projects.agent]
type = "claudecode"
work_dir = "/tmp/cc-connect-release-work"
[[projects.platforms]]
type = "feishu"
app_id = "cli_release"
app_secret = "secret"
`,
wantErr: "reset_on_idle_mins must be >= 0",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, err := config.Load(writeConfig(t, tt.toml))
if err == nil {
t.Fatal("Load() error = nil, want validation error")
}
if !strings.Contains(err.Error(), tt.wantErr) {
t.Fatalf("Load() error = %q, want contains %q", err.Error(), tt.wantErr)
}
})
}
}