Files
grafana/apps/plugins/pkg/app/meta/catalog_test.go
Will Browne 39f4b2a959 Plugins: Rename current meta provider to catalog provider (#114966)
rename cloud provider to catalog provider
2025-12-10 12:22:05 +00:00

187 lines
5.8 KiB
Go

package meta
import (
"context"
"encoding/json"
"errors"
"net/http"
"net/http/httptest"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
pluginsv0alpha1 "github.com/grafana/grafana/apps/plugins/pkg/apis/plugins/v0alpha1"
)
func TestCatalogProvider_GetMeta(t *testing.T) {
ctx := context.Background()
t.Run("successfully fetches plugin metadata", func(t *testing.T) {
expectedMeta := pluginsv0alpha1.MetaJSONData{
Id: "test-plugin",
Name: "Test Plugin",
Type: pluginsv0alpha1.MetaJSONDataTypeDatasource,
}
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, http.MethodGet, r.Method)
assert.Equal(t, "/api/plugins/test-plugin/versions/1.0.0", r.URL.Path)
assert.Equal(t, "application/json", r.Header.Get("Accept"))
assert.Equal(t, "grafana-plugins-app", r.Header.Get("User-Agent"))
response := grafanaComPluginVersionMeta{
PluginID: "test-plugin",
Version: "1.0.0",
JSON: expectedMeta,
Description: "Test description",
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
require.NoError(t, json.NewEncoder(w).Encode(response))
}))
defer server.Close()
provider := NewCatalogProvider(server.URL + "/api/plugins")
result, err := provider.GetMeta(ctx, "test-plugin", "1.0.0")
require.NoError(t, err)
require.NotNil(t, result)
assert.Equal(t, expectedMeta, result.Meta)
assert.Equal(t, defaultCatalogTTL, result.TTL)
})
t.Run("returns ErrMetaNotFound for 404 status", func(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNotFound)
}))
defer server.Close()
provider := NewCatalogProvider(server.URL + "/api/plugins")
result, err := provider.GetMeta(ctx, "nonexistent-plugin", "1.0.0")
assert.Error(t, err)
assert.True(t, errors.Is(err, ErrMetaNotFound))
assert.Nil(t, result)
})
t.Run("returns error for non-200 status codes", func(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusInternalServerError)
}))
defer server.Close()
provider := NewCatalogProvider(server.URL + "/api/plugins")
result, err := provider.GetMeta(ctx, "test-plugin", "1.0.0")
assert.Error(t, err)
assert.Contains(t, err.Error(), "unexpected status code 500")
assert.Nil(t, result)
})
t.Run("returns error for invalid JSON response", func(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte("invalid json"))
}))
defer server.Close()
provider := NewCatalogProvider(server.URL + "/api/plugins")
result, err := provider.GetMeta(ctx, "test-plugin", "1.0.0")
assert.Error(t, err)
assert.Contains(t, err.Error(), "failed to decode response")
assert.Nil(t, result)
})
t.Run("returns error for invalid API URL", func(t *testing.T) {
provider := NewCatalogProvider("://invalid-url")
result, err := provider.GetMeta(ctx, "test-plugin", "1.0.0")
assert.Error(t, err)
assert.Contains(t, err.Error(), "invalid grafana.com API URL")
assert.Nil(t, result)
})
t.Run("uses custom TTL when provided", func(t *testing.T) {
customTTL := 2 * time.Hour
expectedMeta := pluginsv0alpha1.MetaJSONData{
Id: "test-plugin",
Name: "Test Plugin",
Type: pluginsv0alpha1.MetaJSONDataTypeDatasource,
}
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
response := grafanaComPluginVersionMeta{
PluginID: "test-plugin",
Version: "1.0.0",
JSON: expectedMeta,
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
require.NoError(t, json.NewEncoder(w).Encode(response))
}))
defer server.Close()
provider := NewCatalogProviderWithTTL(server.URL+"/api/plugins", customTTL)
result, err := provider.GetMeta(ctx, "test-plugin", "1.0.0")
require.NoError(t, err)
require.NotNil(t, result)
assert.Equal(t, customTTL, result.TTL)
})
t.Run("handles context cancellation", func(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
time.Sleep(100 * time.Millisecond)
w.WriteHeader(http.StatusOK)
}))
defer server.Close()
ctx, cancel := context.WithCancel(context.Background())
cancel()
provider := NewCatalogProvider(server.URL + "/api/plugins")
result, err := provider.GetMeta(ctx, "test-plugin", "1.0.0")
assert.Error(t, err)
assert.Nil(t, result)
})
}
func TestNewCatalogProvider(t *testing.T) {
t.Run("creates provider with default TTL", func(t *testing.T) {
provider := NewCatalogProvider("https://grafana.com/api/plugins")
assert.Equal(t, defaultCatalogTTL, provider.ttl)
assert.NotNil(t, provider.httpClient)
assert.Equal(t, "https://grafana.com/api/plugins", provider.grafanaComAPIURL)
})
t.Run("uses default URL when empty", func(t *testing.T) {
provider := NewCatalogProvider("")
assert.Equal(t, "https://grafana.com/api/plugins", provider.grafanaComAPIURL)
})
}
func TestNewCatalogProviderWithTTL(t *testing.T) {
t.Run("creates provider with custom TTL", func(t *testing.T) {
customTTL := 2 * time.Hour
provider := NewCatalogProviderWithTTL("https://grafana.com/api/plugins", customTTL)
assert.Equal(t, customTTL, provider.ttl)
})
t.Run("accepts zero TTL", func(t *testing.T) {
provider := NewCatalogProviderWithTTL("https://grafana.com/api/plugins", 0)
assert.Equal(t, time.Duration(0), provider.ttl)
})
t.Run("uses default URL when empty", func(t *testing.T) {
provider := NewCatalogProviderWithTTL("", defaultCatalogTTL)
assert.Equal(t, "https://grafana.com/api/plugins", provider.grafanaComAPIURL)
})
}