Sharing refuses a key shorter than minLength characters (default 32, never under 16) or of fewer than minClasses kinds of lowercase, uppercase, digits and symbols (default 2, so random hex passes), saying so without showing it. Opening doesn't check. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
156 lines
4.4 KiB
Go
156 lines
4.4 KiB
Go
package config
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func write(t *testing.T, content string) string {
|
|
t.Helper()
|
|
path := filepath.Join(t.TempDir(), "config.yaml")
|
|
if err := os.WriteFile(path, []byte(content), 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return path
|
|
}
|
|
|
|
func TestLoad(t *testing.T) {
|
|
c, err := Load(write(t, `
|
|
icons: false
|
|
sourcesView: flat
|
|
clipboardClear: 45s
|
|
timeout: 1m
|
|
providers:
|
|
azure:
|
|
hideSubscriptions: [platform-mgmt]
|
|
vaults:
|
|
- https://kv-foo.vault.azure.net/
|
|
databricks:
|
|
enabled: false
|
|
hideProfiles: [test]
|
|
`))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if c.Icons == nil || *c.Icons || c.ClipboardClear == nil || *c.ClipboardClear != 45*time.Second ||
|
|
c.Timeout != time.Minute || len(c.Providers.Azure.Vaults) != 1 || c.Providers.Databricks.HideProfiles[0] != "test" {
|
|
t.Errorf("config = %+v", c)
|
|
}
|
|
if c.SourcesView != "flat" {
|
|
t.Errorf("sourcesView = %q", c.SourcesView)
|
|
}
|
|
if !On(c.Providers.Azure.Enabled) || On(c.Providers.Databricks.Enabled) {
|
|
t.Error("enabled flags wrong")
|
|
}
|
|
az := c.Providers.Azure
|
|
if !Hidden(az.HideSubscriptions, "PLATFORM-MGMT", "id") || Hidden(az.HideSubscriptions, "other", "id") {
|
|
t.Error("Hidden matching wrong")
|
|
}
|
|
}
|
|
|
|
func TestLoadMissingAndEmpty(t *testing.T) {
|
|
for name, path := range map[string]string{
|
|
"missing": filepath.Join(t.TempDir(), "nope.yaml"),
|
|
"empty": write(t, ""),
|
|
} {
|
|
c, err := Load(path)
|
|
if err != nil || c.Icons != nil || c.ClipboardClear != nil {
|
|
t.Errorf("%s: %+v, %v", name, c, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestLoadRejectsMistakes(t *testing.T) {
|
|
for name, content := range map[string]string{
|
|
"typo": "icon: true\n",
|
|
"bad vault": "providers:\n azure:\n vaults: [kv-foo]\n",
|
|
"old layout": "azure:\n vaults: [https://kv.vault.azure.net/]\n",
|
|
"duration": "timeout: soon\n",
|
|
"view": "sourcesView: tree\n",
|
|
"releases": "releases: [git.example.com/team/lazysecrets]\n",
|
|
"http": "releases: [http://git.example.com/team/lazysecrets]\n",
|
|
"share key": "share:\n key: https://kv.vault.azure.net/\n",
|
|
"short keys": "share:\n keyRules:\n minLength: 8\n",
|
|
"classes": "share:\n keyRules:\n minClasses: 5\n",
|
|
} {
|
|
if _, err := Load(write(t, content)); err == nil {
|
|
t.Errorf("%s: no error", name)
|
|
} else if !strings.Contains(err.Error(), "config.yaml") {
|
|
t.Errorf("%s: error doesn't name the file: %v", name, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestLoadAllLayers(t *testing.T) {
|
|
user := write(t, `
|
|
icons: false
|
|
theme:
|
|
azureColor: [blue]
|
|
errorColor: [red, bold]
|
|
providers:
|
|
azure:
|
|
hideSubscriptions: [a]
|
|
`)
|
|
theme := write(t, `
|
|
theme:
|
|
azureColor: ["#82aaff"]
|
|
activeBorderColor: ["#ff966c", bold]
|
|
`)
|
|
c, err := LoadAll([]string{user, filepath.Join(t.TempDir(), "missing.yaml"), theme})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if c.Icons == nil || *c.Icons || len(c.Providers.Azure.HideSubscriptions) != 1 {
|
|
t.Errorf("user settings lost: %+v", c)
|
|
}
|
|
want := map[string][]string{
|
|
"azureColor": {"#82aaff"}, // overridden by the later file
|
|
"errorColor": {"red", "bold"}, // kept from the user's file
|
|
"activeBorderColor": {"#ff966c", "bold"},
|
|
}
|
|
for role, v := range want {
|
|
if strings.Join(c.Theme[role], ",") != strings.Join(v, ",") {
|
|
t.Errorf("theme %s = %v, want %v", role, c.Theme[role], v)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestReleases(t *testing.T) {
|
|
c, err := Load(write(t, "releases: [https://git.example.com/team/lazysecrets]\n"))
|
|
if err != nil || len(c.Releases) != 1 {
|
|
t.Errorf("releases = %v, %v", c.Releases, err)
|
|
}
|
|
}
|
|
|
|
func TestLoadDelay(t *testing.T) {
|
|
c, err := Load(write(t, "loadDelay: 300ms\n"))
|
|
if err != nil || c.LoadDelay == nil || *c.LoadDelay != 300*time.Millisecond {
|
|
t.Errorf("loadDelay = %v, %v", c.LoadDelay, err)
|
|
}
|
|
if _, err := Load(write(t, "loadDelay: 1m\n")); err == nil {
|
|
t.Error("a minute's delay accepted")
|
|
}
|
|
}
|
|
|
|
func TestKeybindingLayers(t *testing.T) {
|
|
a := write(t, "keybinding:\n lists:\n star: [x]\n note: [N]\n")
|
|
b := write(t, "keybinding:\n lists:\n note: [m]\n filter:\n star: [ctrl+x]\n")
|
|
c, err := LoadAll([]string{a, b})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
kb := c.Keybinding
|
|
if got := kb["lists"]["star"]; len(got) != 1 || got[0] != "x" {
|
|
t.Errorf("lists.star from the first file lost: %v", kb["lists"])
|
|
}
|
|
if got := kb["lists"]["note"]; len(got) != 1 || got[0] != "m" {
|
|
t.Errorf("lists.note = %v, want the later file's", got)
|
|
}
|
|
if got := kb["filter"]["star"]; len(got) != 1 || got[0] != "ctrl+x" {
|
|
t.Errorf("filter.star = %v", got)
|
|
}
|
|
}
|