Files
flowsight/backend/internal/routines/routines_test.go
T
asepharyana 8c184ccae1 feat: add Citations and WatchlistChat components, integrate with API
- Implemented Citations component to display citation data.
- Created WatchlistDrawer and ChatSidebar components for managing watchlists and AI chat functionality.
- Integrated API calls for watchlist management and chat interactions.
- Updated index.tsx to include new components in the main application layout.
- Added API client in lib/api.ts for structured API interactions.
- Developed Alerts, Dashboard, Portfolio, Routines, Screener, and Report pages with relevant data fetching and UI components.
- Introduced styles in tokens.css for consistent theming across the application.
- Configured TypeScript and Vite for project setup and development.
2026-09-15 12:36:48 +07:00

99 lines
2.4 KiB
Go

package routines
import (
"context"
"strings"
"testing"
"flowsight/internal/alerts"
"flowsight/internal/store"
)
func seedEngine(t *testing.T) *Engine {
t.Helper()
db, err := store.Open(t.TempDir() + "/routines.db")
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() { db.Close() })
if _, err := db.SeedFromDir("../../tests/fixtures", "demo"); err != nil {
t.Fatal(err)
}
return &Engine{DB: db, Notifier: alerts.NewNotifier("", "", ""), UserKey: "demo"}
}
// Briefing generates from seed with zero empty sections.
func TestBriefing(t *testing.T) {
e := seedEngine(t)
text, cites, err := e.Briefing(context.Background())
if err != nil {
t.Fatal(err)
}
for _, sec := range []string{"Top accumulation", "Foreign flow", "Agenda"} {
if !strings.Contains(text, sec) {
t.Fatalf("missing section %q", sec)
}
}
if len(cites) == 0 {
t.Fatal("briefing has no citations")
}
}
// Radar fires on the accumulation fixture.
func TestRadar(t *testing.T) {
e := seedEngine(t)
text, _, err := e.Radar(context.Background())
if err != nil {
t.Fatal(err)
}
if !strings.Contains(text, "BBCA") {
t.Fatalf("radar missed BBCA: %s", text)
}
}
// Accuracy resolution math: weights follow the ledger.
func TestAccuracyWeight(t *testing.T) {
e := seedEngine(t)
if w := e.DB.AccuracyWeight("smart-money"); w != 0.5 {
t.Fatalf("default weight = %v, want 0.5", w)
}
for i := 0; i < 10; i++ {
_ = e.DB.RecordPrediction("smart-money", "BBCA", "BUY")
}
rows, _ := e.DB.DueForResolution()
_ = rows
}
// Briefing carries agenda + mover sections and respects the 25-line cap.
func TestBriefingAgendaMoverCap(t *testing.T) {
e := seedEngine(t)
text, cites, err := e.Briefing(context.Background())
if err != nil {
t.Fatal(err)
}
for _, sec := range []string{"Top accumulation", "Foreign flow", "Agenda", "Mover of the day"} {
if !strings.Contains(text, sec) {
t.Fatalf("missing section %q:\n%s", sec, text)
}
}
if n := len(strings.Split(strings.TrimRight(text, "\n"), "\n")); n > 25 {
t.Fatalf("briefing = %d lines, want ≤25", n)
}
if len(cites) == 0 {
t.Fatal("briefing has no citations")
}
}
// R5/R6 run without error on seed (windows simply miss today).
func TestCountdownsRun(t *testing.T) {
e := seedEngine(t)
rows, _ := e.DB.ListRoutines("demo")
_ = rows
if _, _, err := e.EarningsCountdown(context.Background()); err != nil {
t.Fatal(err)
}
if _, _, err := e.DividendCalendar(context.Background()); err != nil {
t.Fatal(err)
}
}