| 1 | package config |
| 2 | |
| 3 | import ( |
| 4 | "fmt" |
| 5 | "strings" |
| 6 | "testing" |
| 7 | ) |
| 8 | |
| 9 | func TestScopedRenderSeparatesUserAndProjectConfig(t *testing.T) { |
| 10 | c := Default() |
| 11 | c.Language = "zh" |
| 12 | c.Desktop.Language = "zh" |
| 13 | c.Desktop.Currency = "CNY" |
| 14 | c.Desktop.Theme = "dark" |
| 15 | c.Desktop.ThemeStyle = "graphite" |
| 16 | c.Desktop.CloseBehavior = "background" |
| 17 | c.Desktop.StatusBarStyle = "text" |
| 18 | c.Desktop.StatusBarStyleInitialized = true |
| 19 | c.Desktop.DefaultToolApprovalMode = "workspace-write" |
| 20 | c.Desktop.CheckUpdates = boolPtr(false) |
| 21 | c.Desktop.UpdateChannel = "preview" |
| 22 | c.Agent.RecoveryModel = "deepseek-pro" |
| 23 | c.Agent.RecoveryTemperature = 0.2 |
| 24 | |
| 25 | user := RenderTOMLForScope(c, RenderScopeUser) |
| 26 | for _, want := range []string{fmt.Sprintf("config_version = %d", Default().ConfigVersion), "[desktop]", `currency = "CNY"`, "[billing]", `display_currency = "CNY"`, `theme = "dark"`, `terminal_theme = "auto"`, `close_behavior = "background"`, `status_bar_style = "text"`, `default_tool_approval_mode = "workspace-write"`, `check_updates = false`, "[notifications]", "[tools.shell]"} { |
| 27 | if !strings.Contains(user, want) { |
| 28 | t.Fatalf("user render missing %q:\n%s", want, user) |
| 29 | } |
| 30 | } |
| 31 | if strings.Contains(user, "update_channel") || strings.Contains(user, "[cli]") { |
| 32 | t.Fatalf("user render retained retired update channel:\n%s", user) |
| 33 | } |
| 34 | |
| 35 | project := RenderTOMLForScope(c, RenderScopeProject) |
| 36 | for _, forbidden := range []string{"[desktop]", "[notifications]", "close_behavior =", "default_tool_approval_mode =", "default_auto_recovery_checkpoint =", "check_updates =", "update_channel =", "max_steps", "planner_max_steps"} { |
| 37 | if strings.Contains(project, forbidden) { |
| 38 | t.Fatalf("project render should not contain %q:\n%s", forbidden, project) |
| 39 | } |
| 40 | } |
| 41 | for _, retired := range []string{"default_auto_recovery_checkpoint", "auto_recovery_checkpoint"} { |
| 42 | if strings.Contains(user, retired) || strings.Contains(project, retired) { |
| 43 | t.Fatalf("retired Auto Guard key %q must not be rendered:\nuser:\n%s\nproject:\n%s", retired, user, project) |
| 44 | } |
| 45 | } |
| 46 | if strings.Contains(project, "\nsystem_prompt = \"\"\"") { |
| 47 | t.Fatalf("project render should not pin the built-in system prompt:\n%s", project) |
| 48 | } |
| 49 | if !strings.Contains(project, "# system_prompt =") { |
| 50 | t.Fatalf("project render should leave a system prompt hint:\n%s", project) |
| 51 | } |
| 52 | if strings.Contains(user, "recovery_model") || strings.Contains(project, "recovery_model") { |
| 53 | t.Fatalf("retired recovery_model rendered:\nuser:\n%s\nproject:\n%s", user, project) |
| 54 | } |
| 55 | if strings.Contains(user, "auto_plan") || strings.Contains(project, "auto_plan") { |
| 56 | t.Fatalf("retired auto-plan keys must not be rendered:\nuser:\n%s\nproject:\n%s", user, project) |
| 57 | } |
| 58 | if strings.Contains(user, "recovery_temperature") || strings.Contains(project, "recovery_temperature") { |
| 59 | t.Fatalf("deprecated recovery_temperature must not be rendered:\nuser:\n%s\nproject:\n%s", user, project) |
| 60 | } |
| 61 | } |
| 62 |