* feat(announcements): Add support for archived announcements and add past announcement section in UI * Add missing field
242 lines
6.9 KiB
Go
242 lines
6.9 KiB
Go
package announcement
|
|
|
|
import (
|
|
"errors"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestAnnouncement_ValidateAndSetDefaults(t *testing.T) {
|
|
now := time.Now()
|
|
scenarios := []struct {
|
|
name string
|
|
announcement *Announcement
|
|
expectedError error
|
|
expectedType string
|
|
}{
|
|
{
|
|
name: "valid-announcement-with-all-fields",
|
|
announcement: &Announcement{
|
|
Timestamp: now,
|
|
Type: TypeWarning,
|
|
Message: "This is a test announcement",
|
|
Archived: false,
|
|
},
|
|
expectedError: nil,
|
|
expectedType: TypeWarning,
|
|
},
|
|
{
|
|
name: "valid-announcement-with-archived-true",
|
|
announcement: &Announcement{
|
|
Timestamp: now,
|
|
Type: TypeOperational,
|
|
Message: "This is an archived announcement",
|
|
Archived: true,
|
|
},
|
|
expectedError: nil,
|
|
expectedType: TypeOperational,
|
|
},
|
|
{
|
|
name: "valid-announcement-with-empty-type-should-default-to-none",
|
|
announcement: &Announcement{
|
|
Timestamp: now,
|
|
Message: "This announcement has no type",
|
|
},
|
|
expectedError: nil,
|
|
expectedType: TypeNone,
|
|
},
|
|
{
|
|
name: "invalid-announcement-with-empty-message",
|
|
announcement: &Announcement{
|
|
Timestamp: now,
|
|
Type: TypeWarning,
|
|
Message: "",
|
|
},
|
|
expectedError: ErrEmptyMessage,
|
|
},
|
|
{
|
|
name: "invalid-announcement-with-zero-timestamp",
|
|
announcement: &Announcement{
|
|
Timestamp: time.Time{},
|
|
Type: TypeWarning,
|
|
Message: "Test message",
|
|
},
|
|
expectedError: ErrMissingTimestamp,
|
|
},
|
|
{
|
|
name: "invalid-announcement-with-invalid-type",
|
|
announcement: &Announcement{
|
|
Timestamp: now,
|
|
Type: "invalid-type",
|
|
Message: "Test message",
|
|
},
|
|
expectedError: ErrInvalidAnnouncementType,
|
|
},
|
|
}
|
|
for _, scenario := range scenarios {
|
|
t.Run(scenario.name, func(t *testing.T) {
|
|
err := scenario.announcement.ValidateAndSetDefaults()
|
|
if !errors.Is(err, scenario.expectedError) {
|
|
t.Errorf("expected error %v, got %v", scenario.expectedError, err)
|
|
}
|
|
if scenario.expectedError == nil && scenario.announcement.Type != scenario.expectedType {
|
|
t.Errorf("expected type %s, got %s", scenario.expectedType, scenario.announcement.Type)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestAnnouncement_ValidateAndSetDefaults_AllTypes(t *testing.T) {
|
|
now := time.Now()
|
|
validTypes := []string{TypeOutage, TypeWarning, TypeInformation, TypeOperational, TypeNone}
|
|
for _, validType := range validTypes {
|
|
t.Run("type-"+validType, func(t *testing.T) {
|
|
announcement := &Announcement{
|
|
Timestamp: now,
|
|
Type: validType,
|
|
Message: "Test message",
|
|
}
|
|
if err := announcement.ValidateAndSetDefaults(); err != nil {
|
|
t.Errorf("expected no error for type %s, got %v", validType, err)
|
|
}
|
|
if announcement.Type != validType {
|
|
t.Errorf("expected type %s, got %s", validType, announcement.Type)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSortByTimestamp(t *testing.T) {
|
|
now := time.Now()
|
|
earlier := now.Add(-1 * time.Hour)
|
|
later := now.Add(1 * time.Hour)
|
|
announcements := []*Announcement{
|
|
{Timestamp: now, Message: "now"},
|
|
{Timestamp: later, Message: "later"},
|
|
{Timestamp: earlier, Message: "earlier"},
|
|
}
|
|
SortByTimestamp(announcements)
|
|
if announcements[0].Timestamp != later {
|
|
t.Error("expected first announcement to be the latest")
|
|
}
|
|
if announcements[1].Timestamp != now {
|
|
t.Error("expected second announcement to be the middle one")
|
|
}
|
|
if announcements[2].Timestamp != earlier {
|
|
t.Error("expected third announcement to be the earliest")
|
|
}
|
|
}
|
|
|
|
func TestSortByTimestamp_WithArchivedField(t *testing.T) {
|
|
now := time.Now()
|
|
earlier := now.Add(-1 * time.Hour)
|
|
later := now.Add(1 * time.Hour)
|
|
announcements := []*Announcement{
|
|
{Timestamp: now, Message: "now", Archived: false},
|
|
{Timestamp: later, Message: "later", Archived: true},
|
|
{Timestamp: earlier, Message: "earlier", Archived: false},
|
|
}
|
|
SortByTimestamp(announcements)
|
|
// Sorting should be by timestamp only, not affected by archived status
|
|
if announcements[0].Timestamp != later {
|
|
t.Error("expected first announcement to be the latest, regardless of archived status")
|
|
}
|
|
if !announcements[0].Archived {
|
|
t.Error("expected first announcement to be archived")
|
|
}
|
|
if announcements[1].Timestamp != now {
|
|
t.Error("expected second announcement to be the middle one")
|
|
}
|
|
if announcements[2].Timestamp != earlier {
|
|
t.Error("expected third announcement to be the earliest")
|
|
}
|
|
}
|
|
|
|
func TestValidateAndSetDefaults_Slice(t *testing.T) {
|
|
now := time.Now()
|
|
scenarios := []struct {
|
|
name string
|
|
announcements []*Announcement
|
|
expectedError error
|
|
shouldValidate bool
|
|
}{
|
|
{
|
|
name: "all-valid-announcements",
|
|
announcements: []*Announcement{
|
|
{Timestamp: now, Type: TypeWarning, Message: "First announcement"},
|
|
{Timestamp: now, Type: TypeOperational, Message: "Second announcement"},
|
|
},
|
|
expectedError: nil,
|
|
shouldValidate: true,
|
|
},
|
|
{
|
|
name: "mixed-archived-announcements",
|
|
announcements: []*Announcement{
|
|
{Timestamp: now, Type: TypeWarning, Message: "Active announcement", Archived: false},
|
|
{Timestamp: now, Type: TypeOperational, Message: "Archived announcement", Archived: true},
|
|
},
|
|
expectedError: nil,
|
|
shouldValidate: true,
|
|
},
|
|
{
|
|
name: "one-invalid-announcement-in-slice",
|
|
announcements: []*Announcement{
|
|
{Timestamp: now, Type: TypeWarning, Message: "Valid announcement"},
|
|
{Timestamp: now, Type: TypeOperational, Message: ""},
|
|
},
|
|
expectedError: ErrEmptyMessage,
|
|
shouldValidate: false,
|
|
},
|
|
{
|
|
name: "announcement-with-missing-timestamp",
|
|
announcements: []*Announcement{
|
|
{Timestamp: now, Type: TypeWarning, Message: "Valid announcement"},
|
|
{Timestamp: time.Time{}, Type: TypeOperational, Message: "Invalid announcement"},
|
|
},
|
|
expectedError: ErrMissingTimestamp,
|
|
shouldValidate: false,
|
|
},
|
|
{
|
|
name: "announcement-with-invalid-type",
|
|
announcements: []*Announcement{
|
|
{Timestamp: now, Type: TypeWarning, Message: "Valid announcement"},
|
|
{Timestamp: now, Type: "bad-type", Message: "Invalid announcement"},
|
|
},
|
|
expectedError: ErrInvalidAnnouncementType,
|
|
shouldValidate: false,
|
|
},
|
|
}
|
|
for _, scenario := range scenarios {
|
|
t.Run(scenario.name, func(t *testing.T) {
|
|
err := ValidateAndSetDefaults(scenario.announcements)
|
|
if !errors.Is(err, scenario.expectedError) {
|
|
t.Errorf("expected error %v, got %v", scenario.expectedError, err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestAnnouncement_ArchivedFieldDefaults(t *testing.T) {
|
|
now := time.Now()
|
|
announcement := &Announcement{
|
|
Timestamp: now,
|
|
Type: TypeWarning,
|
|
Message: "Test announcement",
|
|
// Archived not set, should default to false
|
|
}
|
|
if err := announcement.ValidateAndSetDefaults(); err != nil {
|
|
t.Errorf("expected no error, got %v", err)
|
|
}
|
|
// Zero value for bool is false
|
|
if announcement.Archived {
|
|
t.Error("expected Archived to default to false")
|
|
}
|
|
}
|
|
|
|
func TestValidateAndSetDefaults_EmptySlice(t *testing.T) {
|
|
announcements := []*Announcement{}
|
|
if err := ValidateAndSetDefaults(announcements); err != nil {
|
|
t.Errorf("expected no error for empty slice, got %v", err)
|
|
}
|
|
}
|