flake-update-20260201
1package sources
2
3import (
4 "os"
5 "path/filepath"
6 "testing"
7 "time"
8
9 "github.com/vdemeester/home/tools/review-tool/internal/config"
10)
11
12// Helper to create temp directory with test files
13func setupTestHistoryDir(t *testing.T) string {
14 t.Helper()
15 dir := t.TempDir()
16
17 // Create directory structure
18 sessionsDir := filepath.Join(dir, "sessions", "2026-01")
19 learningsDir := filepath.Join(dir, "learnings", "2026-01")
20 researchDir := filepath.Join(dir, "research", "2026-01")
21
22 for _, d := range []string{sessionsDir, learningsDir, researchDir} {
23 if err := os.MkdirAll(d, 0o755); err != nil {
24 t.Fatalf("failed to create dir: %v", err)
25 }
26 }
27
28 // Create test session file with metadata
29 sessionContent := `# Terraform Branch Protection Implementation
30
31**Date:** 2026-01-21
32**Repository:** tektoncd/plumbing
33**Duration:** ~3 hours
34
35## Summary
36Implemented branch protection automation.
37`
38 if err := os.WriteFile(filepath.Join(sessionsDir, "2026-01-21-terraform-session.md"), []byte(sessionContent), 0o644); err != nil {
39 t.Fatalf("failed to write session file: %v", err)
40 }
41
42 // Create session file without explicit date (date from filename)
43 sessionNoDate := `# Mobile Development Planning
44
45## Summary
46Discussed mobile dev workflow.
47`
48 if err := os.WriteFile(filepath.Join(sessionsDir, "2026-01-15-mobile-planning.md"), []byte(sessionNoDate), 0o644); err != nil {
49 t.Fatalf("failed to write session file: %v", err)
50 }
51
52 // Create learning file
53 learningContent := `# SSH Config Required for Non-Standard Keys
54
55**Date:** 2026-01-18
56**Duration:** ~45 minutes
57**Commit:** adf33b32
58
59## Problem
60SSH authentication failing with custom key paths.
61
62## Solution
63Added proper Host blocks to ~/.ssh/config.
64`
65 if err := os.WriteFile(filepath.Join(learningsDir, "2026-01-18-ssh-config-learning.md"), []byte(learningContent), 0o644); err != nil {
66 t.Fatalf("failed to write learning file: %v", err)
67 }
68
69 // Create research file (org-mode)
70 researchContent := `#+title: SelfCI Analysis
71#+date: [2026-01-16 Thu]
72#+filetags: :ci:research:
73
74* Summary
75Research on local CI systems.
76`
77 if err := os.WriteFile(filepath.Join(researchDir, "selfci-analysis.org"), []byte(researchContent), 0o644); err != nil {
78 t.Fatalf("failed to write research file: %v", err)
79 }
80
81 return dir
82}
83
84func TestClaudeSource_ParsesSessionWithMetadata(t *testing.T) {
85 historyDir := setupTestHistoryDir(t)
86
87 cfg := &config.ClaudeConfig{
88 Enabled: true,
89 HistoryDir: historyDir,
90 IncludeSessions: true,
91 IncludeLearnings: false,
92 IncludeResearch: false,
93 }
94
95 source := NewClaudeSource(cfg)
96
97 // Query for January 2026
98 start := time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC)
99 end := time.Date(2026, 1, 31, 23, 59, 59, 0, time.UTC)
100
101 act, err := source.Fetch(t.Context(), start, end)
102 if err != nil {
103 t.Fatalf("Fetch() error = %v", err)
104 }
105
106 if len(act.Items) == 0 {
107 t.Fatal("expected at least one session item")
108 }
109
110 // Find the terraform session
111 var found bool
112 for _, item := range act.Items {
113 if item.Title == "Terraform Branch Protection Implementation" {
114 found = true
115 if item.Type != "session" {
116 t.Errorf("Type = %q, want %q", item.Type, "session")
117 }
118 // Date should be 2026-01-21
119 if item.Timestamp.Day() != 21 {
120 t.Errorf("Timestamp day = %d, want 21", item.Timestamp.Day())
121 }
122 }
123 }
124
125 if !found {
126 t.Error("terraform session not found in items")
127 }
128}
129
130func TestClaudeSource_ParsesDateFromFilename(t *testing.T) {
131 historyDir := setupTestHistoryDir(t)
132
133 cfg := &config.ClaudeConfig{
134 Enabled: true,
135 HistoryDir: historyDir,
136 IncludeSessions: true,
137 IncludeLearnings: false,
138 IncludeResearch: false,
139 }
140
141 source := NewClaudeSource(cfg)
142
143 start := time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC)
144 end := time.Date(2026, 1, 31, 23, 59, 59, 0, time.UTC)
145
146 act, err := source.Fetch(t.Context(), start, end)
147 if err != nil {
148 t.Fatalf("Fetch() error = %v", err)
149 }
150
151 // Find mobile planning session (no explicit date in content)
152 var found bool
153 for _, item := range act.Items {
154 if item.Title == "Mobile Development Planning" {
155 found = true
156 // Date should be extracted from filename: 2026-01-15
157 if item.Timestamp.Day() != 15 {
158 t.Errorf("Timestamp day = %d, want 15", item.Timestamp.Day())
159 }
160 }
161 }
162
163 if !found {
164 t.Error("mobile planning session not found")
165 }
166}
167
168func TestClaudeSource_ParsesLearnings(t *testing.T) {
169 historyDir := setupTestHistoryDir(t)
170
171 cfg := &config.ClaudeConfig{
172 Enabled: true,
173 HistoryDir: historyDir,
174 IncludeSessions: false,
175 IncludeLearnings: true,
176 IncludeResearch: false,
177 }
178
179 source := NewClaudeSource(cfg)
180
181 start := time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC)
182 end := time.Date(2026, 1, 31, 23, 59, 59, 0, time.UTC)
183
184 act, err := source.Fetch(t.Context(), start, end)
185 if err != nil {
186 t.Fatalf("Fetch() error = %v", err)
187 }
188
189 if len(act.Items) != 1 {
190 t.Fatalf("expected 1 learning item, got %d", len(act.Items))
191 }
192
193 item := act.Items[0]
194 if item.Type != "learning" {
195 t.Errorf("Type = %q, want %q", item.Type, "learning")
196 }
197 if item.Timestamp.Day() != 18 {
198 t.Errorf("Timestamp day = %d, want 18", item.Timestamp.Day())
199 }
200}
201
202func TestClaudeSource_ParsesResearchOrgMode(t *testing.T) {
203 historyDir := setupTestHistoryDir(t)
204
205 cfg := &config.ClaudeConfig{
206 Enabled: true,
207 HistoryDir: historyDir,
208 IncludeSessions: false,
209 IncludeLearnings: false,
210 IncludeResearch: true,
211 }
212
213 source := NewClaudeSource(cfg)
214
215 start := time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC)
216 end := time.Date(2026, 1, 31, 23, 59, 59, 0, time.UTC)
217
218 act, err := source.Fetch(t.Context(), start, end)
219 if err != nil {
220 t.Fatalf("Fetch() error = %v", err)
221 }
222
223 if len(act.Items) != 1 {
224 t.Fatalf("expected 1 research item, got %d", len(act.Items))
225 }
226
227 item := act.Items[0]
228 if item.Type != "research" {
229 t.Errorf("Type = %q, want %q", item.Type, "research")
230 }
231 if item.Title != "SelfCI Analysis" {
232 t.Errorf("Title = %q, want %q", item.Title, "SelfCI Analysis")
233 }
234}
235
236func TestClaudeSource_FiltersOutsideDateRange(t *testing.T) {
237 historyDir := setupTestHistoryDir(t)
238
239 cfg := &config.ClaudeConfig{
240 Enabled: true,
241 HistoryDir: historyDir,
242 IncludeSessions: true,
243 IncludeLearnings: true,
244 IncludeResearch: true,
245 }
246
247 source := NewClaudeSource(cfg)
248
249 // Query for December 2025 - should return nothing
250 start := time.Date(2025, 12, 1, 0, 0, 0, 0, time.UTC)
251 end := time.Date(2025, 12, 31, 23, 59, 59, 0, time.UTC)
252
253 act, err := source.Fetch(t.Context(), start, end)
254 if err != nil {
255 t.Fatalf("Fetch() error = %v", err)
256 }
257
258 if len(act.Items) != 0 {
259 t.Errorf("expected 0 items outside date range, got %d", len(act.Items))
260 }
261}