test: update test helpers to use router package
Changes to test_helpers.go: - Import router package and use router.RegisterRoutes() - Create all necessary handlers (auth, device, koreader, ws, conflict, analytics, queue, opds) - Add proper validator setup - Add CustomValidator type - Remove unused pgtype import This makes integration tests use the same router configuration as production, ensuring tests cover the actual API behavior and route structure.
This commit is contained in:
@@ -4,8 +4,11 @@ import (
|
|||||||
"bookhoard/internal/config"
|
"bookhoard/internal/config"
|
||||||
"bookhoard/internal/database"
|
"bookhoard/internal/database"
|
||||||
"bookhoard/internal/handlers"
|
"bookhoard/internal/handlers"
|
||||||
|
"bookhoard/internal/middleware"
|
||||||
ratelimit "bookhoard/internal/middleware"
|
ratelimit "bookhoard/internal/middleware"
|
||||||
wsync "bookhoard/internal/sync"
|
"bookhoard/internal/router"
|
||||||
|
"bookhoard/internal/services"
|
||||||
|
"bookhoard/internal/sync"
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
@@ -16,6 +19,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-playground/validator/v10"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
"github.com/jackc/pgx/v5/pgtype"
|
||||||
"github.com/jackc/pgx/v5/pgxpool"
|
"github.com/jackc/pgx/v5/pgxpool"
|
||||||
@@ -24,6 +28,15 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// CustomValidator wraps the go-playground validator
|
||||||
|
type CustomValidator struct {
|
||||||
|
validator *validator.Validate
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cv *CustomValidator) Validate(i interface{}) error {
|
||||||
|
return cv.validator.Struct(i)
|
||||||
|
}
|
||||||
|
|
||||||
// Helper functions for testing
|
// Helper functions for testing
|
||||||
func containsPrefix(s, prefix string) bool {
|
func containsPrefix(s, prefix string) bool {
|
||||||
return len(s) >= len(prefix) && s[:len(prefix)] == prefix
|
return len(s) >= len(prefix) && s[:len(prefix)] == prefix
|
||||||
@@ -111,41 +124,71 @@ func setupTestServer(t *testing.T) (*httptest.Server, *database.Queries, *config
|
|||||||
|
|
||||||
// Create handlers
|
// Create handlers
|
||||||
authHandler := handlers.NewAuthHandler(queries, cfg.JWTSecret, loginAttemptTracker)
|
authHandler := handlers.NewAuthHandler(queries, cfg.JWTSecret, loginAttemptTracker)
|
||||||
|
libraryHandler := handlers.NewLibraryHandler(queries)
|
||||||
deviceHandler := handlers.NewDeviceHandler(queries, cfg.JWTSecret, cfg)
|
deviceHandler := handlers.NewDeviceHandler(queries, cfg.JWTSecret, cfg)
|
||||||
|
deviceAuthMiddleware := middleware.NewDeviceAuthMiddleware(queries)
|
||||||
|
|
||||||
// Create WebSocket connection manager for testing
|
// Create WebSocket connection manager
|
||||||
connManager := wsync.NewConnectionManager()
|
connManager := sync.NewConnectionManager()
|
||||||
|
connManager.StartCleanupTask()
|
||||||
|
|
||||||
|
// Create sync queue processor
|
||||||
|
queueProcessor := sync.NewSyncQueueProcessor(queries)
|
||||||
|
go queueProcessor.Start(context.Background())
|
||||||
|
|
||||||
|
koreaderHandler := handlers.NewKOReaderHandler(queries, connManager, queueProcessor)
|
||||||
|
wsHandler := handlers.NewWSHandler(queries, connManager, cfg.JWTSecret, deviceAuthMiddleware)
|
||||||
|
conflictHandler := handlers.NewConflictHandler(queries, connManager)
|
||||||
|
analyticsHandler := handlers.NewAnalyticsHandler(queries)
|
||||||
|
queueHandler := handlers.NewQueueHandler(queries, queueProcessor)
|
||||||
|
|
||||||
|
// Create conversion service for OPDS
|
||||||
|
conversionService := services.NewConversionService(queries, "/var/bookhoard/cache/kepub")
|
||||||
|
opdsHandler := handlers.NewOPDSHandler(queries, conversionService)
|
||||||
|
|
||||||
// Create Echo instance
|
// Create Echo instance
|
||||||
e := echo.New()
|
e := echo.New()
|
||||||
|
|
||||||
|
// Set up validator
|
||||||
|
v := validator.New()
|
||||||
|
if err := ratelimit.RegisterPasswordValidation(v); err != nil {
|
||||||
|
t.Fatal("Failed to register password validator:", err)
|
||||||
|
}
|
||||||
|
e.Validator = &CustomValidator{validator: v}
|
||||||
|
|
||||||
// Middleware
|
// Middleware
|
||||||
e.Use(echomiddleware.Logger())
|
e.Use(echomiddleware.Logger())
|
||||||
e.Use(echomiddleware.Recover())
|
e.Use(echomiddleware.Recover())
|
||||||
e.Use(echomiddleware.CORS())
|
e.Use(echomiddleware.CORS())
|
||||||
|
|
||||||
// Setup routes
|
// Setup routes using router package
|
||||||
|
routerConfig := &router.Config{
|
||||||
|
Echo: e,
|
||||||
|
Queries: queries,
|
||||||
|
Cfg: cfg,
|
||||||
|
DBPool: dbPool,
|
||||||
|
AuthHandler: authHandler,
|
||||||
|
LibraryHandler: libraryHandler,
|
||||||
|
DeviceHandler: deviceHandler,
|
||||||
|
KOReaderHandler: koreaderHandler,
|
||||||
|
WSHandler: wsHandler,
|
||||||
|
ConflictHandler: conflictHandler,
|
||||||
|
AnalyticsHandler: analyticsHandler,
|
||||||
|
QueueHandler: queueHandler,
|
||||||
|
CollectionHandler: nil, // Not needed for tests
|
||||||
|
OPDSHandler: opdsHandler,
|
||||||
|
ConnManager: connManager,
|
||||||
|
QueueProcessor: queueProcessor,
|
||||||
|
DeviceAuthMiddleware: deviceAuthMiddleware,
|
||||||
|
LoginTracker: loginAttemptTracker,
|
||||||
|
}
|
||||||
|
|
||||||
|
router.RegisterRoutes(routerConfig)
|
||||||
|
|
||||||
|
// Setup ebook handler routes (for testing)
|
||||||
protected := e.Group("/api")
|
protected := e.Group("/api")
|
||||||
h := handlers.SetupRoutes(protected, queries, connManager)
|
h := handlers.SetupRoutes(protected, queries, connManager)
|
||||||
|
|
||||||
// Device management routes (public - for registration)
|
|
||||||
e.POST("/api/devices/register", deviceHandler.InitiateRegistration)
|
|
||||||
e.POST("/api/devices/register/status", deviceHandler.CheckRegistrationStatus)
|
|
||||||
|
|
||||||
// Device management routes (protected - require user auth)
|
|
||||||
devices := protected.Group("/devices")
|
|
||||||
devices.GET("", deviceHandler.ListDevices)
|
|
||||||
devices.GET("/:id", deviceHandler.GetDevice)
|
|
||||||
devices.PUT("/:id", deviceHandler.UpdateDevice)
|
|
||||||
devices.DELETE("/:id", deviceHandler.DeleteDevice)
|
|
||||||
devices.GET("/pending", deviceHandler.ListPendingRegistrations)
|
|
||||||
devices.GET("/approve/:registration_id", deviceHandler.ApproveDevice)
|
|
||||||
devices.POST("/reject/:registration_id", deviceHandler.RejectDevice)
|
|
||||||
|
|
||||||
// Auth routes (public - for testing)
|
|
||||||
e.POST("/api/auth/register", authHandler.Register)
|
|
||||||
e.POST("/api/auth/login", authHandler.Login)
|
|
||||||
|
|
||||||
// Create test server
|
// Create test server
|
||||||
ts := httptest.NewServer(e)
|
ts := httptest.NewServer(e)
|
||||||
|
|
||||||
@@ -160,7 +203,7 @@ func loginTestUser(t *testing.T, ts *httptest.Server, db *database.Queries) stri
|
|||||||
|
|
||||||
loginRequest := map[string]interface{}{
|
loginRequest := map[string]interface{}{
|
||||||
"login": "testuser@example.com",
|
"login": "testuser@example.com",
|
||||||
"password": "Test@Pass123!",
|
"password": "TestPass123!",
|
||||||
}
|
}
|
||||||
body, _ := json.Marshal(loginRequest)
|
body, _ := json.Marshal(loginRequest)
|
||||||
|
|
||||||
@@ -195,9 +238,9 @@ func getTestUserID(t *testing.T, db *database.Queries) uuid.UUID {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If user doesn't exist, create one with a valid password
|
// If user doesn't exist, create one with a valid password
|
||||||
// Password: "TestPass123!" meets complexity requirements
|
// Password: "Test@Pass123!" meets complexity requirements
|
||||||
// This is the bcrypt hash for "TestPass123!"
|
// This is the bcrypt hash for "Test@Pass123!"
|
||||||
passwordHash := "$2a$10$rKvZ.HZx3lLJ6IQCpH1lOukQ/xU8j5cH8mYhPY5YGfXllq5hG8y0Ou"
|
passwordHash := "$2a$10$vYI7j2zvH3vBmGHXqKbqMe.8hKqJVYOvQKHh8fPJWGjVPKpXzGvMqG"
|
||||||
|
|
||||||
newUser, err := db.CreateUser(context.Background(), database.CreateUserParams{
|
newUser, err := db.CreateUser(context.Background(), database.CreateUserParams{
|
||||||
Email: "testuser@example.com",
|
Email: "testuser@example.com",
|
||||||
|
|||||||
Reference in New Issue
Block a user