chore(release): v0.922 — Greenlight (handler tests: dashboard, presence)
This commit is contained in:
parent
12dbb5bbe4
commit
2a0a6a1ec9
3 changed files with 210 additions and 1 deletions
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
|||
0.921
|
||||
0.922
|
||||
|
|
|
|||
124
veza-backend-api/internal/handlers/dashboard_test.go
Normal file
124
veza-backend-api/internal/handlers/dashboard_test.go
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"veza-backend-api/internal/models"
|
||||
"veza-backend-api/internal/services"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// mockDashboardAuditService returns empty stats and activity for tests
|
||||
type mockDashboardAuditService struct {
|
||||
statsErr error
|
||||
activityErr error
|
||||
}
|
||||
|
||||
func (m *mockDashboardAuditService) GetStats(ctx context.Context, startDate, endDate time.Time) ([]*services.AuditStats, error) {
|
||||
if m.statsErr != nil {
|
||||
return nil, m.statsErr
|
||||
}
|
||||
return []*services.AuditStats{}, nil
|
||||
}
|
||||
|
||||
func (m *mockDashboardAuditService) GetUserActivity(ctx context.Context, userID uuid.UUID, limit int) ([]*services.AuditLog, error) {
|
||||
if m.activityErr != nil {
|
||||
return nil, m.activityErr
|
||||
}
|
||||
return []*services.AuditLog{}, nil
|
||||
}
|
||||
|
||||
// mockDashboardTrackService returns empty tracks for tests
|
||||
type mockDashboardTrackService struct {
|
||||
tracksErr error
|
||||
}
|
||||
|
||||
func (m *mockDashboardTrackService) ListTracks(ctx context.Context, params TrackListParamsForDashboard) ([]*models.Track, int64, error) {
|
||||
if m.tracksErr != nil {
|
||||
return nil, 0, m.tracksErr
|
||||
}
|
||||
return []*models.Track{}, 0, nil
|
||||
}
|
||||
|
||||
func TestDashboardHandler_GetDashboard_HappyPath(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
logger := zap.NewNop()
|
||||
handler := NewDashboardHandlerWithInterface(
|
||||
&mockDashboardAuditService{},
|
||||
&mockDashboardTrackService{},
|
||||
logger,
|
||||
)
|
||||
|
||||
router := gin.New()
|
||||
userID := uuid.New()
|
||||
router.Use(func(c *gin.Context) {
|
||||
c.Set("user_id", userID)
|
||||
c.Next()
|
||||
})
|
||||
router.GET("/dashboard", handler.GetDashboard())
|
||||
|
||||
req := httptest.NewRequest("GET", "/dashboard", nil)
|
||||
w := httptest.NewRecorder()
|
||||
router.ServeHTTP(w, req)
|
||||
|
||||
assert.Equal(t, http.StatusOK, w.Code)
|
||||
var resp APIResponse
|
||||
err := json.Unmarshal(w.Body.Bytes(), &resp)
|
||||
require.NoError(t, err)
|
||||
assert.True(t, resp.Success)
|
||||
assert.NotNil(t, resp.Data)
|
||||
}
|
||||
|
||||
func TestDashboardHandler_GetDashboard_Unauthorized(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
logger := zap.NewNop()
|
||||
handler := NewDashboardHandlerWithInterface(
|
||||
&mockDashboardAuditService{},
|
||||
&mockDashboardTrackService{},
|
||||
logger,
|
||||
)
|
||||
|
||||
router := gin.New()
|
||||
// No auth middleware - no user_id in context
|
||||
router.GET("/dashboard", handler.GetDashboard())
|
||||
|
||||
req := httptest.NewRequest("GET", "/dashboard", nil)
|
||||
w := httptest.NewRecorder()
|
||||
router.ServeHTTP(w, req)
|
||||
|
||||
assert.Equal(t, http.StatusUnauthorized, w.Code)
|
||||
}
|
||||
|
||||
func TestDashboardHandler_GetDashboard_WithQueryParams(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
logger := zap.NewNop()
|
||||
handler := NewDashboardHandlerWithInterface(
|
||||
&mockDashboardAuditService{},
|
||||
&mockDashboardTrackService{},
|
||||
logger,
|
||||
)
|
||||
|
||||
router := gin.New()
|
||||
userID := uuid.New()
|
||||
router.Use(func(c *gin.Context) {
|
||||
c.Set("user_id", userID)
|
||||
c.Next()
|
||||
})
|
||||
router.GET("/dashboard", handler.GetDashboard())
|
||||
|
||||
req := httptest.NewRequest("GET", "/dashboard?activity_limit=5&library_limit=3&stats_period=7d", nil)
|
||||
w := httptest.NewRecorder()
|
||||
router.ServeHTTP(w, req)
|
||||
|
||||
assert.Equal(t, http.StatusOK, w.Code)
|
||||
}
|
||||
85
veza-backend-api/internal/handlers/presence_handler_test.go
Normal file
85
veza-backend-api/internal/handlers/presence_handler_test.go
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"veza-backend-api/internal/models"
|
||||
"veza-backend-api/internal/services"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/driver/sqlite"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func setupPresenceHandler(t *testing.T) (*PresenceHandler, *gin.Engine) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
logger := zap.NewNop()
|
||||
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, db.AutoMigrate(&models.UserPresence{}))
|
||||
|
||||
presenceSvc := services.NewPresenceService(db, logger)
|
||||
handler := NewPresenceHandler(presenceSvc, logger)
|
||||
|
||||
router := gin.New()
|
||||
router.Use(func(c *gin.Context) {
|
||||
if uidStr := c.GetHeader("X-User-ID"); uidStr != "" {
|
||||
if uid, err := uuid.Parse(uidStr); err == nil {
|
||||
c.Set("user_id", uid)
|
||||
}
|
||||
}
|
||||
c.Next()
|
||||
})
|
||||
router.GET("/users/:id/presence", handler.GetPresence)
|
||||
router.PUT("/users/me/presence", handler.UpdatePresence)
|
||||
|
||||
return handler, router
|
||||
}
|
||||
|
||||
func TestPresenceHandler_GetPresence_InvalidUserID(t *testing.T) {
|
||||
_, router := setupPresenceHandler(t)
|
||||
|
||||
req := httptest.NewRequest("GET", "/users/invalid-id/presence", nil)
|
||||
w := httptest.NewRecorder()
|
||||
router.ServeHTTP(w, req)
|
||||
|
||||
assert.Equal(t, http.StatusBadRequest, w.Code)
|
||||
}
|
||||
|
||||
func TestPresenceHandler_GetPresence_NotFound(t *testing.T) {
|
||||
_, router := setupPresenceHandler(t)
|
||||
userID := uuid.New()
|
||||
viewerID := uuid.New()
|
||||
|
||||
// Pass X-User-ID so GetUserIDUUID (optional viewer) succeeds; request targets a different user with no presence
|
||||
req := httptest.NewRequest("GET", "/users/"+userID.String()+"/presence", nil)
|
||||
req.Header.Set("X-User-ID", viewerID.String())
|
||||
w := httptest.NewRecorder()
|
||||
router.ServeHTTP(w, req)
|
||||
|
||||
// Should return 200 with offline status when user has no presence
|
||||
assert.Equal(t, http.StatusOK, w.Code)
|
||||
var resp APIResponse
|
||||
require.NoError(t, json.Unmarshal(w.Body.Bytes(), &resp))
|
||||
assert.True(t, resp.Success)
|
||||
}
|
||||
|
||||
func TestPresenceHandler_UpdatePresence_Unauthorized(t *testing.T) {
|
||||
_, router := setupPresenceHandler(t)
|
||||
body := bytes.NewBufferString(`{"status":"online"}`)
|
||||
req := httptest.NewRequest("PUT", "/users/me/presence", body)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
w := httptest.NewRecorder()
|
||||
router.ServeHTTP(w, req)
|
||||
|
||||
// No user_id in context - GetUserIDUUID fails, handler returns 401 via RespondWithAppError
|
||||
assert.True(t, w.Code == http.StatusUnauthorized || w.Code == http.StatusBadRequest)
|
||||
}
|
||||
Loading…
Reference in a new issue