Files
kandev/apps/backend/pkg/pluginsdk/plugin_test.go
T
Kandev Agent c53f699714 feat: add plugin system with grpc runtime and native ui plugins
- go plugin backends ship as release tarballs (per-platform binaries, checksums) that
  kandev installs from url/upload or filesystem sideload+sync, then spawns and
  supervises via hashicorp/go-plugin (unix socket / loopback tcp+automtls)
- strict typed grpc contract (kandev.plugin.v1): DeliverEvent/InvokeTool/HandleWebhook
  plus a capability-gated host service (state, secrets, emit); author sdk in
  pkg/pluginsdk; packaging cli in cmd/plugin-pack
- native frontend bundles: window.registerKandevPlugin + registry/host loader with
  dynamic routes, nav items, slots and ws handlers; plugins settings page with
  install dialog, sync button and enable/disable/uninstall
- gated behind the plugins feature flag (prod off, dev/e2e on); covered by unit and
  integration tests plus playwright e2e against a real packaged fixture plugin

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 17:55:45 +01:00

53 lines
1.6 KiB
Go

package pluginsdk
import (
"context"
"testing"
"github.com/stretchr/testify/require"
)
func TestUnimplementedPlugin_DefaultsAreNoOps(t *testing.T) {
var p UnimplementedPlugin
require.NoError(t, p.OnEvent(context.Background(), &Event{EventID: "e1"}))
resp, err := p.InvokeTool(context.Background(), &ToolRequest{ToolName: "noop"})
require.NoError(t, err)
require.NotNil(t, resp)
webhookResp, err := p.HandleWebhook(context.Background(), &WebhookRequest{Path: "/x"})
require.NoError(t, err)
require.NotNil(t, webhookResp)
require.Equal(t, int32(404), webhookResp.Status)
}
func TestUnimplementedPlugin_SetHostThenHost(t *testing.T) {
var p UnimplementedPlugin
require.Nil(t, p.Host())
h := &fakeHost{}
p.SetHost(h)
require.Equal(t, h, p.Host())
}
// fakeHost is a minimal Host implementation used only to prove SetHost/Host
// wiring; broker-backed Host behavior is covered by the integration test in
// serve_test.go.
type fakeHost struct{}
func (f *fakeHost) GetState(context.Context, string, string, string) (map[string]any, bool, error) {
return nil, false, nil
}
func (f *fakeHost) SetState(context.Context, string, string, string, map[string]any) error {
return nil
}
func (f *fakeHost) DeleteState(context.Context, string, string, string) error { return nil }
func (f *fakeHost) ListState(context.Context, string, string) ([]StateEntry, error) {
return nil, nil
}
func (f *fakeHost) RevealSecret(context.Context, string) (string, error) { return "", nil }
func (f *fakeHost) EmitEvent(context.Context, string, map[string]any) error { return nil }
var _ Host = (*fakeHost)(nil)