package plugins import ( "os" "path/filepath" "testing" ) type fsDir struct { name string files map[string][]byte dirs map[string]*fsDir } func setupPluginDir(t *testing.T, plugins map[string]*fsDir) string { t.Helper() base := filepath.Join(t.TempDir(), ".verstak", "plugins") os.MkdirAll(base, 0o750) for name, plugin := range plugins { pDir := filepath.Join(base, name) os.MkdirAll(pDir, 0o750) for fname, content := range plugin.files { os.WriteFile(filepath.Join(pDir, fname), content, 0o640) } for dname, d := range plugin.dirs { dDir := filepath.Join(pDir, dname) os.MkdirAll(dDir, 0o750) for fname, content := range d.files { os.WriteFile(filepath.Join(dDir, fname), content, 0o640) } } } return filepath.Dir(filepath.Dir(base)) // vault root } func TestDiscover(t *testing.T) { root := setupPluginDir(t, map[string]*fsDir{ "client": { files: map[string][]byte{ "plugin.json": []byte(`{ "name": "client", "version": "1.0.0", "description": "Client template", "templates": ["client"] }`), }, dirs: map[string]*fsDir{ "templates": { files: map[string][]byte{ "client.json": []byte(`{ "name": "Клиент", "root_type": "case", "tree": [ {"type": "folder", "title": "Документы"}, {"type": "note", "title": "Overview"}, {"type": "folder", "title": "Переписка"} ] }`), }, }, }, }, "empty-dir": {}, "no-json": { files: map[string][]byte{"README.md": []byte("hi")}, }, }) mgr := NewManager(root) mgr.Discover() plugins := mgr.Plugins() if len(plugins) != 1 { t.Errorf("plugins = %d, want 1", len(plugins)) } if len(plugins) > 0 && plugins[0].Meta.Name != "client" { t.Errorf("plugin name = %q", plugins[0].Meta.Name) } // Templates. tmpls := mgr.Templates() if len(tmpls) != 1 { t.Errorf("templates = %d, want 1", len(tmpls)) } if len(tmpls) > 0 { tmpl := tmpls[0] if tmpl.Name != "Клиент" { t.Errorf("template name = %q", tmpl.Name) } if tmpl.Plugin != "client" { t.Errorf("template plugin = %q", tmpl.Plugin) } if len(tmpl.Tree) != 3 { t.Errorf("template tree = %d items, want 3", len(tmpl.Tree)) } } } func TestEnableDisable(t *testing.T) { root := setupPluginDir(t, map[string]*fsDir{ "plugin-a": { files: map[string][]byte{ "plugin.json": []byte(`{"name": "a", "version": "1.0"}`), }, }, "plugin-b": { files: map[string][]byte{ "plugin.json": []byte(`{"name": "b", "version": "1.0"}`), }, }, }) mgr := NewManager(root) mgr.Discover() if len(mgr.Plugins()) != 2 { t.Fatalf("plugins = %d, want 2", len(mgr.Plugins())) } // All active by default. if len(mgr.Active()) != 2 { t.Errorf("active = %d, want 2", len(mgr.Active())) } // Disable one. mgr.Disable("a") if len(mgr.Active()) != 1 { t.Errorf("active after disable = %d, want 1", len(mgr.Active())) } // Re-enable. mgr.Enable("a") if len(mgr.Active()) != 2 { t.Errorf("active after enable = %d, want 2", len(mgr.Active())) } } func TestActiveNames(t *testing.T) { root := setupPluginDir(t, map[string]*fsDir{ "p1": {files: map[string][]byte{"plugin.json": []byte(`{"name":"p1"}`)}}, "p2": {files: map[string][]byte{"plugin.json": []byte(`{"name":"p2"}`)}}, }) mgr := NewManager(root) mgr.Discover() mgr.Disable("p1") names := mgr.ActiveNames() if len(names) != 1 || names[0] != "p2" { t.Errorf("active names = %v, want [p2]", names) } } func TestNoPluginsDir(t *testing.T) { root := t.TempDir() mgr := NewManager(root) mgr.Discover() // Should not crash. if len(mgr.Plugins()) != 0 { t.Errorf("plugins = %d, want 0", len(mgr.Plugins())) } }