Initial commit
This commit is contained in:
95
internal/scheduler/badge_test.go
Normal file
95
internal/scheduler/badge_test.go
Normal file
@@ -0,0 +1,95 @@
|
||||
package scheduler
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"veola/internal/models"
|
||||
)
|
||||
|
||||
func bestItem(best, target float64) models.Item {
|
||||
bp := best
|
||||
it := models.Item{BestPrice: &bp}
|
||||
if target > 0 {
|
||||
t := target
|
||||
it.TargetPrice = &t
|
||||
}
|
||||
return it
|
||||
}
|
||||
|
||||
func TestPickBadgeAllTimeLow(t *testing.T) {
|
||||
now := time.Now()
|
||||
hist := []models.PricePoint{
|
||||
{Price: 100, PolledAt: now.Add(-40 * 24 * time.Hour)},
|
||||
{Price: 80, PolledAt: now.Add(-10 * 24 * time.Hour)},
|
||||
{Price: 60, PolledAt: now.Add(-1 * 24 * time.Hour)},
|
||||
}
|
||||
it := bestItem(50, 0)
|
||||
got := PickBadge(it, hist, now)
|
||||
if got.Label != "All-time low" {
|
||||
t.Errorf("expected all-time low, got %q", got.Label)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPickBadgeBelowAverage(t *testing.T) {
|
||||
now := time.Now()
|
||||
hist := []models.PricePoint{
|
||||
{Price: 100, PolledAt: now.Add(-25 * 24 * time.Hour)},
|
||||
{Price: 100, PolledAt: now.Add(-10 * 24 * time.Hour)},
|
||||
{Price: 100, PolledAt: now.Add(-5 * 24 * time.Hour)},
|
||||
}
|
||||
it := bestItem(80, 0) // 20% below 100 avg, not lowest because there's no lower in history but best is below points
|
||||
// add an older lower point so all-time-low is NOT triggered
|
||||
hist = append(hist, models.PricePoint{Price: 70, PolledAt: now.Add(-90 * 24 * time.Hour)})
|
||||
got := PickBadge(it, hist, now)
|
||||
if got.Label != "20% below 30-day avg" {
|
||||
t.Errorf("expected 20%% below 30-day avg, got %q", got.Label)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPickBadgeBelowTarget(t *testing.T) {
|
||||
now := time.Now()
|
||||
// 30-day window mean equals best (50) so avg badge does not fire.
|
||||
// An older lower point disables the all-time-low badge.
|
||||
hist := []models.PricePoint{
|
||||
{Price: 50, PolledAt: now.Add(-2 * 24 * time.Hour)},
|
||||
{Price: 50, PolledAt: now.Add(-1 * 24 * time.Hour)},
|
||||
{Price: 40, PolledAt: now.Add(-90 * 24 * time.Hour)},
|
||||
}
|
||||
it := bestItem(50, 100) // 50% below target
|
||||
got := PickBadge(it, hist, now)
|
||||
if got.Label != "50% below target" {
|
||||
t.Errorf("expected 50%% below target, got %q", got.Label)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPickBadgeNone(t *testing.T) {
|
||||
now := time.Now()
|
||||
// best matches recent avg, no target, and an older lower point exists -
|
||||
// no badge should fire.
|
||||
hist := []models.PricePoint{
|
||||
{Price: 50, PolledAt: now.Add(-1 * 24 * time.Hour)},
|
||||
{Price: 40, PolledAt: now.Add(-90 * 24 * time.Hour)},
|
||||
}
|
||||
it := bestItem(50, 0)
|
||||
got := PickBadge(it, hist, now)
|
||||
if got.Label != "" {
|
||||
t.Errorf("expected no badge, got %q", got.Label)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPickBadgeIgnoresShortAvgGap(t *testing.T) {
|
||||
now := time.Now()
|
||||
hist := []models.PricePoint{
|
||||
{Price: 100, PolledAt: now.Add(-1 * 24 * time.Hour)},
|
||||
{Price: 95, PolledAt: now.Add(-2 * 24 * time.Hour)},
|
||||
}
|
||||
// best 92 is only ~5.6% below avg 97.5 — under the 10% floor
|
||||
older := models.PricePoint{Price: 80, PolledAt: now.Add(-90 * 24 * time.Hour)}
|
||||
hist = append(hist, older)
|
||||
it := bestItem(92, 0)
|
||||
got := PickBadge(it, hist, now)
|
||||
if got.Label != "" {
|
||||
t.Errorf("expected no badge for <10%% gap, got %q", got.Label)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user