Files
VoCat/internal/extensions/manager_test.go
T
MengMengCode 9fc3f1c5b8 feat: add Telegram API URL handling and version comparison utilities
- Implemented `telegramAPIURL` and `validateTelegramAPIURL` functions for constructing and validating Telegram API URLs.
- Added semantic versioning utilities in `version.go` to compare versions and validate semantic version formats.
- Created tests for version comparison logic in `version_test.go`.
- Introduced IMS call handling in `call_runtime.go`, including methods for dialing, answering, and hanging up calls.
- Added tests for incoming call handling and validation in `call_runtime_test.go`.
- Developed a new `PluginsCard` component for managing plugins via URL or file upload in the web interface.
- Implemented plugin management functions in `extensions.ts` and created an `ExtensionPage` for displaying plugin contributions.
2026-08-09 19:28:12 +08:00

101 lines
2.7 KiB
Go

package extensions
import (
"archive/zip"
"bytes"
"io"
"log/slog"
"strings"
"testing"
)
func TestInstallListDisableAndUninstall(t *testing.T) {
manager, err := NewManager(t.TempDir(), slog.New(slog.NewTextHandler(io.Discard, nil)))
if err != nil {
t.Fatal(err)
}
defer manager.Close()
archive := testPackage(t, map[string]string{
ManifestFilename: `{
"schema_version":1,"id":"test-plugin","name":"Test","version":"1.0.0",
"permissions":["devices.read"],
"contributions":[{"id":"test-page","label":"Test","location":"sidebar","entry":"web/index.html"}]
}`,
"web/index.html": "<h1>test</h1>",
})
plugin, err := manager.Install(bytes.NewReader(archive), "")
if err != nil {
t.Fatal(err)
}
if plugin.ID != "test-plugin" || !plugin.Enabled || len(manager.List()) != 1 {
t.Fatalf("unexpected installed plugin: %#v", plugin)
}
if _, err := manager.SetEnabled(plugin.ID, false); err != nil {
t.Fatal(err)
}
if manager.List()[0].Enabled {
t.Fatal("plugin remained enabled")
}
if err := manager.Uninstall(plugin.ID); err != nil {
t.Fatal(err)
}
if len(manager.List()) != 0 {
t.Fatal("plugin remained installed")
}
}
func TestInstallRejectsPathTraversal(t *testing.T) {
manager, err := NewManager(t.TempDir(), nil)
if err != nil {
t.Fatal(err)
}
defer manager.Close()
archive := testPackage(t, map[string]string{
ManifestFilename: `{
"schema_version":1,"id":"bad-plugin","name":"Bad","version":"1",
"contributions":[{"id":"bad-page","label":"Bad","location":"sidebar","entry":"web/index.html"}]
}`,
"../escaped": "bad",
})
if _, err := manager.Install(bytes.NewReader(archive), ""); err == nil || !strings.Contains(err.Error(), "unsafe path") {
t.Fatalf("Install traversal error = %v", err)
}
}
func TestInstallVerifiesSHA256(t *testing.T) {
manager, err := NewManager(t.TempDir(), nil)
if err != nil {
t.Fatal(err)
}
defer manager.Close()
archive := testPackage(t, map[string]string{
ManifestFilename: `{
"schema_version":1,"id":"hash-plugin","name":"Hash","version":"1",
"contributions":[{"id":"hash-page","label":"Hash","location":"sidebar","entry":"web/index.html"}]
}`,
"web/index.html": "ok",
})
if _, err := manager.Install(bytes.NewReader(archive), strings.Repeat("0", 64)); err == nil {
t.Fatal("Install accepted incorrect SHA-256")
}
}
func testPackage(t *testing.T, files map[string]string) []byte {
t.Helper()
var output bytes.Buffer
writer := zip.NewWriter(&output)
for name, content := range files {
entry, err := writer.Create(name)
if err != nil {
t.Fatal(err)
}
if _, err := entry.Write([]byte(content)); err != nil {
t.Fatal(err)
}
}
if err := writer.Close(); err != nil {
t.Fatal(err)
}
return output.Bytes()
}