All checks were successful
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-school (push) Successful in 28s
CI / test-go-edu-search (push) Successful in 27s
CI / test-python-klausur (push) Successful in 1m45s
CI / test-python-agent-core (push) Successful in 16s
CI / test-nodejs-website (push) Successful in 21s
- edu-search-service von breakpilot-pwa nach breakpilot-lehrer kopiert (ohne vendor) - opensearch + edu-search-service in docker-compose.yml hinzugefuegt - voice-service aus docker-compose.yml entfernt (jetzt in breakpilot-core) - geo-service aus docker-compose.yml entfernt (nicht mehr benoetigt) - CI/CD: edu-search-service zu Gitea Actions und Woodpecker hinzugefuegt (Go lint, test mit go mod download, build, SBOM) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
631 lines
18 KiB
Go
631 lines
18 KiB
Go
package handlers
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/breakpilot/edu-search-service/internal/orchestrator"
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
// MockAudienceRepository implements orchestrator.AudienceRepository for testing
|
|
type MockAudienceRepository struct {
|
|
audiences []orchestrator.Audience
|
|
exports []orchestrator.AudienceExport
|
|
members []orchestrator.AudienceMember
|
|
}
|
|
|
|
func NewMockAudienceRepository() *MockAudienceRepository {
|
|
return &MockAudienceRepository{
|
|
audiences: make([]orchestrator.Audience, 0),
|
|
exports: make([]orchestrator.AudienceExport, 0),
|
|
members: make([]orchestrator.AudienceMember, 0),
|
|
}
|
|
}
|
|
|
|
func (m *MockAudienceRepository) CreateAudience(ctx context.Context, audience *orchestrator.Audience) error {
|
|
audience.ID = uuid.New()
|
|
audience.CreatedAt = time.Now()
|
|
audience.UpdatedAt = time.Now()
|
|
m.audiences = append(m.audiences, *audience)
|
|
return nil
|
|
}
|
|
|
|
func (m *MockAudienceRepository) GetAudience(ctx context.Context, id uuid.UUID) (*orchestrator.Audience, error) {
|
|
for i := range m.audiences {
|
|
if m.audiences[i].ID == id {
|
|
return &m.audiences[i], nil
|
|
}
|
|
}
|
|
return nil, context.DeadlineExceeded // simulate not found
|
|
}
|
|
|
|
func (m *MockAudienceRepository) ListAudiences(ctx context.Context, activeOnly bool) ([]orchestrator.Audience, error) {
|
|
if activeOnly {
|
|
var active []orchestrator.Audience
|
|
for _, a := range m.audiences {
|
|
if a.IsActive {
|
|
active = append(active, a)
|
|
}
|
|
}
|
|
return active, nil
|
|
}
|
|
return m.audiences, nil
|
|
}
|
|
|
|
func (m *MockAudienceRepository) UpdateAudience(ctx context.Context, audience *orchestrator.Audience) error {
|
|
for i := range m.audiences {
|
|
if m.audiences[i].ID == audience.ID {
|
|
m.audiences[i].Name = audience.Name
|
|
m.audiences[i].Description = audience.Description
|
|
m.audiences[i].Filters = audience.Filters
|
|
m.audiences[i].IsActive = audience.IsActive
|
|
m.audiences[i].UpdatedAt = time.Now()
|
|
audience.UpdatedAt = m.audiences[i].UpdatedAt
|
|
return nil
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (m *MockAudienceRepository) DeleteAudience(ctx context.Context, id uuid.UUID) error {
|
|
for i := range m.audiences {
|
|
if m.audiences[i].ID == id {
|
|
m.audiences[i].IsActive = false
|
|
return nil
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (m *MockAudienceRepository) GetAudienceMembers(ctx context.Context, id uuid.UUID, limit, offset int) ([]orchestrator.AudienceMember, int, error) {
|
|
// Return mock members
|
|
if len(m.members) == 0 {
|
|
m.members = []orchestrator.AudienceMember{
|
|
{
|
|
ID: uuid.New(),
|
|
Name: "Prof. Dr. Test Person",
|
|
Email: "test@university.de",
|
|
Position: "professor",
|
|
University: "Test Universität",
|
|
Department: "Informatik",
|
|
SubjectArea: "Informatik",
|
|
PublicationCount: 42,
|
|
},
|
|
{
|
|
ID: uuid.New(),
|
|
Name: "Dr. Another Person",
|
|
Email: "another@university.de",
|
|
Position: "researcher",
|
|
University: "Test Universität",
|
|
Department: "Mathematik",
|
|
SubjectArea: "Mathematik",
|
|
PublicationCount: 15,
|
|
},
|
|
}
|
|
}
|
|
|
|
total := len(m.members)
|
|
if offset >= total {
|
|
return []orchestrator.AudienceMember{}, total, nil
|
|
}
|
|
|
|
end := offset + limit
|
|
if end > total {
|
|
end = total
|
|
}
|
|
|
|
return m.members[offset:end], total, nil
|
|
}
|
|
|
|
func (m *MockAudienceRepository) UpdateAudienceCount(ctx context.Context, id uuid.UUID) (int, error) {
|
|
count := len(m.members)
|
|
for i := range m.audiences {
|
|
if m.audiences[i].ID == id {
|
|
m.audiences[i].MemberCount = count
|
|
now := time.Now()
|
|
m.audiences[i].LastCountUpdate = &now
|
|
}
|
|
}
|
|
return count, nil
|
|
}
|
|
|
|
func (m *MockAudienceRepository) CreateExport(ctx context.Context, export *orchestrator.AudienceExport) error {
|
|
export.ID = uuid.New()
|
|
export.CreatedAt = time.Now()
|
|
m.exports = append(m.exports, *export)
|
|
return nil
|
|
}
|
|
|
|
func (m *MockAudienceRepository) ListExports(ctx context.Context, audienceID uuid.UUID) ([]orchestrator.AudienceExport, error) {
|
|
var exports []orchestrator.AudienceExport
|
|
for _, e := range m.exports {
|
|
if e.AudienceID == audienceID {
|
|
exports = append(exports, e)
|
|
}
|
|
}
|
|
return exports, nil
|
|
}
|
|
|
|
func setupAudienceRouter(repo *MockAudienceRepository) *gin.Engine {
|
|
gin.SetMode(gin.TestMode)
|
|
router := gin.New()
|
|
|
|
handler := NewAudienceHandler(repo)
|
|
|
|
v1 := router.Group("/v1")
|
|
SetupAudienceRoutes(v1, handler)
|
|
|
|
return router
|
|
}
|
|
|
|
func TestAudienceHandler_ListAudiences_Empty(t *testing.T) {
|
|
repo := NewMockAudienceRepository()
|
|
router := setupAudienceRouter(repo)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/v1/audiences", nil)
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusOK {
|
|
t.Errorf("Expected status %d, got %d", http.StatusOK, w.Code)
|
|
}
|
|
|
|
var response struct {
|
|
Audiences []orchestrator.Audience `json:"audiences"`
|
|
Count int `json:"count"`
|
|
}
|
|
if err := json.Unmarshal(w.Body.Bytes(), &response); err != nil {
|
|
t.Fatalf("Failed to unmarshal response: %v", err)
|
|
}
|
|
|
|
if response.Count != 0 {
|
|
t.Errorf("Expected 0 audiences, got %d", response.Count)
|
|
}
|
|
}
|
|
|
|
func TestAudienceHandler_CreateAudience(t *testing.T) {
|
|
repo := NewMockAudienceRepository()
|
|
router := setupAudienceRouter(repo)
|
|
|
|
body := CreateAudienceRequest{
|
|
Name: "Test Audience",
|
|
Description: "A test audience for professors",
|
|
Filters: orchestrator.AudienceFilters{
|
|
PositionTypes: []string{"professor"},
|
|
States: []string{"BW", "BY"},
|
|
},
|
|
CreatedBy: "test-admin",
|
|
}
|
|
|
|
bodyJSON, _ := json.Marshal(body)
|
|
req := httptest.NewRequest(http.MethodPost, "/v1/audiences", bytes.NewBuffer(bodyJSON))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusCreated {
|
|
t.Errorf("Expected status %d, got %d: %s", http.StatusCreated, w.Code, w.Body.String())
|
|
}
|
|
|
|
var response orchestrator.Audience
|
|
if err := json.Unmarshal(w.Body.Bytes(), &response); err != nil {
|
|
t.Fatalf("Failed to unmarshal response: %v", err)
|
|
}
|
|
|
|
if response.Name != "Test Audience" {
|
|
t.Errorf("Expected name 'Test Audience', got '%s'", response.Name)
|
|
}
|
|
|
|
if !response.IsActive {
|
|
t.Errorf("Expected audience to be active")
|
|
}
|
|
|
|
if len(repo.audiences) != 1 {
|
|
t.Errorf("Expected 1 audience in repo, got %d", len(repo.audiences))
|
|
}
|
|
}
|
|
|
|
func TestAudienceHandler_CreateAudience_InvalidJSON(t *testing.T) {
|
|
repo := NewMockAudienceRepository()
|
|
router := setupAudienceRouter(repo)
|
|
|
|
req := httptest.NewRequest(http.MethodPost, "/v1/audiences", bytes.NewBuffer([]byte("invalid json")))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusBadRequest {
|
|
t.Errorf("Expected status %d, got %d", http.StatusBadRequest, w.Code)
|
|
}
|
|
}
|
|
|
|
func TestAudienceHandler_CreateAudience_MissingName(t *testing.T) {
|
|
repo := NewMockAudienceRepository()
|
|
router := setupAudienceRouter(repo)
|
|
|
|
body := map[string]interface{}{
|
|
"description": "Missing name field",
|
|
}
|
|
|
|
bodyJSON, _ := json.Marshal(body)
|
|
req := httptest.NewRequest(http.MethodPost, "/v1/audiences", bytes.NewBuffer(bodyJSON))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusBadRequest {
|
|
t.Errorf("Expected status %d, got %d", http.StatusBadRequest, w.Code)
|
|
}
|
|
}
|
|
|
|
func TestAudienceHandler_GetAudience(t *testing.T) {
|
|
repo := NewMockAudienceRepository()
|
|
router := setupAudienceRouter(repo)
|
|
|
|
// Create an audience first
|
|
audience := orchestrator.Audience{
|
|
ID: uuid.New(),
|
|
Name: "Test Audience",
|
|
Description: "Test description",
|
|
IsActive: true,
|
|
CreatedAt: time.Now(),
|
|
UpdatedAt: time.Now(),
|
|
}
|
|
repo.audiences = append(repo.audiences, audience)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/v1/audiences/"+audience.ID.String(), nil)
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusOK {
|
|
t.Errorf("Expected status %d, got %d: %s", http.StatusOK, w.Code, w.Body.String())
|
|
}
|
|
|
|
var response orchestrator.Audience
|
|
if err := json.Unmarshal(w.Body.Bytes(), &response); err != nil {
|
|
t.Fatalf("Failed to unmarshal response: %v", err)
|
|
}
|
|
|
|
if response.Name != "Test Audience" {
|
|
t.Errorf("Expected name 'Test Audience', got '%s'", response.Name)
|
|
}
|
|
}
|
|
|
|
func TestAudienceHandler_GetAudience_InvalidID(t *testing.T) {
|
|
repo := NewMockAudienceRepository()
|
|
router := setupAudienceRouter(repo)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/v1/audiences/invalid-uuid", nil)
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusBadRequest {
|
|
t.Errorf("Expected status %d, got %d", http.StatusBadRequest, w.Code)
|
|
}
|
|
}
|
|
|
|
func TestAudienceHandler_GetAudience_NotFound(t *testing.T) {
|
|
repo := NewMockAudienceRepository()
|
|
router := setupAudienceRouter(repo)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/v1/audiences/"+uuid.New().String(), nil)
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusNotFound {
|
|
t.Errorf("Expected status %d, got %d", http.StatusNotFound, w.Code)
|
|
}
|
|
}
|
|
|
|
func TestAudienceHandler_UpdateAudience(t *testing.T) {
|
|
repo := NewMockAudienceRepository()
|
|
router := setupAudienceRouter(repo)
|
|
|
|
// Create an audience first
|
|
audience := orchestrator.Audience{
|
|
ID: uuid.New(),
|
|
Name: "Old Name",
|
|
Description: "Old description",
|
|
IsActive: true,
|
|
CreatedAt: time.Now(),
|
|
UpdatedAt: time.Now(),
|
|
}
|
|
repo.audiences = append(repo.audiences, audience)
|
|
|
|
body := UpdateAudienceRequest{
|
|
Name: "New Name",
|
|
Description: "New description",
|
|
IsActive: true,
|
|
}
|
|
|
|
bodyJSON, _ := json.Marshal(body)
|
|
req := httptest.NewRequest(http.MethodPut, "/v1/audiences/"+audience.ID.String(), bytes.NewBuffer(bodyJSON))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusOK {
|
|
t.Errorf("Expected status %d, got %d: %s", http.StatusOK, w.Code, w.Body.String())
|
|
}
|
|
|
|
// Verify the update
|
|
if repo.audiences[0].Name != "New Name" {
|
|
t.Errorf("Expected name 'New Name', got '%s'", repo.audiences[0].Name)
|
|
}
|
|
}
|
|
|
|
func TestAudienceHandler_DeleteAudience(t *testing.T) {
|
|
repo := NewMockAudienceRepository()
|
|
router := setupAudienceRouter(repo)
|
|
|
|
// Create an audience first
|
|
audience := orchestrator.Audience{
|
|
ID: uuid.New(),
|
|
Name: "To Delete",
|
|
IsActive: true,
|
|
CreatedAt: time.Now(),
|
|
UpdatedAt: time.Now(),
|
|
}
|
|
repo.audiences = append(repo.audiences, audience)
|
|
|
|
req := httptest.NewRequest(http.MethodDelete, "/v1/audiences/"+audience.ID.String(), nil)
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusOK {
|
|
t.Errorf("Expected status %d, got %d", http.StatusOK, w.Code)
|
|
}
|
|
|
|
// Verify soft delete
|
|
if repo.audiences[0].IsActive {
|
|
t.Errorf("Expected audience to be inactive after delete")
|
|
}
|
|
}
|
|
|
|
func TestAudienceHandler_GetAudienceMembers(t *testing.T) {
|
|
repo := NewMockAudienceRepository()
|
|
router := setupAudienceRouter(repo)
|
|
|
|
// Create an audience first
|
|
audience := orchestrator.Audience{
|
|
ID: uuid.New(),
|
|
Name: "Test Audience",
|
|
IsActive: true,
|
|
CreatedAt: time.Now(),
|
|
UpdatedAt: time.Now(),
|
|
}
|
|
repo.audiences = append(repo.audiences, audience)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/v1/audiences/"+audience.ID.String()+"/members", nil)
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusOK {
|
|
t.Errorf("Expected status %d, got %d: %s", http.StatusOK, w.Code, w.Body.String())
|
|
}
|
|
|
|
var response struct {
|
|
Members []orchestrator.AudienceMember `json:"members"`
|
|
Count int `json:"count"`
|
|
TotalCount int `json:"total_count"`
|
|
}
|
|
if err := json.Unmarshal(w.Body.Bytes(), &response); err != nil {
|
|
t.Fatalf("Failed to unmarshal response: %v", err)
|
|
}
|
|
|
|
if response.TotalCount != 2 {
|
|
t.Errorf("Expected 2 total members, got %d", response.TotalCount)
|
|
}
|
|
}
|
|
|
|
func TestAudienceHandler_GetAudienceMembers_WithPagination(t *testing.T) {
|
|
repo := NewMockAudienceRepository()
|
|
router := setupAudienceRouter(repo)
|
|
|
|
audience := orchestrator.Audience{
|
|
ID: uuid.New(),
|
|
Name: "Test Audience",
|
|
IsActive: true,
|
|
CreatedAt: time.Now(),
|
|
UpdatedAt: time.Now(),
|
|
}
|
|
repo.audiences = append(repo.audiences, audience)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/v1/audiences/"+audience.ID.String()+"/members?limit=1&offset=0", nil)
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusOK {
|
|
t.Errorf("Expected status %d, got %d", http.StatusOK, w.Code)
|
|
}
|
|
|
|
var response struct {
|
|
Members []orchestrator.AudienceMember `json:"members"`
|
|
Count int `json:"count"`
|
|
Limit int `json:"limit"`
|
|
Offset int `json:"offset"`
|
|
}
|
|
if err := json.Unmarshal(w.Body.Bytes(), &response); err != nil {
|
|
t.Fatalf("Failed to unmarshal response: %v", err)
|
|
}
|
|
|
|
if response.Count != 1 {
|
|
t.Errorf("Expected 1 member in response, got %d", response.Count)
|
|
}
|
|
|
|
if response.Limit != 1 {
|
|
t.Errorf("Expected limit 1, got %d", response.Limit)
|
|
}
|
|
}
|
|
|
|
func TestAudienceHandler_RefreshAudienceCount(t *testing.T) {
|
|
repo := NewMockAudienceRepository()
|
|
router := setupAudienceRouter(repo)
|
|
|
|
audience := orchestrator.Audience{
|
|
ID: uuid.New(),
|
|
Name: "Test Audience",
|
|
IsActive: true,
|
|
MemberCount: 0,
|
|
CreatedAt: time.Now(),
|
|
UpdatedAt: time.Now(),
|
|
}
|
|
repo.audiences = append(repo.audiences, audience)
|
|
|
|
// Pre-initialize members so count works correctly
|
|
repo.members = []orchestrator.AudienceMember{
|
|
{ID: uuid.New(), Name: "Test Person 1"},
|
|
{ID: uuid.New(), Name: "Test Person 2"},
|
|
}
|
|
|
|
req := httptest.NewRequest(http.MethodPost, "/v1/audiences/"+audience.ID.String()+"/refresh", nil)
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusOK {
|
|
t.Errorf("Expected status %d, got %d", http.StatusOK, w.Code)
|
|
}
|
|
|
|
var response struct {
|
|
AudienceID string `json:"audience_id"`
|
|
MemberCount int `json:"member_count"`
|
|
}
|
|
if err := json.Unmarshal(w.Body.Bytes(), &response); err != nil {
|
|
t.Fatalf("Failed to unmarshal response: %v", err)
|
|
}
|
|
|
|
if response.MemberCount != 2 {
|
|
t.Errorf("Expected member_count 2, got %d", response.MemberCount)
|
|
}
|
|
}
|
|
|
|
func TestAudienceHandler_CreateExport(t *testing.T) {
|
|
repo := NewMockAudienceRepository()
|
|
router := setupAudienceRouter(repo)
|
|
|
|
audience := orchestrator.Audience{
|
|
ID: uuid.New(),
|
|
Name: "Test Audience",
|
|
IsActive: true,
|
|
CreatedAt: time.Now(),
|
|
UpdatedAt: time.Now(),
|
|
}
|
|
repo.audiences = append(repo.audiences, audience)
|
|
|
|
body := CreateExportRequest{
|
|
ExportType: "csv",
|
|
Purpose: "Newsletter December 2024",
|
|
ExportedBy: "admin",
|
|
}
|
|
|
|
bodyJSON, _ := json.Marshal(body)
|
|
req := httptest.NewRequest(http.MethodPost, "/v1/audiences/"+audience.ID.String()+"/exports", bytes.NewBuffer(bodyJSON))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusCreated {
|
|
t.Errorf("Expected status %d, got %d: %s", http.StatusCreated, w.Code, w.Body.String())
|
|
}
|
|
|
|
var response orchestrator.AudienceExport
|
|
if err := json.Unmarshal(w.Body.Bytes(), &response); err != nil {
|
|
t.Fatalf("Failed to unmarshal response: %v", err)
|
|
}
|
|
|
|
if response.ExportType != "csv" {
|
|
t.Errorf("Expected export_type 'csv', got '%s'", response.ExportType)
|
|
}
|
|
|
|
if response.RecordCount != 2 {
|
|
t.Errorf("Expected record_count 2, got %d", response.RecordCount)
|
|
}
|
|
}
|
|
|
|
func TestAudienceHandler_ListExports(t *testing.T) {
|
|
repo := NewMockAudienceRepository()
|
|
router := setupAudienceRouter(repo)
|
|
|
|
audience := orchestrator.Audience{
|
|
ID: uuid.New(),
|
|
Name: "Test Audience",
|
|
IsActive: true,
|
|
CreatedAt: time.Now(),
|
|
UpdatedAt: time.Now(),
|
|
}
|
|
repo.audiences = append(repo.audiences, audience)
|
|
|
|
// Add an export
|
|
export := orchestrator.AudienceExport{
|
|
ID: uuid.New(),
|
|
AudienceID: audience.ID,
|
|
ExportType: "csv",
|
|
RecordCount: 100,
|
|
Purpose: "Test export",
|
|
CreatedAt: time.Now(),
|
|
}
|
|
repo.exports = append(repo.exports, export)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/v1/audiences/"+audience.ID.String()+"/exports", nil)
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusOK {
|
|
t.Errorf("Expected status %d, got %d", http.StatusOK, w.Code)
|
|
}
|
|
|
|
var response struct {
|
|
Exports []orchestrator.AudienceExport `json:"exports"`
|
|
Count int `json:"count"`
|
|
}
|
|
if err := json.Unmarshal(w.Body.Bytes(), &response); err != nil {
|
|
t.Fatalf("Failed to unmarshal response: %v", err)
|
|
}
|
|
|
|
if response.Count != 1 {
|
|
t.Errorf("Expected 1 export, got %d", response.Count)
|
|
}
|
|
}
|
|
|
|
func TestAudienceHandler_ListAudiences_ActiveOnly(t *testing.T) {
|
|
repo := NewMockAudienceRepository()
|
|
router := setupAudienceRouter(repo)
|
|
|
|
// Add active and inactive audiences
|
|
repo.audiences = []orchestrator.Audience{
|
|
{ID: uuid.New(), Name: "Active", IsActive: true, CreatedAt: time.Now(), UpdatedAt: time.Now()},
|
|
{ID: uuid.New(), Name: "Inactive", IsActive: false, CreatedAt: time.Now(), UpdatedAt: time.Now()},
|
|
}
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/v1/audiences?active_only=true", nil)
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusOK {
|
|
t.Errorf("Expected status %d, got %d", http.StatusOK, w.Code)
|
|
}
|
|
|
|
var response struct {
|
|
Audiences []orchestrator.Audience `json:"audiences"`
|
|
Count int `json:"count"`
|
|
}
|
|
if err := json.Unmarshal(w.Body.Bytes(), &response); err != nil {
|
|
t.Fatalf("Failed to unmarshal response: %v", err)
|
|
}
|
|
|
|
if response.Count != 1 {
|
|
t.Errorf("Expected 1 active audience, got %d", response.Count)
|
|
}
|
|
|
|
if response.Audiences[0].Name != "Active" {
|
|
t.Errorf("Expected audience 'Active', got '%s'", response.Audiences[0].Name)
|
|
}
|
|
}
|