Files

443 lines
13 KiB
Go

package reporting
import (
"context"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/gochat/gochat/internal/channel"
"github.com/gochat/gochat/internal/model"
)
func TestReportingEventListener_OnConversationCreated_Cov3(t *testing.T) {
db := newTestDB(t)
l := NewReportingEventListener(db)
assigneeID := uint(5)
conv := &model.Conversation{
Base: model.Base{ID: 1, CreatedAt: time.Now()},
AccountID: 1,
InboxID: 2,
AssigneeID: &assigneeID,
}
event := channel.NewChannelEvent(channel.EventConversationCreated, channel.ChannelAPI, 1, 2)
event.Data["conversation"] = conv
err := l.OnEvent(context.Background(), event)
require.NoError(t, err)
// Verify reporting event was created
var events []ReportingEvent
db.Find(&events)
require.Len(t, events, 1)
assert.Equal(t, "conversation_created", events[0].Name)
assert.Equal(t, uint(1), events[0].AccountID)
assert.NotNil(t, events[0].UserID)
assert.Equal(t, assigneeID, *events[0].UserID)
}
func TestReportingEventListener_OnConversationCreated_NoAssignee_Cov3(t *testing.T) {
db := newTestDB(t)
l := NewReportingEventListener(db)
conv := &model.Conversation{
Base: model.Base{ID: 1, CreatedAt: time.Now()},
AccountID: 1,
InboxID: 2,
}
event := channel.NewChannelEvent(channel.EventConversationCreated, channel.ChannelAPI, 1, 2)
event.Data["conversation"] = conv
err := l.OnEvent(context.Background(), event)
require.NoError(t, err)
var events []ReportingEvent
db.Find(&events)
require.Len(t, events, 1)
assert.Nil(t, events[0].UserID)
}
func TestReportingEventListener_OnConversationCreated_ExtractError_Cov3(t *testing.T) {
db := newTestDB(t)
l := NewReportingEventListener(db)
// Event without conversation data — should return error
event := channel.NewChannelEvent(channel.EventConversationCreated, channel.ChannelAPI, 1, 2)
event.Data = map[string]interface{}{}
err := l.OnEvent(context.Background(), event)
assert.Error(t, err)
}
func TestReportingEventListener_OnConversationResolved_Cov3(t *testing.T) {
db := newTestDB(t)
l := NewReportingEventListener(db)
assigneeID := uint(5)
createdAt := time.Now().Add(-1 * time.Hour)
conv := &model.Conversation{
Base: model.Base{ID: 1, CreatedAt: createdAt},
AccountID: 1,
InboxID: 2,
AssigneeID: &assigneeID,
}
event := channel.NewChannelEvent(channel.EventConversationResolved, channel.ChannelAPI, 1, 2)
event.Data["conversation"] = conv
err := l.OnEvent(context.Background(), event)
require.NoError(t, err)
var events []ReportingEvent
db.Find(&events)
require.Len(t, events, 2)
// First event is resolution_time
assert.Equal(t, "resolution_time", events[0].Name)
assert.Greater(t, events[0].Value, 0.0)
// Second is resolutions_count
assert.Equal(t, "resolutions_count", events[1].Name)
assert.Equal(t, 1.0, events[1].Value)
}
func TestReportingEventListener_OnConversationResolved_ExtractError_Cov3(t *testing.T) {
db := newTestDB(t)
l := NewReportingEventListener(db)
event := channel.NewChannelEvent(channel.EventConversationResolved, channel.ChannelAPI, 1, 2)
event.Data = map[string]interface{}{}
err := l.OnEvent(context.Background(), event)
assert.Error(t, err)
}
func TestReportingEventListener_OnConversationResolved_DBError_Cov3(t *testing.T) {
// Close the db to trigger a DB error
db := newTestDB(t)
sqlDB, _ := db.DB()
sqlDB.Close()
l := NewReportingEventListener(db)
conv := &model.Conversation{
Base: model.Base{ID: 1, CreatedAt: time.Now()},
AccountID: 1,
InboxID: 2,
}
event := channel.NewChannelEvent(channel.EventConversationResolved, channel.ChannelAPI, 1, 2)
event.Data["conversation"] = conv
err := l.OnEvent(context.Background(), event)
assert.Error(t, err)
}
func TestReportingEventListener_OnConversationAssigned_Cov3(t *testing.T) {
db := newTestDB(t)
l := NewReportingEventListener(db)
assigneeID := uint(5)
conv := &model.Conversation{
Base: model.Base{ID: 1, CreatedAt: time.Now()},
AccountID: 1,
InboxID: 2,
AssigneeID: &assigneeID,
}
event := channel.NewChannelEvent(channel.EventConversationAssigned, channel.ChannelAPI, 1, 2)
event.Data["conversation"] = conv
err := l.OnEvent(context.Background(), event)
require.NoError(t, err)
var events []ReportingEvent
db.Find(&events)
require.Len(t, events, 1)
assert.Equal(t, "first_response", events[0].Name)
}
func TestReportingEventListener_OnConversationAssigned_ExtractError_Cov3(t *testing.T) {
db := newTestDB(t)
l := NewReportingEventListener(db)
event := channel.NewChannelEvent(channel.EventConversationAssigned, channel.ChannelAPI, 1, 2)
event.Data = map[string]interface{}{}
err := l.OnEvent(context.Background(), event)
assert.Error(t, err)
}
func TestReportingEventListener_OnMessageCreated_Outgoing_Cov3(t *testing.T) {
db := newTestDB(t)
l := NewReportingEventListener(db)
senderID := uint(5)
msg := &model.Message{
Base: model.Base{ID: 1, CreatedAt: time.Now()},
AccountID: 1,
InboxID: 2,
ConversationID: 3,
MessageType: "outgoing",
SenderType: "agent",
SenderID: &senderID,
}
event := channel.NewChannelEvent(channel.EventMessageCreated, channel.ChannelAPI, 1, 2)
event.Data["message"] = msg
err := l.OnEvent(context.Background(), event)
require.NoError(t, err)
var events []ReportingEvent
db.Find(&events)
require.Len(t, events, 1)
assert.Equal(t, "reply_time", events[0].Name)
assert.Equal(t, senderID, *events[0].UserID)
}
func TestReportingEventListener_OnMessageCreated_Incoming_Cov3(t *testing.T) {
db := newTestDB(t)
l := NewReportingEventListener(db)
msg := &model.Message{
Base: model.Base{ID: 1, CreatedAt: time.Now()},
AccountID: 1,
InboxID: 2,
ConversationID: 3,
MessageType: "incoming",
SenderType: "contact",
}
event := channel.NewChannelEvent(channel.EventMessageCreated, channel.ChannelAPI, 1, 2)
event.Data["message"] = msg
err := l.OnEvent(context.Background(), event)
require.NoError(t, err)
// Incoming messages are not tracked
var events []ReportingEvent
db.Find(&events)
assert.Empty(t, events)
}
func TestReportingEventListener_OnMessageCreated_NoMessage_Cov3(t *testing.T) {
db := newTestDB(t)
l := NewReportingEventListener(db)
event := channel.NewChannelEvent(channel.EventMessageCreated, channel.ChannelAPI, 1, 2)
event.Data = map[string]interface{}{}
err := l.OnEvent(context.Background(), event)
require.NoError(t, err) // returns nil when no message
}
func TestReportingEventListener_OnMessageCreated_DBError_Cov3(t *testing.T) {
db := newTestDB(t)
sqlDB, _ := db.DB()
sqlDB.Close()
l := NewReportingEventListener(db)
senderID := uint(5)
msg := &model.Message{
Base: model.Base{ID: 1, CreatedAt: time.Now()},
AccountID: 1,
InboxID: 2,
ConversationID: 3,
MessageType: "outgoing",
SenderType: "agent",
SenderID: &senderID,
}
event := channel.NewChannelEvent(channel.EventMessageCreated, channel.ChannelAPI, 1, 2)
event.Data["message"] = msg
err := l.OnEvent(context.Background(), event)
assert.Error(t, err)
}
func TestReportingEventListener_OnEvent_Unknown_Cov3(t *testing.T) {
db := newTestDB(t)
l := NewReportingEventListener(db)
event := channel.NewChannelEvent("unknown.event", channel.ChannelAPI, 1, 2)
err := l.OnEvent(context.Background(), event)
require.NoError(t, err)
}
func TestReportingEventListener_Name_Cov3(t *testing.T) {
l := NewReportingEventListener(nil)
assert.Equal(t, "reporting_event_listener", l.Name())
}
func TestReportingService_CreateEvent_Cov3(t *testing.T) {
db := newTestDB(t)
svc := NewReportingService(db)
now := time.Now()
event := &ReportingEvent{
AccountID: 1,
Name: "test_metric",
Value: 42.0,
EventStartTime: now,
EventEndTime: now,
}
err := svc.CreateEvent(context.Background(), event)
require.NoError(t, err)
assert.NotZero(t, event.ID)
}
func TestReportingService_GetEvent_Cov3(t *testing.T) {
db := newTestDB(t)
svc := NewReportingService(db)
now := time.Now()
event := &ReportingEvent{
AccountID: 1,
Name: "test_metric",
Value: 42.0,
EventStartTime: now,
EventEndTime: now,
}
require.NoError(t, svc.CreateEvent(context.Background(), event))
got, err := svc.GetEvent(context.Background(), event.ID)
require.NoError(t, err)
assert.Equal(t, "test_metric", got.Name)
}
func TestReportingService_GetEvent_NotFound_Cov3(t *testing.T) {
db := newTestDB(t)
svc := NewReportingService(db)
_, err := svc.GetEvent(context.Background(), 999)
assert.Error(t, err)
}
func TestReportingService_ListEventsByAccount_Cov3(t *testing.T) {
db := newTestDB(t)
svc := NewReportingService(db)
now := time.Now()
event1 := &ReportingEvent{AccountID: 1, Name: "m1", Value: 1, EventStartTime: now, EventEndTime: now}
event2 := &ReportingEvent{AccountID: 1, Name: "m2", Value: 2, EventStartTime: now, EventEndTime: now}
event3 := &ReportingEvent{AccountID: 2, Name: "m3", Value: 3, EventStartTime: now, EventEndTime: now}
require.NoError(t, svc.CreateEvent(context.Background(), event1))
require.NoError(t, svc.CreateEvent(context.Background(), event2))
require.NoError(t, svc.CreateEvent(context.Background(), event3))
events, err := svc.ListEventsByAccount(context.Background(), 1, now.Add(-1*time.Hour), now.Add(1*time.Hour))
require.NoError(t, err)
assert.Len(t, events, 2)
}
func TestReportingService_ListEventsByAccountAndName_Cov3(t *testing.T) {
db := newTestDB(t)
svc := NewReportingService(db)
now := time.Now()
event1 := &ReportingEvent{AccountID: 1, Name: "reply_time", Value: 1, EventStartTime: now, EventEndTime: now}
event2 := &ReportingEvent{AccountID: 1, Name: "resolution_time", Value: 2, EventStartTime: now, EventEndTime: now}
require.NoError(t, svc.CreateEvent(context.Background(), event1))
require.NoError(t, svc.CreateEvent(context.Background(), event2))
events, err := svc.ListEventsByAccountAndName(context.Background(), 1, "reply_time", now.Add(-1*time.Hour), now.Add(1*time.Hour))
require.NoError(t, err)
assert.Len(t, events, 1)
assert.Equal(t, "reply_time", events[0].Name)
}
func TestReportingService_CreateRollup_Cov3(t *testing.T) {
db := newTestDB(t)
svc := NewReportingService(db)
rollup := &ReportingEventsRollup{
AccountID: 1,
Date: time.Now().Truncate(24 * time.Hour),
DimensionType: DimensionAccount,
DimensionID: 1,
Metric: MetricResolutionsCount,
Count: 5,
SumValue: 100.0,
}
err := svc.CreateRollup(context.Background(), rollup)
require.NoError(t, err)
}
func TestReportingService_GetRollups_Cov3(t *testing.T) {
db := newTestDB(t)
svc := NewReportingService(db)
now := time.Now().Truncate(24 * time.Hour)
rollup := &ReportingEventsRollup{
AccountID: 1,
Date: now,
DimensionType: DimensionAccount,
DimensionID: 1,
Metric: MetricResolutionsCount,
Count: 5,
}
require.NoError(t, svc.CreateRollup(context.Background(), rollup))
rollups, err := svc.GetRollups(context.Background(), 1, DimensionAccount, 1, now.Add(-1*time.Hour), now.Add(1*time.Hour))
require.NoError(t, err)
assert.Len(t, rollups, 1)
}
func TestReportingService_GetRollupsByMetric_Cov3(t *testing.T) {
db := newTestDB(t)
svc := NewReportingService(db)
now := time.Now().Truncate(24 * time.Hour)
rollup := &ReportingEventsRollup{
AccountID: 1,
Date: now,
DimensionType: DimensionAccount,
DimensionID: 1,
Metric: MetricReplyTime,
Count: 3,
}
require.NoError(t, svc.CreateRollup(context.Background(), rollup))
rollups, err := svc.GetRollupsByMetric(context.Background(), 1, DimensionAccount, 1, MetricReplyTime, now.Add(-1*time.Hour), now.Add(1*time.Hour))
require.NoError(t, err)
assert.Len(t, rollups, 1)
}
func TestReportingService_DeleteRollupsByDate_Cov3(t *testing.T) {
db := newTestDB(t)
svc := NewReportingService(db)
now := time.Now().Truncate(24 * time.Hour)
rollup := &ReportingEventsRollup{
AccountID: 1,
Date: now,
DimensionType: DimensionAccount,
DimensionID: 1,
Metric: MetricReplyTime,
}
require.NoError(t, svc.CreateRollup(context.Background(), rollup))
err := svc.DeleteRollupsByDate(context.Background(), 1, now.Add(-1*time.Hour), now.Add(1*time.Hour))
require.NoError(t, err)
rollups, _ := svc.GetRollups(context.Background(), 1, DimensionAccount, 1, now.Add(-1*time.Hour), now.Add(1*time.Hour))
assert.Empty(t, rollups)
}
// --- Metric registry tests ---
func TestGetMetricDefinition_Cov3(t *testing.T) {
def, ok := GetMetricDefinition("avg_first_response_time")
assert.True(t, ok)
assert.Equal(t, "first_response", def.RawEventName)
}
func TestGetMetricDefinition_NotFound_Cov3(t *testing.T) {
_, ok := GetMetricDefinition("nonexistent")
assert.False(t, ok)
}
func TestAllMetricKeys_Cov3(t *testing.T) {
keys := AllMetricKeys()
assert.NotEmpty(t, keys)
assert.Contains(t, keys, "avg_first_response_time")
assert.Contains(t, keys, "resolutions_count")
}