Files
new-api/plugins/builtin_plugins_test.go

124 lines
4.5 KiB
Go

package plugins
import (
"io/fs"
"testing"
"github.com/QuantumNous/new-api/pkg/jsplugin"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestBuiltInVendorPluginsDeclareNativeRoutesAndLegacyChannelTypes(t *testing.T) {
generation := jsplugin.DefaultRegistry.Generation()
require.NotNil(t, generation)
routes := []struct {
method string
path string
key string
routeType jsplugin.RouteType
action string
renderer string
}{
{"POST", "/kling/v1/videos/text2video", "kling", jsplugin.RouteTypeSubmit, "text_to_video", "taskCreated"},
{"POST", "/kling/v1/videos/image2video", "kling", jsplugin.RouteTypeSubmit, "image_to_video", "taskCreated"},
{"GET", "/kling/v1/videos/text2video/:task_id", "kling", jsplugin.RouteTypeQuery, "", "taskStatus"},
{"GET", "/kling/v1/videos/image2video/:task_id", "kling", jsplugin.RouteTypeQuery, "", "taskStatus"},
{"POST", "/jimeng/", "jimeng", jsplugin.RouteTypeDynamic, "", "renderTask"},
{"POST", "/suno/submit/:action", "sunoapi", jsplugin.RouteTypeSubmit, "", "renderSubmit"},
{"POST", "/suno/fetch", "sunoapi", jsplugin.RouteTypeDynamic, "", "renderTasks"},
{"GET", "/suno/fetch/:task_id", "sunoapi", jsplugin.RouteTypeQuery, "", "renderTask"},
{"POST", "/doubao/api/v3/contents/generations/tasks", "doubao", jsplugin.RouteTypeSubmit, "", "taskCreated"},
{"GET", "/doubao/api/v3/contents/generations/tasks/:task_id", "doubao", jsplugin.RouteTypeQuery, "", "taskStatus"},
}
for _, expected := range routes {
t.Run(expected.method+" "+expected.path, func(t *testing.T) {
binding, found := generation.LookupDeclaredRoute(expected.method, expected.path)
require.True(t, found)
require.Equal(t, expected.key, binding.Plugin.Meta.Key)
require.Equal(t, expected.routeType, binding.Route.Type)
require.Equal(t, expected.action, binding.Route.Action)
require.Equal(t, expected.renderer, binding.Route.Render)
})
}
channelTypes := []struct {
value int
key string
}{
{1, "sora"},
{36, "sunoapi"},
{45, "doubao"},
{50, "kling"},
{51, "jimeng"},
{54, "doubao"},
{55, "sora"},
}
for _, channelType := range channelTypes {
plugin, found := generation.GetByChannelType(channelType.value)
require.True(t, found)
require.Equal(t, channelType.key, plugin.Meta.Key)
}
}
func TestBuiltInTaskPluginResponsesAndUsageContracts(t *testing.T) {
expectedKeys := []string{"alibaba", "doubao", "google", "hailuo", "jimeng", "kling", "sora", "sunoapi", "vertex-ai", "vidu"}
generation := jsplugin.DefaultRegistry.Generation()
require.NotNil(t, generation)
entries, err := fs.ReadDir(taskPlugins, "tasks")
require.NoError(t, err)
actualKeys := make([]string, 0, len(entries))
for _, entry := range entries {
if entry.IsDir() {
actualKeys = append(actualKeys, entry.Name())
}
}
assert.Equal(t, expectedKeys, actualKeys)
for _, key := range expectedKeys {
t.Run(key, func(t *testing.T) {
_, found := generation.Get(key)
require.True(t, found, "factory plugin was excluded from the active generation")
source, sourceErr := Source(key)
require.NoError(t, sourceErr)
registry := jsplugin.NewRegistry()
plugin, registerErr := registry.RegisterFactory(source, jsplugin.Options{Key: key})
require.NoError(t, registerErr)
var responsesClaim jsplugin.ProtocolClaim
foundResponses := false
for _, claim := range plugin.Meta.Protocols {
if claim.Name == "openai_responses" {
responsesClaim = claim
foundResponses = true
break
}
}
require.True(t, foundResponses, "openai_responses claim must be present")
assert.Equal(t, []string{"stream", "sync", "background"}, responsesClaim.Supports)
for _, model := range plugin.Meta.Models {
binding, claimed := registry.Generation().LookupEndpoint("POST", "/v1/responses", model)
require.True(t, claimed, model)
assert.Same(t, plugin, binding.Plugin)
}
for _, hook := range []string{"decodeRequest", "renderEvents", "renderFinal"} {
callable, callableErr := plugin.Engine.HasCallablePath(t.Context(), "protocols", "openai_responses", hook)
require.NoError(t, callableErr)
assert.True(t, callable, hook)
}
for _, hook := range []string{"extractUsage", "extractUsageOnComplete"} {
callable, callableErr := plugin.Engine.HasExport(t.Context(), hook)
require.NoError(t, callableErr)
assert.True(t, callable, hook)
}
require.NotEmpty(t, plugin.Meta.UsageSchema)
for usageKey, schema := range plugin.Meta.UsageSchema {
assert.NotEmpty(t, schema.Description, usageKey)
}
})
}
}