Add full monorepo: virtual-banker, backend, frontend, docs, scripts, deployment
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
231
backend/api/rest/api_test.go
Normal file
231
backend/api/rest/api_test.go
Normal file
@@ -0,0 +1,231 @@
|
||||
package rest_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/explorer/backend/api/rest"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// setupTestServer creates a test server with a test database
|
||||
func setupTestServer(t *testing.T) (*rest.Server, *http.ServeMux) {
|
||||
// Use test database or in-memory database
|
||||
// For now, we'll use a mock approach
|
||||
db, err := setupTestDB(t)
|
||||
if err != nil {
|
||||
t.Skipf("Skipping test: database not available: %v", err)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
server := rest.NewServer(db, 138) // ChainID 138
|
||||
mux := http.NewServeMux()
|
||||
server.SetupRoutes(mux)
|
||||
|
||||
return server, mux
|
||||
}
|
||||
|
||||
// setupTestDB creates a test database connection
|
||||
func setupTestDB(t *testing.T) (*pgxpool.Pool, error) {
|
||||
// In a real test, you would use a test database
|
||||
// For now, return nil to skip database-dependent tests
|
||||
// TODO: Set up test database connection
|
||||
// This allows tests to run without a database connection
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// TestHealthEndpoint tests the health check endpoint
|
||||
func TestHealthEndpoint(t *testing.T) {
|
||||
_, mux := setupTestServer(t)
|
||||
|
||||
req := httptest.NewRequest("GET", "/health", nil)
|
||||
w := httptest.NewRecorder()
|
||||
mux.ServeHTTP(w, req)
|
||||
|
||||
assert.Equal(t, http.StatusOK, w.Code)
|
||||
|
||||
var response map[string]interface{}
|
||||
err := json.Unmarshal(w.Body.Bytes(), &response)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "ok", response["status"])
|
||||
}
|
||||
|
||||
// TestListBlocks tests the blocks list endpoint
|
||||
func TestListBlocks(t *testing.T) {
|
||||
_, mux := setupTestServer(t)
|
||||
|
||||
req := httptest.NewRequest("GET", "/api/v1/blocks?limit=10&page=1", nil)
|
||||
w := httptest.NewRecorder()
|
||||
mux.ServeHTTP(w, req)
|
||||
|
||||
// Should return 200 or 500 depending on database connection
|
||||
assert.True(t, w.Code == http.StatusOK || w.Code == http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
// TestGetBlockByNumber tests getting a block by number
|
||||
func TestGetBlockByNumber(t *testing.T) {
|
||||
_, mux := setupTestServer(t)
|
||||
|
||||
req := httptest.NewRequest("GET", "/api/v1/blocks/138/1000", nil)
|
||||
w := httptest.NewRecorder()
|
||||
mux.ServeHTTP(w, req)
|
||||
|
||||
// Should return 200, 404, or 500 depending on database and block existence
|
||||
assert.True(t, w.Code == http.StatusOK || w.Code == http.StatusNotFound || w.Code == http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
// TestListTransactions tests the transactions list endpoint
|
||||
func TestListTransactions(t *testing.T) {
|
||||
_, mux := setupTestServer(t)
|
||||
|
||||
req := httptest.NewRequest("GET", "/api/v1/transactions?limit=10&page=1", nil)
|
||||
w := httptest.NewRecorder()
|
||||
mux.ServeHTTP(w, req)
|
||||
|
||||
assert.True(t, w.Code == http.StatusOK || w.Code == http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
// TestGetTransactionByHash tests getting a transaction by hash
|
||||
func TestGetTransactionByHash(t *testing.T) {
|
||||
_, mux := setupTestServer(t)
|
||||
|
||||
req := httptest.NewRequest("GET", "/api/v1/transactions/138/0x1234567890abcdef", nil)
|
||||
w := httptest.NewRecorder()
|
||||
mux.ServeHTTP(w, req)
|
||||
|
||||
assert.True(t, w.Code == http.StatusOK || w.Code == http.StatusNotFound || w.Code == http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
// TestSearchEndpoint tests the unified search endpoint
|
||||
func TestSearchEndpoint(t *testing.T) {
|
||||
_, mux := setupTestServer(t)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
query string
|
||||
wantCode int
|
||||
}{
|
||||
{"block number", "?q=1000", http.StatusOK},
|
||||
{"address", "?q=0x1234567890abcdef1234567890abcdef12345678", http.StatusOK},
|
||||
{"transaction hash", "?q=0xabcdef1234567890abcdef1234567890abcdef12", http.StatusOK},
|
||||
{"empty query", "?q=", http.StatusBadRequest},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
req := httptest.NewRequest("GET", "/api/v1/search"+tc.query, nil)
|
||||
w := httptest.NewRecorder()
|
||||
mux.ServeHTTP(w, req)
|
||||
|
||||
assert.True(t, w.Code == tc.wantCode || w.Code == http.StatusInternalServerError)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestTrack1Endpoints tests Track 1 (public) endpoints
|
||||
func TestTrack1Endpoints(t *testing.T) {
|
||||
_, mux := setupTestServer(t)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
endpoint string
|
||||
method string
|
||||
}{
|
||||
{"latest blocks", "/api/v1/track1/blocks/latest", "GET"},
|
||||
{"latest transactions", "/api/v1/track1/txs/latest", "GET"},
|
||||
{"bridge status", "/api/v1/track1/bridge/status", "GET"},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
req := httptest.NewRequest(tc.method, tc.endpoint, nil)
|
||||
w := httptest.NewRecorder()
|
||||
mux.ServeHTTP(w, req)
|
||||
|
||||
// Track 1 endpoints should be accessible without auth
|
||||
assert.True(t, w.Code == http.StatusOK || w.Code == http.StatusInternalServerError)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestCORSHeaders tests CORS headers are present
|
||||
func TestCORSHeaders(t *testing.T) {
|
||||
_, mux := setupTestServer(t)
|
||||
|
||||
req := httptest.NewRequest("GET", "/health", nil)
|
||||
w := httptest.NewRecorder()
|
||||
mux.ServeHTTP(w, req)
|
||||
|
||||
// Check for CORS headers (if implemented)
|
||||
// This is a placeholder - actual implementation may vary
|
||||
assert.NotNil(t, w.Header())
|
||||
}
|
||||
|
||||
// TestErrorHandling tests error responses
|
||||
func TestErrorHandling(t *testing.T) {
|
||||
_, mux := setupTestServer(t)
|
||||
|
||||
// Test invalid block number
|
||||
req := httptest.NewRequest("GET", "/api/v1/blocks/138/invalid", nil)
|
||||
w := httptest.NewRecorder()
|
||||
mux.ServeHTTP(w, req)
|
||||
|
||||
assert.True(t, w.Code >= http.StatusBadRequest)
|
||||
|
||||
var errorResponse map[string]interface{}
|
||||
err := json.Unmarshal(w.Body.Bytes(), &errorResponse)
|
||||
if err == nil {
|
||||
assert.NotNil(t, errorResponse["error"])
|
||||
}
|
||||
}
|
||||
|
||||
// TestPagination tests pagination parameters
|
||||
func TestPagination(t *testing.T) {
|
||||
_, mux := setupTestServer(t)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
query string
|
||||
wantCode int
|
||||
}{
|
||||
{"valid pagination", "?limit=10&page=1", http.StatusOK},
|
||||
{"large limit", "?limit=1000&page=1", http.StatusOK}, // Should be capped
|
||||
{"invalid page", "?limit=10&page=0", http.StatusBadRequest},
|
||||
{"negative limit", "?limit=-10&page=1", http.StatusBadRequest},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
req := httptest.NewRequest("GET", "/api/v1/blocks"+tc.query, nil)
|
||||
w := httptest.NewRecorder()
|
||||
mux.ServeHTTP(w, req)
|
||||
|
||||
assert.True(t, w.Code == tc.wantCode || w.Code == http.StatusInternalServerError)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestRequestTimeout tests request timeout handling
|
||||
func TestRequestTimeout(t *testing.T) {
|
||||
// This would test timeout behavior
|
||||
// Implementation depends on timeout middleware
|
||||
t.Skip("Requires timeout middleware implementation")
|
||||
}
|
||||
|
||||
// BenchmarkListBlocks benchmarks the blocks list endpoint
|
||||
func BenchmarkListBlocks(b *testing.B) {
|
||||
_, mux := setupTestServer(&testing.T{})
|
||||
|
||||
req := httptest.NewRequest("GET", "/api/v1/blocks?limit=10&page=1", nil)
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
w := httptest.NewRecorder()
|
||||
mux.ServeHTTP(w, req)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user