package importer_test import ( "context" "encoding/json" "net/http" "net/http/httptest" "os" "path/filepath" "testing" "github.com/modelcontextprotocol/registry/internal/config" "github.com/modelcontextprotocol/registry/internal/database" "github.com/modelcontextprotocol/registry/internal/importer" "github.com/modelcontextprotocol/registry/internal/service" 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 := filepath.Join(os.TempDir(), "test_import_seed.json") seedData := []*apiv0.ServerJSON{ { Schema: model.CurrentSchemaURL, Name: "io.github.test/test-server-1", Description: "Test server 1", Repository: &model.Repository{ URL: "https://github.com/test/repo1", Source: "github", ID: "123", }, Version: "1.0.0", }, } jsonData, err := json.Marshal(seedData) require.NoError(t, err) err = os.WriteFile(tempFile, jsonData, 0600) require.NoError(t, err) defer os.Remove(tempFile) // Create registry service testDB := database.NewTestDB(t) registryService := service.NewRegistryService(testDB, &config.Config{EnableRegistryValidation: false}) // Create importer service and test import importerService := importer.NewService(registryService) err = importerService.ImportFromPath(context.Background(), tempFile) require.NoError(t, err) // Verify the server was imported using registry service servers, _, err := registryService.ListServers(context.Background(), nil, "", 10) require.NoError(t, err) assert.Len(t, servers, 1) assert.Equal(t, "io.github.test/test-server-1", servers[0].Server.Name) assert.Equal(t, "1.0.0", servers[0].Server.Version) assert.Equal(t, "Test server 1", servers[0].Server.Description) assert.NotNil(t, servers[0].Meta.Official) assert.Equal(t, model.StatusActive, servers[0].Meta.Official.Status) } func TestImportService_HTTPFile(t *testing.T) { // Create a test HTTP server seedData := []*apiv0.ServerJSON{ { Schema: model.CurrentSchemaURL, Name: "io.github.test/http-test-server", Description: "HTTP test server", Repository: &model.Repository{ URL: "https://github.com/test/http-repo", Source: "github", ID: "456", }, Version: "2.0.0", }, } jsonData, err := json.Marshal(seedData) require.NoError(t, err) // Create test HTTP server httpServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.Header().Set("Content-Type", "application/json") _, _ = w.Write(jsonData) })) defer httpServer.Close() // Create registry service testDB := database.NewTestDB(t) registryService := service.NewRegistryService(testDB, &config.Config{EnableRegistryValidation: false}) // Create importer service and test import importerService := importer.NewService(registryService) err = importerService.ImportFromPath(context.Background(), httpServer.URL+"/seed.json") require.NoError(t, err) // Verify the server was imported servers, _, err := registryService.ListServers(context.Background(), nil, "", 10) require.NoError(t, err) assert.Len(t, servers, 1) assert.Equal(t, "io.github.test/http-test-server", servers[0].Server.Name) assert.Equal(t, "2.0.0", servers[0].Server.Version) assert.Equal(t, "HTTP test server", servers[0].Server.Description) assert.NotNil(t, servers[0].Meta.Official) } func TestImportService_RegistryPagination(t *testing.T) { ctx := context.Background() // Create registry service with test data testDB := database.NewTestDB(t) registryService := service.NewRegistryService(testDB, &config.Config{EnableRegistryValidation: false}) // Setup source registry with test data sourceServers := []*apiv0.ServerJSON{ { Schema: model.CurrentSchemaURL, Name: "com.source/server-1", Description: "Source server 1", Version: "1.0.0", }, { Schema: model.CurrentSchemaURL, Name: "com.source/server-2", Description: "Source server 2", Version: "1.0.0", }, } for _, server := range sourceServers { _, err := registryService.CreateServer(ctx, server) require.NoError(t, err) } // Create test HTTP server that serves the registry API httpServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { servers, _, _ := registryService.ListServers(ctx, nil, "", 10) // Convert to response format serverValues := make([]apiv0.ServerResponse, len(servers)) for i, server := range servers { serverValues[i] = *server } response := apiv0.ServerListResponse{ Servers: serverValues, Metadata: apiv0.Metadata{ Count: len(servers), }, } w.Header().Set("Content-Type", "application/json") _ = json.NewEncoder(w).Encode(response) })) defer httpServer.Close() // Create target registry for import targetDB := database.NewTestDB(t) targetRegistryService := service.NewRegistryService(targetDB, &config.Config{EnableRegistryValidation: false}) // Create importer service and test registry import importerService := importer.NewService(targetRegistryService) err := importerService.ImportFromPath(context.Background(), httpServer.URL+"/v0/servers") require.NoError(t, err) // Verify servers were imported importedServers, _, err := targetRegistryService.ListServers(context.Background(), nil, "", 10) require.NoError(t, err) assert.Len(t, importedServers, 2) // Verify server details serverNames := make([]string, len(importedServers)) for i, server := range importedServers { serverNames[i] = server.Server.Name } assert.Contains(t, serverNames, "com.source/server-1") assert.Contains(t, serverNames, "com.source/server-2") } func TestImportService_ErrorHandling(t *testing.T) { // Create registry service testDB := database.NewTestDB(t) registryService := service.NewRegistryService(testDB, &config.Config{EnableRegistryValidation: false}) importerService := importer.NewService(registryService) tests := []struct { name string path string expectError bool errorMsg string }{ { name: "non-existent local file", path: "/tmp/non-existent-file.json", expectError: true, errorMsg: "failed to read seed data", }, { name: "invalid JSON file", path: "/tmp/invalid.json", expectError: true, errorMsg: "failed to read seed data", }, { name: "non-existent HTTP URL", path: "http://non-existent-domain-12345.com/seed.json", expectError: true, errorMsg: "failed to read seed data", }, } // Create invalid JSON file for testing invalidJSON := []byte("{invalid json}") tempFile, err := os.CreateTemp("", "invalid-*.json") require.NoError(t, err) defer os.Remove(tempFile.Name()) err = os.WriteFile(tempFile.Name(), invalidJSON, 0600) require.NoError(t, err) // Update test case to use temp file for i := range tests { if tests[i].path == "/tmp/invalid.json" { tests[i].path = tempFile.Name() break } } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { err := importerService.ImportFromPath(context.Background(), tt.path) if tt.expectError { assert.Error(t, err) if tt.errorMsg != "" { assert.Contains(t, err.Error(), tt.errorMsg) } } else { assert.NoError(t, err) } }) } }