mirror of
https://github.com/esengine/DeepSeek-Reasonix.git
synced 2026-11-07 10:45:59 -10:00
* feat(desktop): add project tabs and context inspector * feat(desktop): refine project workspace UI * fix 打开一致加载 * 顶部统一logo+左侧边栏+统一菜单 * 底部最低宽度 * update much * update code * update code * feat(desktop): refine workspace layout and message actions * fix(desktop): scope file refs to active tab root * test(desktop): stabilize capabilities config dirs * fix(desktop): protect sessions open in other tabs * fix(desktop): resume scoped history in matching tab * chore(desktop): drop committed scratch artifacts; ignore tmp/ and .codex/ The project-tabs branch carried 30 throwaway screenshots, a mock HTML, and a codex env file into the tree because tmp/ and .codex/ were never ignored. Remove them and add the ignore rules so scratch output stays out of future commits. * test(desktop): isolate AppData per test so the suite passes on Windows The new project/topic/workspace tests only overrode HOME and XDG_CONFIG_HOME, but desktopConfigDir() and config.MemoryUserDir() resolve through os.UserConfigDir(), which reads %AppData% on Windows and ignores those vars. With AppData pointed at one shared TestMain dir, the project/topic/workspace registries leaked across tests: full-package runs failed (project tree len 2 want 1, trash mixing other tests' sessions, Plugins[0] reading a neighbor's MCP entry) while each test passed alone. Route every test through isolateDesktopUserDirs, which already sets HOME, USERPROFILE, XDG_CONFIG_HOME, and AppData to a per-test temp dir. go test ./... (and -race) now pass on Windows. --------- Co-authored-by: reasonix <[email protected]>
66 lines
1.9 KiB
Go
66 lines
1.9 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"reflect"
|
|
"testing"
|
|
)
|
|
|
|
func TestBoundArrayPayloadsAreNonNilBeforeStartup(t *testing.T) {
|
|
isolateDesktopUserDirs(t)
|
|
|
|
app := NewApp()
|
|
cases := []struct {
|
|
name string
|
|
got any
|
|
}{
|
|
{"Checkpoints", app.Checkpoints()},
|
|
{"ListSessions", app.ListSessions()},
|
|
{"ListTrashedSessions", app.ListTrashedSessions()},
|
|
{"ListWorkspaces", app.ListWorkspaces()},
|
|
{"History", app.History()},
|
|
{"Jobs", app.Jobs()},
|
|
{"Commands", app.Commands()},
|
|
{"Models", app.Models()},
|
|
{"ListDir", app.ListDir("__missing__")},
|
|
{"ListTabs", app.ListTabs()},
|
|
{"ListProjectTree", app.ListProjectTree()},
|
|
}
|
|
for _, tc := range cases {
|
|
assertNonNilSliceJSON(t, tc.name, tc.got)
|
|
}
|
|
|
|
if got := app.SlashArgs("/skill "); got.Items == nil {
|
|
t.Fatal("SlashArgs().Items is nil; frontend expects []")
|
|
}
|
|
if got := app.WorkspaceChanges(); got.Files == nil {
|
|
t.Fatal("WorkspaceChanges().Files is nil; frontend expects []")
|
|
}
|
|
if got := app.ContextPanel("missing"); got.ReadFiles == nil || got.ChangedFiles == nil {
|
|
t.Fatalf("ContextPanel(missing) arrays = read:%v changed:%v, want non-nil", got.ReadFiles, got.ChangedFiles)
|
|
}
|
|
if got := app.Settings(); got.Providers == nil || got.ProviderKinds == nil ||
|
|
got.Permissions.Allow == nil || got.Permissions.Ask == nil || got.Permissions.Deny == nil ||
|
|
got.Sandbox.AllowWrite == nil {
|
|
t.Fatalf("Settings() contains nil array fields: %+v", got)
|
|
}
|
|
}
|
|
|
|
func assertNonNilSliceJSON(t *testing.T, name string, got any) {
|
|
t.Helper()
|
|
v := reflect.ValueOf(got)
|
|
if v.Kind() != reflect.Slice {
|
|
t.Fatalf("%s returned %T, want slice", name, got)
|
|
}
|
|
if v.IsNil() {
|
|
t.Fatalf("%s returned nil slice; frontend expects []", name)
|
|
}
|
|
raw, err := json.Marshal(got)
|
|
if err != nil {
|
|
t.Fatalf("%s JSON marshal: %v", name, err)
|
|
}
|
|
if string(raw) == "null" {
|
|
t.Fatalf("%s JSON encoded as null; frontend expects []", name)
|
|
}
|
|
}
|