214 lines
8.1 KiB
Go
214 lines
8.1 KiB
Go
package repository
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/gochat/gochat/internal/model"
|
|
)
|
|
|
|
// helper to create a test ReportingEvent
|
|
func newTestReportingEvent(accountID uint, name string, value float64, inboxID *uint, eventStart time.Time, eventEnd time.Time) *model.ReportingEvent {
|
|
return &model.ReportingEvent{
|
|
AccountID: accountID,
|
|
InboxID: inboxID,
|
|
Name: name,
|
|
Value: value,
|
|
EventStartTime: eventStart,
|
|
EventEndTime: eventEnd,
|
|
}
|
|
}
|
|
|
|
// --- Test 1: Create ---
|
|
func TestReportingEventRepo_Create(t *testing.T) {
|
|
db := setupTestDB(t, &model.ReportingEvent{})
|
|
repo := NewReportingEventRepo(db)
|
|
|
|
event := newTestReportingEvent(1, model.MetricNameFirstResponse, 42.5, nil, time.Time{}, time.Time{})
|
|
err := repo.Create(context.Background(), event)
|
|
require.NoError(t, err)
|
|
assert.NotZero(t, event.ID)
|
|
assert.Equal(t, uint(1), event.AccountID)
|
|
assert.Equal(t, model.MetricNameFirstResponse, event.Name)
|
|
assert.Equal(t, 42.5, event.Value)
|
|
}
|
|
|
|
// --- Test 2: FindByAccountID ---
|
|
func TestReportingEventRepo_FindByAccountID(t *testing.T) {
|
|
db := setupTestDB(t, &model.ReportingEvent{})
|
|
repo := NewReportingEventRepo(db)
|
|
|
|
since := time.Date(2025, 1, 1, 0, 0, 0, 0, time.UTC)
|
|
until := time.Date(2025, 12, 31, 23, 59, 59, 0, time.UTC)
|
|
|
|
// Create events for account 1 within range
|
|
e1 := newTestReportingEvent(1, model.MetricNameFirstResponse, 10.0, nil, time.Time{}, time.Time{})
|
|
e1.CreatedAt = time.Date(2025, 6, 15, 12, 0, 0, 0, time.UTC)
|
|
require.NoError(t, db.Create(e1).Error)
|
|
|
|
e2 := newTestReportingEvent(1, model.MetricNameReplyTime, 20.0, nil, time.Time{}, time.Time{})
|
|
e2.CreatedAt = time.Date(2025, 7, 20, 12, 0, 0, 0, time.UTC)
|
|
require.NoError(t, db.Create(e2).Error)
|
|
|
|
// Create event for different account — should not be returned
|
|
e3 := newTestReportingEvent(2, model.MetricNameFirstResponse, 30.0, nil, time.Time{}, time.Time{})
|
|
e3.CreatedAt = time.Date(2025, 6, 15, 12, 0, 0, 0, time.UTC)
|
|
require.NoError(t, db.Create(e3).Error)
|
|
|
|
events, err := repo.FindByAccountID(context.Background(), 1, since, until)
|
|
require.NoError(t, err)
|
|
assert.Len(t, events, 2)
|
|
|
|
names := map[string]bool{}
|
|
for _, ev := range events {
|
|
names[ev.Name] = true
|
|
}
|
|
assert.True(t, names[model.MetricNameFirstResponse])
|
|
assert.True(t, names[model.MetricNameReplyTime])
|
|
}
|
|
|
|
// --- Test 3: FindByAccountID returns empty when no matches ---
|
|
func TestReportingEventRepo_FindByAccountID_NoMatches(t *testing.T) {
|
|
db := setupTestDB(t, &model.ReportingEvent{})
|
|
repo := NewReportingEventRepo(db)
|
|
|
|
since := time.Date(2025, 1, 1, 0, 0, 0, 0, time.UTC)
|
|
until := time.Date(2025, 12, 31, 23, 59, 59, 0, time.UTC)
|
|
|
|
events, err := repo.FindByAccountID(context.Background(), 999, since, until)
|
|
require.NoError(t, err)
|
|
assert.Empty(t, events)
|
|
}
|
|
|
|
// --- Test 4: FindByMetric ---
|
|
func TestReportingEventRepo_FindByMetric(t *testing.T) {
|
|
db := setupTestDB(t, &model.ReportingEvent{})
|
|
repo := NewReportingEventRepo(db)
|
|
|
|
since := time.Date(2025, 1, 1, 0, 0, 0, 0, time.UTC)
|
|
until := time.Date(2025, 12, 31, 23, 59, 59, 0, time.UTC)
|
|
|
|
// Create events with different metric names
|
|
e1 := newTestReportingEvent(1, model.MetricNameFirstResponse, 10.0, nil, time.Time{}, time.Time{})
|
|
e1.CreatedAt = time.Date(2025, 3, 10, 0, 0, 0, 0, time.UTC)
|
|
require.NoError(t, db.Create(e1).Error)
|
|
|
|
e2 := newTestReportingEvent(1, model.MetricNameFirstResponse, 15.0, nil, time.Time{}, time.Time{})
|
|
e2.CreatedAt = time.Date(2025, 4, 10, 0, 0, 0, 0, time.UTC)
|
|
require.NoError(t, db.Create(e2).Error)
|
|
|
|
e3 := newTestReportingEvent(1, model.MetricNameReplyTime, 20.0, nil, time.Time{}, time.Time{})
|
|
e3.CreatedAt = time.Date(2025, 5, 10, 0, 0, 0, 0, time.UTC)
|
|
require.NoError(t, db.Create(e3).Error)
|
|
|
|
events, err := repo.FindByMetric(context.Background(), 1, model.MetricNameFirstResponse, since, until)
|
|
require.NoError(t, err)
|
|
assert.Len(t, events, 2)
|
|
for _, ev := range events {
|
|
assert.Equal(t, model.MetricNameFirstResponse, ev.Name)
|
|
}
|
|
}
|
|
|
|
// --- Test 5: FindByInboxID ---
|
|
func TestReportingEventRepo_FindByInboxID(t *testing.T) {
|
|
db := setupTestDB(t, &model.ReportingEvent{})
|
|
repo := NewReportingEventRepo(db)
|
|
|
|
since := time.Date(2025, 1, 1, 0, 0, 0, 0, time.UTC)
|
|
until := time.Date(2025, 12, 31, 23, 59, 59, 0, time.UTC)
|
|
|
|
inboxID1 := uint(10)
|
|
inboxID2 := uint(20)
|
|
|
|
e1 := newTestReportingEvent(1, model.MetricNameFirstResponse, 10.0, &inboxID1, time.Time{}, time.Time{})
|
|
e1.CreatedAt = time.Date(2025, 6, 15, 0, 0, 0, 0, time.UTC)
|
|
require.NoError(t, db.Create(e1).Error)
|
|
|
|
e2 := newTestReportingEvent(1, model.MetricNameReplyTime, 25.0, &inboxID2, time.Time{}, time.Time{})
|
|
e2.CreatedAt = time.Date(2025, 6, 15, 0, 0, 0, 0, time.UTC)
|
|
require.NoError(t, db.Create(e2).Error)
|
|
|
|
// Should only return events for inbox 10 under account 1
|
|
events, err := repo.FindByInboxID(context.Background(), 1, inboxID1, since, until)
|
|
require.NoError(t, err)
|
|
assert.Len(t, events, 1)
|
|
assert.Equal(t, inboxID1, *events[0].InboxID)
|
|
assert.Equal(t, model.MetricNameFirstResponse, events[0].Name)
|
|
}
|
|
|
|
// --- Test 6: FindByDateRange (PG-only: uses event_start_time / event_end_time range queries) ---
|
|
func TestReportingEventRepo_FindByDateRange(t *testing.T) {
|
|
skipIfSQLite(t) // event_start_time/event_end_time range queries rely on PG timestamp semantics
|
|
|
|
db := setupTestDB(t, &model.ReportingEvent{})
|
|
repo := NewReportingEventRepo(db)
|
|
|
|
since := time.Date(2025, 1, 1, 0, 0, 0, 0, time.UTC)
|
|
until := time.Date(2025, 12, 31, 23, 59, 59, 0, time.UTC)
|
|
|
|
start1 := time.Date(2025, 3, 1, 0, 0, 0, 0, time.UTC)
|
|
end1 := time.Date(2025, 3, 31, 23, 59, 59, 0, time.UTC)
|
|
|
|
e1 := newTestReportingEvent(1, model.MetricNameResolutionTime, 300.0, nil, start1, end1)
|
|
require.NoError(t, db.Create(e1).Error)
|
|
|
|
// Event outside the date range (event_start_time < since)
|
|
start2 := time.Date(2024, 12, 1, 0, 0, 0, 0, time.UTC)
|
|
end2 := time.Date(2024, 12, 31, 23, 59, 59, 0, time.UTC)
|
|
e2 := newTestReportingEvent(1, model.MetricNameResolutionTime, 500.0, nil, start2, end2)
|
|
require.NoError(t, db.Create(e2).Error)
|
|
|
|
events, err := repo.FindByDateRange(context.Background(), 1, since, until)
|
|
require.NoError(t, err)
|
|
assert.Len(t, events, 1)
|
|
assert.Equal(t, e1.ID, events[0].ID)
|
|
}
|
|
|
|
// --- Test 7: AggregateByMetric (PG-only: uses COALESCE/AVG aggregation) ---
|
|
func TestReportingEventRepo_AggregateByMetric(t *testing.T) {
|
|
skipIfSQLite(t) // COALESCE(AVG(value), 0) aggregation uses PG-specific semantics
|
|
|
|
db := setupTestDB(t, &model.ReportingEvent{})
|
|
repo := NewReportingEventRepo(db)
|
|
|
|
since := time.Date(2025, 1, 1, 0, 0, 0, 0, time.UTC)
|
|
until := time.Date(2025, 12, 31, 23, 59, 59, 0, time.UTC)
|
|
|
|
// Insert 3 events with the same metric name and different values
|
|
e1 := newTestReportingEvent(1, model.MetricNameFirstResponse, 10.0, nil, time.Time{}, time.Time{})
|
|
e1.CreatedAt = time.Date(2025, 3, 10, 0, 0, 0, 0, time.UTC)
|
|
require.NoError(t, db.Create(e1).Error)
|
|
|
|
e2 := newTestReportingEvent(1, model.MetricNameFirstResponse, 20.0, nil, time.Time{}, time.Time{})
|
|
e2.CreatedAt = time.Date(2025, 4, 10, 0, 0, 0, 0, time.UTC)
|
|
require.NoError(t, db.Create(e2).Error)
|
|
|
|
e3 := newTestReportingEvent(1, model.MetricNameFirstResponse, 30.0, nil, time.Time{}, time.Time{})
|
|
e3.CreatedAt = time.Date(2025, 5, 10, 0, 0, 0, 0, time.UTC)
|
|
require.NoError(t, db.Create(e3).Error)
|
|
|
|
avgValue, total, err := repo.AggregateByMetric(context.Background(), 1, model.MetricNameFirstResponse, since, until)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, int64(3), total)
|
|
assert.InDelta(t, 20.0, avgValue, 0.01) // (10+20+30)/3 = 20
|
|
}
|
|
|
|
// --- Test 8: AggregateByMetric returns zero when no matches (PG-only) ---
|
|
func TestReportingEventRepo_AggregateByMetric_NoMatches(t *testing.T) {
|
|
skipIfSQLite(t) // COALESCE(AVG(value), 0) aggregation uses PG-specific semantics
|
|
|
|
db := setupTestDB(t, &model.ReportingEvent{})
|
|
repo := NewReportingEventRepo(db)
|
|
|
|
since := time.Date(2025, 1, 1, 0, 0, 0, 0, time.UTC)
|
|
until := time.Date(2025, 12, 31, 23, 59, 59, 0, time.UTC)
|
|
|
|
avgValue, total, err := repo.AggregateByMetric(context.Background(), 999, model.MetricNameFirstResponse, since, until)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, int64(0), total)
|
|
assert.Equal(t, 0.0, avgValue)
|
|
} |