verstak-desktop/internal/core/pluginstate/manager_test.go

176 lines
4.0 KiB
Go

package pluginstate
import (
"os"
"path/filepath"
"testing"
"github.com/verstak/verstak-desktop/internal/core/vault"
)
func TestLoad_DefaultCreation(t *testing.T) {
dir := t.TempDir()
v := vault.NewVault(nil)
if err := v.CreateVault(dir); err != nil {
t.Fatalf("CreateVault: %v", err)
}
m := NewManager(v)
if err := m.Load(); err != nil {
t.Fatalf("Load: %v", err)
}
state := m.Get()
if state.SchemaVersion != 1 {
t.Errorf("SchemaVersion: got %d, want 1", state.SchemaVersion)
}
if len(state.EnabledPlugins) != 0 {
t.Errorf("EnabledPlugins: expected empty, got %v", state.EnabledPlugins)
}
}
func TestEnableDisable(t *testing.T) {
dir := t.TempDir()
v := vault.NewVault(nil)
if err := v.CreateVault(dir); err != nil {
t.Fatalf("CreateVault: %v", err)
}
m := NewManager(v)
if err := m.Load(); err != nil {
t.Fatal(err)
}
// Enable
if err := m.EnablePlugin("test-plugin"); err != nil {
t.Fatalf("EnablePlugin: %v", err)
}
if !m.IsEnabled("test-plugin") {
t.Error("expected test-plugin to be enabled")
}
// Disable
if err := m.DisablePlugin("test-plugin"); err != nil {
t.Fatalf("DisablePlugin: %v", err)
}
if !m.IsDisabled("test-plugin") {
t.Error("expected test-plugin to be disabled")
}
if m.IsEnabled("test-plugin") {
t.Error("expected test-plugin to NOT be enabled after disable")
}
}
func TestDisablePlugin_Persists(t *testing.T) {
dir := t.TempDir()
v := vault.NewVault(nil)
if err := v.CreateVault(dir); err != nil {
t.Fatalf("CreateVault: %v", err)
}
m := NewManager(v)
m.Load()
m.EnablePlugin("test-plugin")
m.DisablePlugin("test-plugin")
// Re-load from disk
m2 := NewManager(v)
m2.Load()
if m2.IsEnabled("test-plugin") {
t.Error("disabled plugin should not be enabled after reload")
}
if !m2.IsDisabled("test-plugin") {
t.Error("disabled plugin should be disabled after reload")
}
}
func TestRecordDesiredPlugin(t *testing.T) {
dir := t.TempDir()
v := vault.NewVault(nil)
if err := v.CreateVault(dir); err != nil {
t.Fatalf("CreateVault: %v", err)
}
m := NewManager(v)
m.Load()
if err := m.RecordDesiredPlugin("test-plugin", "1.0.0", "official"); err != nil {
t.Fatalf("RecordDesiredPlugin: %v", err)
}
state := m.Get()
if len(state.DesiredPlugins) != 1 {
t.Fatalf("DesiredPlugins: expected 1, got %d", len(state.DesiredPlugins))
}
if state.DesiredPlugins[0].ID != "test-plugin" {
t.Errorf("DesiredPlugin ID: got %q, want %q", state.DesiredPlugins[0].ID, "test-plugin")
}
}
func TestMissingInstalled(t *testing.T) {
dir := t.TempDir()
v := vault.NewVault(nil)
if err := v.CreateVault(dir); err != nil {
t.Fatalf("CreateVault: %v", err)
}
m := NewManager(v)
m.Load()
m.RecordDesiredPlugin("plugin-a", "1.0.0", "official")
m.RecordDesiredPlugin("plugin-b", "2.0.0", "local")
m.RecordDesiredPlugin("plugin-c", "3.0.0", "official")
// Only plugin-a is installed
missing := m.ListMissingInstalled([]string{"plugin-a"})
if len(missing) != 2 {
t.Fatalf("expected 2 missing, got %d", len(missing))
}
ids := make(map[string]bool)
for _, dp := range missing {
ids[dp.ID] = true
}
if !ids["plugin-b"] || !ids["plugin-c"] {
t.Errorf("expected plugin-b and plugin-c in missing, got %v", ids)
}
}
func TestCorruptPluginsJSON(t *testing.T) {
dir := t.TempDir()
v := vault.NewVault(nil)
if err := v.CreateVault(dir); err != nil {
t.Fatalf("CreateVault: %v", err)
}
// Create corrupt plugins.json
vaultPath := v.GetVaultPath()
pluginsPath := filepath.Join(vaultPath, ".verstak", "plugins.json")
os.WriteFile(pluginsPath, []byte("{not json"), 0o644)
m := NewManager(v)
err := m.Load()
if err == nil {
t.Fatal("expected error for corrupt plugins.json")
}
// Should have created defaults
state := m.Get()
if state.SchemaVersion != 1 {
t.Errorf("SchemaVersion: got %d, want 1", state.SchemaVersion)
}
}
func TestVaultClosed_StateUnavailable(t *testing.T) {
v := vault.NewVault(nil)
// Don't open vault — state should fail
m := NewManager(v)
err := m.Load()
if err == nil {
t.Fatal("expected error when vault is not open")
}
}