middleware-manager/api/handlers/plugin_handler_test.go
hhftechnologies ce71c4037c
Some checks are pending
Build and Push Docker Image / build-and-push (push) Waiting to run
Tests / Run Tests (push) Waiting to run
Tests / Lint (push) Waiting to run
Tests / Build (push) Blocked by required conditions
testfiles
2026-01-24 11:58:12 +05:30

200 lines
6 KiB
Go

package handlers
import (
"bytes"
"encoding/json"
"net/http"
"os"
"path/filepath"
"testing"
"github.com/gin-gonic/gin"
"github.com/hhftechnology/middleware-manager/internal/testutil"
)
// TestNewPluginHandler tests plugin handler creation
func TestNewPluginHandler(t *testing.T) {
db := testutil.NewTempDB(t)
cm := testutil.NewTestConfigManager(t)
configPath := filepath.Join(t.TempDir(), "traefik.yml")
handler := NewPluginHandler(db.DB, configPath, cm)
if handler == nil {
t.Fatal("NewPluginHandler() returned nil")
}
if handler.DB == nil {
t.Error("handler.DB is nil")
}
if handler.TraefikStaticConfigPath != configPath {
t.Errorf("TraefikStaticConfigPath = %q, want %q", handler.TraefikStaticConfigPath, configPath)
}
}
// TestPluginHandler_RefreshPluginFetcher tests fetcher refresh
func TestPluginHandler_RefreshPluginFetcher(t *testing.T) {
db := testutil.NewTempDB(t)
cm := testutil.NewTestConfigManager(t)
configPath := filepath.Join(t.TempDir(), "traefik.yml")
handler := NewPluginHandler(db.DB, configPath, cm)
err := handler.RefreshPluginFetcher()
if err != nil {
t.Errorf("RefreshPluginFetcher() error = %v", err)
}
}
// TestPluginHandler_RefreshPluginFetcher_NoConfigManager tests refresh without config manager
func TestPluginHandler_RefreshPluginFetcher_NoConfigManager(t *testing.T) {
db := testutil.NewTempDB(t)
configPath := filepath.Join(t.TempDir(), "traefik.yml")
handler := NewPluginHandler(db.DB, configPath, nil)
err := handler.RefreshPluginFetcher()
if err == nil {
t.Error("RefreshPluginFetcher() should error without config manager")
}
}
// TestPluginHandler_GetPlugins tests getting plugins
func TestPluginHandler_GetPlugins(t *testing.T) {
db := testutil.NewTempDB(t)
cm := testutil.NewTestConfigManager(t)
configPath := filepath.Join(t.TempDir(), "traefik.yml")
handler := NewPluginHandler(db.DB, configPath, cm)
c, rec := testutil.NewContext(t, http.MethodGet, "/api/plugins", nil)
handler.GetPlugins(c)
if rec.Code != http.StatusOK {
t.Fatalf("expected 200, got %d: %s", rec.Code, rec.Body.String())
}
var plugins []map[string]interface{}
if err := json.Unmarshal(rec.Body.Bytes(), &plugins); err != nil {
t.Fatalf("failed to parse response: %v", err)
}
// Should return an array (possibly empty)
if plugins == nil {
t.Error("expected array, got nil")
}
}
// TestPluginHandler_GetPlugins_WithLocalConfig tests getting plugins with local config
func TestPluginHandler_GetPlugins_WithLocalConfig(t *testing.T) {
db := testutil.NewTempDB(t)
cm := testutil.NewTestConfigManager(t)
configDir := t.TempDir()
configPath := filepath.Join(configDir, "traefik.yml")
// Create a test traefik config with plugins
traefikConfig := `
experimental:
plugins:
mtls-whitelist:
moduleName: github.com/example/mtls-whitelist
version: v1.0.0
`
if err := os.WriteFile(configPath, []byte(traefikConfig), 0644); err != nil {
t.Fatalf("failed to write test config: %v", err)
}
handler := NewPluginHandler(db.DB, configPath, cm)
c, rec := testutil.NewContext(t, http.MethodGet, "/api/plugins", nil)
handler.GetPlugins(c)
if rec.Code != http.StatusOK {
t.Fatalf("expected 200, got %d: %s", rec.Code, rec.Body.String())
}
var plugins []map[string]interface{}
json.Unmarshal(rec.Body.Bytes(), &plugins)
// Should find the plugin from local config
found := false
for _, p := range plugins {
if p["name"] == "mtls-whitelist" {
found = true
break
}
}
if !found && len(plugins) > 0 {
// Plugin should be in the list
t.Log("Plugin not found in response, but this may be expected if Traefik API is not available")
}
}
// TestPluginHandler_InstallPlugin_InvalidJSON tests invalid install request
func TestPluginHandler_InstallPlugin_InvalidJSON(t *testing.T) {
db := testutil.NewTempDB(t)
cm := testutil.NewTestConfigManager(t)
configPath := filepath.Join(t.TempDir(), "traefik.yml")
handler := NewPluginHandler(db.DB, configPath, cm)
body := bytes.NewBufferString(`{invalid}`)
c, rec := testutil.NewContext(t, http.MethodPost, "/api/plugins/install", body)
handler.InstallPlugin(c)
if rec.Code != http.StatusBadRequest {
t.Errorf("expected 400, got %d", rec.Code)
}
}
// TestPluginHandler_InstallPlugin_MissingFields tests install with missing fields
func TestPluginHandler_InstallPlugin_MissingFields(t *testing.T) {
db := testutil.NewTempDB(t)
cm := testutil.NewTestConfigManager(t)
configPath := filepath.Join(t.TempDir(), "traefik.yml")
handler := NewPluginHandler(db.DB, configPath, cm)
// Missing required fields
body := bytes.NewBufferString(`{"name": "test"}`)
c, rec := testutil.NewContext(t, http.MethodPost, "/api/plugins/install", body)
handler.InstallPlugin(c)
if rec.Code != http.StatusBadRequest {
t.Errorf("expected 400, got %d", rec.Code)
}
}
// TestPluginHandler_RemovePlugin_InvalidJSON ensures remove plugin validates body
func TestPluginHandler_RemovePlugin_InvalidJSON(t *testing.T) {
db := testutil.NewTempDB(t)
cm := testutil.NewTestConfigManager(t)
configPath := filepath.Join(t.TempDir(), "traefik.yml")
handler := NewPluginHandler(db.DB, configPath, cm)
c, rec := testutil.NewContext(t, http.MethodDelete, "/api/plugins/remove", bytes.NewBufferString(`{invalid}`))
handler.RemovePlugin(c)
if rec.Code != http.StatusBadRequest {
t.Errorf("expected 400, got %d", rec.Code)
}
}
// TestPluginHandler_GetPluginUsage tests getting plugin usage info
func TestPluginHandler_GetPluginUsage(t *testing.T) {
db := testutil.NewTempDB(t)
cm := testutil.NewTestConfigManager(t)
configPath := filepath.Join(t.TempDir(), "traefik.yml")
handler := NewPluginHandler(db.DB, configPath, cm)
c, rec := testutil.NewContext(t, http.MethodGet, "/api/plugins/test-plugin/usage", nil)
c.Params = gin.Params{{Key: "name", Value: "test-plugin"}}
handler.GetPluginUsage(c)
// Depending on fetcher configuration, this may be 404 or 500, but should not panic
if rec.Code != http.StatusOK && rec.Code != http.StatusNotFound && rec.Code != http.StatusInternalServerError {
t.Fatalf("unexpected status code %d", rec.Code)
}
}