Files
relspecgo/pkg/ui/filebrowser_test.go
T
SG CommandandClaude Sonnet 5.5 0235a28add feat(ui): file browser and connection string builder dialogs (#44)
Enter on File Path inputs opens a file browser (load/save, extension
filter, hidden toggle, overwrite confirm). Enter on Connection String
inputs opens a builder for PostgreSQL, MSSQL and SQLite with masked
password/preview, parsing and optional connection test.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 11:35:12 +02:00

125 lines
3.2 KiB
Go

package ui
import (
"os"
"path/filepath"
"reflect"
"testing"
)
func touch(t *testing.T, path string) {
t.Helper()
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(path, nil, 0o644); err != nil {
t.Fatal(err)
}
}
func names(entries []FileEntry) []string {
var out []string
for _, e := range entries {
if e.IsDir {
out = append(out, e.Name+"/")
} else {
out = append(out, e.Name)
}
}
return out
}
func TestMatchesExtension(t *testing.T) {
tests := []struct {
name string
exts []string
want bool
}{
{"a.dbml", []string{".dbml"}, true},
{"A.DBML", []string{".dbml"}, true},
{"a.json", []string{".dbml"}, false},
{"a.yml", []string{".yaml", ".yml"}, true},
{"noext", []string{".sql"}, false},
{"anything", nil, true},
}
for _, tt := range tests {
if got := MatchesExtension(tt.name, tt.exts); got != tt.want {
t.Errorf("MatchesExtension(%q, %v) = %v, want %v", tt.name, tt.exts, got, tt.want)
}
}
}
func TestListDirFilterAndHidden(t *testing.T) {
dir := t.TempDir()
touch(t, filepath.Join(dir, "b.dbml"))
touch(t, filepath.Join(dir, "A.dbml"))
touch(t, filepath.Join(dir, "c.json"))
touch(t, filepath.Join(dir, ".hidden.dbml"))
touch(t, filepath.Join(dir, "sub", "x.txt"))
touch(t, filepath.Join(dir, ".git", "x"))
got, err := ListDir(dir, FormatExtensions("dbml"), false)
if err != nil {
t.Fatal(err)
}
if want := []string{"sub/", "A.dbml", "b.dbml"}; !reflect.DeepEqual(names(got), want) {
t.Errorf("filtered: got %v, want %v", names(got), want)
}
got, _ = ListDir(dir, FormatExtensions("dbml"), true)
if want := []string{".git/", "sub/", ".hidden.dbml", "A.dbml", "b.dbml"}; !reflect.DeepEqual(names(got), want) {
t.Errorf("hidden: got %v, want %v", names(got), want)
}
got, _ = ListDir(dir, nil, false)
if want := []string{"sub/", "A.dbml", "b.dbml", "c.json"}; !reflect.DeepEqual(names(got), want) {
t.Errorf("no filter: got %v, want %v", names(got), want)
}
}
func TestListDirMissing(t *testing.T) {
if _, err := ListDir(filepath.Join(t.TempDir(), "nope"), nil, false); err == nil {
t.Error("expected error for missing directory")
}
}
func TestResolveStart(t *testing.T) {
dir := t.TempDir()
file := filepath.Join(dir, "schema.dbml")
touch(t, file)
wd, _ := os.Getwd()
tests := []struct {
name string
in string
wantDir string
wantFileName string
}{
{"existing file", file, dir, "schema.dbml"},
{"directory", dir, dir, ""},
{"new file in existing dir", filepath.Join(dir, "new.dbml"), dir, "new.dbml"},
{"empty", "", wd, ""},
{"nonexistent parent", filepath.Join(dir, "no", "such", "f.dbml"), wd, ""},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
d, n := ResolveStart(tt.in)
if d != tt.wantDir || n != tt.wantFileName {
t.Errorf("got (%q, %q), want (%q, %q)", d, n, tt.wantDir, tt.wantFileName)
}
})
}
}
func TestFormatExtensions(t *testing.T) {
if got := FormatExtensions("yaml"); !reflect.DeepEqual(got, []string{".yaml", ".yml"}) {
t.Errorf("yaml: %v", got)
}
if FormatExtensions("unknown") != nil {
t.Error("unknown format should not filter")
}
if !IsDirectoryFormat("gorm") || IsDirectoryFormat("json") {
t.Error("directory format detection wrong")
}
}