registry/internal/importer/importer_test.go
adam jones 9d9a02c57f
Database implementation cleanup (#335)
## Motivation and Context

The database logic was getting a bit unwieldy and fragile - especially
because business logic that should really have lived at the registry
service level was being pushed into the persistence level.

This PR tightens the interface, simplifies the code there, as well as
rips out a bunch of mocks etc. we don't need.

## How Has This Been Tested?

Locally everything works

## Breaking Changes

The list endpoint was surprisingly always filtering for isLatest only,
which seems like a bug? I have removed this filter.
2025-09-02 13:37:28 +01:00

201 lines
5.4 KiB
Go

package importer_test
import (
"context"
"encoding/json"
"net/http"
"net/http/httptest"
"os"
"testing"
"time"
"github.com/modelcontextprotocol/registry/internal/database"
"github.com/modelcontextprotocol/registry/internal/importer"
apiv0 "github.com/modelcontextprotocol/registry/pkg/api/v0"
"github.com/modelcontextprotocol/registry/pkg/model"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestImportService_LocalFile(t *testing.T) {
// Create a temporary seed file
tempFile := "/tmp/test_import_seed.json"
seedData := []apiv0.ServerJSON{
{
Name: "io.github.test/test-server-1",
Description: "Test server 1",
Repository: model.Repository{
URL: "https://github.com/test/repo1",
Source: "github",
ID: "123",
},
VersionDetail: model.VersionDetail{
Version: "1.0.0",
},
Meta: &apiv0.ServerMeta{
IOModelContextProtocolRegistry: &apiv0.RegistryExtensions{
ID: "test-id-1",
PublishedAt: time.Now(),
UpdatedAt: time.Now(),
IsLatest: true,
},
},
},
}
jsonData, err := json.Marshal(seedData)
require.NoError(t, err)
err = os.WriteFile(tempFile, jsonData, 0600)
require.NoError(t, err)
defer os.Remove(tempFile)
memDB := database.NewMemoryDB()
// Create importer service and test import
service := importer.NewService(memDB)
err = service.ImportFromPath(context.Background(), tempFile)
require.NoError(t, err)
// Verify the server was imported
servers, _, err := memDB.List(context.Background(), nil, "", 10)
require.NoError(t, err)
assert.Len(t, servers, 1)
assert.Equal(t, "io.github.test/test-server-1", servers[0].Name)
}
func TestImportService_HTTPFile(t *testing.T) {
// Create a test HTTP server
seedData := []apiv0.ServerJSON{
{
Name: "io.github.test/http-test-server",
Description: "HTTP test server",
Repository: model.Repository{
URL: "https://github.com/test/repo1",
Source: "github",
ID: "123",
},
VersionDetail: model.VersionDetail{
Version: "2.0.0",
},
Meta: &apiv0.ServerMeta{
IOModelContextProtocolRegistry: &apiv0.RegistryExtensions{
ID: "test-id-2",
PublishedAt: time.Now(),
UpdatedAt: time.Now(),
IsLatest: true,
},
},
},
}
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(seedData)
}))
defer server.Close()
memDB := database.NewMemoryDB()
// Create importer service and test import
service := importer.NewService(memDB)
err := service.ImportFromPath(context.Background(), server.URL+"/seed.json")
require.NoError(t, err)
// Verify the server was imported
servers, _, err := memDB.List(context.Background(), nil, "", 10)
require.NoError(t, err)
assert.Len(t, servers, 1)
assert.Equal(t, "io.github.test/http-test-server", servers[0].Name)
}
func TestImportService_RegistryAPI(t *testing.T) {
// Create test data
testServers := []apiv0.ServerJSON{
{
Name: "io.github.test/api-server-1",
Description: "API server 1",
Repository: model.Repository{
URL: "https://github.com/test/repo1",
Source: "github",
ID: "123",
},
VersionDetail: model.VersionDetail{
Version: "1.0.0",
},
Meta: &apiv0.ServerMeta{
IOModelContextProtocolRegistry: &apiv0.RegistryExtensions{
ID: "api-test-id-1",
PublishedAt: time.Now(),
UpdatedAt: time.Now(),
IsLatest: true,
},
},
},
{
Name: "io.github.test/api-server-2",
Description: "API server 2",
Repository: model.Repository{
URL: "https://github.com/test/repo2",
Source: "github",
ID: "456",
},
VersionDetail: model.VersionDetail{
Version: "2.0.0",
},
Meta: &apiv0.ServerMeta{
IOModelContextProtocolRegistry: &apiv0.RegistryExtensions{
ID: "api-test-id-2",
PublishedAt: time.Now(),
UpdatedAt: time.Now(),
IsLatest: true,
},
},
},
}
// Create test server that responds with paginated results
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
cursor := r.URL.Query().Get("cursor")
var response struct {
Servers []apiv0.ServerJSON `json:"servers"`
Metadata *struct {
NextCursor string `json:"next_cursor,omitempty"`
} `json:"metadata,omitempty"`
}
switch cursor {
case "":
// First page
response.Servers = []apiv0.ServerJSON{testServers[0]}
response.Metadata = &struct {
NextCursor string `json:"next_cursor,omitempty"`
}{NextCursor: "page2"}
case "page2":
// Second page
response.Servers = []apiv0.ServerJSON{testServers[1]}
// No next cursor means end of results
}
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(response)
}))
defer server.Close()
memDB := database.NewMemoryDB()
// Create importer service and test import
service := importer.NewService(memDB)
err := service.ImportFromPath(context.Background(), server.URL+"/v0/servers")
require.NoError(t, err)
// Verify both servers were imported
servers, _, err := memDB.List(context.Background(), nil, "", 10)
require.NoError(t, err)
assert.Len(t, servers, 2)
names := []string{servers[0].Name, servers[1].Name}
assert.Contains(t, names, "io.github.test/api-server-1")
assert.Contains(t, names, "io.github.test/api-server-2")
}