package monitor_test import ( "context" "sync" "testing" "time" "somegit.dev/vikingowl/reddit-reader/internal/domain" "somegit.dev/vikingowl/reddit-reader/internal/monitor" "somegit.dev/vikingowl/reddit-reader/internal/store" ) type mockFetcher struct { posts []domain.Post } func (m *mockFetcher) FetchPosts(_ context.Context, _, _ string, _ int) ([]domain.Post, error) { return m.posts, nil } type mockSummarizer struct { mu sync.Mutex calls int } func (m *mockSummarizer) Score(_ context.Context, _ domain.Post, _ domain.Interests) (float64, error) { m.mu.Lock() defer m.mu.Unlock() m.calls++ return 0.8, nil } func (m *mockSummarizer) Summarize(_ context.Context, _ domain.Post) (string, error) { return "- bullet 1\n- bullet 2\n- bullet 3\n- bullet 4\n- bullet 5", nil } func TestMonitorPollCycle(t *testing.T) { st, err := store.Open(":memory:") if err != nil { t.Fatal(err) } defer st.Close() st.AddSubreddit(domain.Subreddit{Name: "golang", PollSort: "new"}) st.AddFilter(domain.Filter{Subreddit: "golang", Pattern: "go"}) fetcher := &mockFetcher{ posts: []domain.Post{ {ID: "t3_new1", Subreddit: "golang", Title: "Go tips", CreatedUTC: time.Now()}, {ID: "t3_new2", Subreddit: "golang", Title: "Rust tips", CreatedUTC: time.Now()}, }, } summarizer := &mockSummarizer{} m := monitor.New(st, fetcher, summarizer, monitor.Config{ RelevanceThreshold: 0.6, MaxPostsPerPoll: 25, Interests: domain.Interests{Description: "Go programming"}, }) newPosts, err := m.PollOnce(context.Background()) if err != nil { t.Fatalf("PollOnce: %v", err) } // "Go tips" matches keyword "go", "Rust tips" does not if len(newPosts) != 1 { t.Fatalf("newPosts = %d, want 1", len(newPosts)) } if newPosts[0].ID != "t3_new1" { t.Errorf("post ID = %q, want t3_new1", newPosts[0].ID) } if newPosts[0].Summary == nil { t.Error("expected summary to be set") } exists, _ := st.PostExists("t3_new1") if !exists { t.Error("post should be in store") } } func TestMonitorDedup(t *testing.T) { st, err := store.Open(":memory:") if err != nil { t.Fatal(err) } defer st.Close() st.AddSubreddit(domain.Subreddit{Name: "golang", PollSort: "new"}) st.InsertPost(domain.Post{ID: "t3_existing", Subreddit: "golang", Title: "Old", CreatedUTC: time.Now()}) fetcher := &mockFetcher{ posts: []domain.Post{ {ID: "t3_existing", Subreddit: "golang", Title: "Old", CreatedUTC: time.Now()}, }, } m := monitor.New(st, fetcher, &mockSummarizer{}, monitor.Config{ RelevanceThreshold: 0.6, MaxPostsPerPoll: 25, Interests: domain.Interests{Description: "Go"}, }) newPosts, err := m.PollOnce(context.Background()) if err != nil { t.Fatalf("PollOnce: %v", err) } if len(newPosts) != 0 { t.Errorf("expected 0 new posts (dedup), got %d", len(newPosts)) } }