Initial commit

This commit is contained in:
2026-05-13 19:42:49 -07:00
commit cfa01bd4ef
54 changed files with 11718 additions and 0 deletions

View 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)
}
}