flake-update-20260201
1package sources
2
3import (
4 "os/exec"
5 "testing"
6 "time"
7
8 "github.com/vdemeester/home/tools/review-tool/internal/activity"
9 "github.com/vdemeester/home/tools/review-tool/internal/config"
10)
11
12func TestGitHubSource_ParsePRJSON(t *testing.T) {
13 // Test JSON parsing logic directly
14 jsonData := `[{"closedAt":"2026-01-27T10:44:31Z","number":9305,"repository":{"name":"pipeline","nameWithOwner":"tektoncd/pipeline"},"title":"Fix CI workflow","url":"https://github.com/tektoncd/pipeline/pull/9305"}]`
15
16 items, err := parsePRJSON([]byte(jsonData), "pr_merged")
17 if err != nil {
18 t.Fatalf("parsePRJSON() error = %v", err)
19 }
20
21 if len(items) != 1 {
22 t.Fatalf("expected 1 item, got %d", len(items))
23 }
24
25 item := items[0]
26 if item.Title != "Fix CI workflow" {
27 t.Errorf("Title = %q, want %q", item.Title, "Fix CI workflow")
28 }
29 if item.Type != "pr_merged" {
30 t.Errorf("Type = %q, want %q", item.Type, "pr_merged")
31 }
32 if item.Category != activity.CategoryGitHub {
33 t.Errorf("Category = %q, want %q", item.Category, activity.CategoryGitHub)
34 }
35 if item.URL != "https://github.com/tektoncd/pipeline/pull/9305" {
36 t.Errorf("URL = %q, want correct URL", item.URL)
37 }
38 if item.Metadata["repository"] != "tektoncd/pipeline" {
39 t.Errorf("repository = %q, want %q", item.Metadata["repository"], "tektoncd/pipeline")
40 }
41}
42
43func TestGitHubSource_ParseMultiplePRs(t *testing.T) {
44 jsonData := `[
45 {"closedAt":"2026-01-27T10:00:00Z","number":1,"repository":{"nameWithOwner":"org/repo1"},"title":"PR 1","url":"https://github.com/org/repo1/pull/1"},
46 {"closedAt":"2026-01-26T09:00:00Z","number":2,"repository":{"nameWithOwner":"org/repo2"},"title":"PR 2","url":"https://github.com/org/repo2/pull/2"}
47 ]`
48
49 items, err := parsePRJSON([]byte(jsonData), "pr_merged")
50 if err != nil {
51 t.Fatalf("parsePRJSON() error = %v", err)
52 }
53
54 if len(items) != 2 {
55 t.Fatalf("expected 2 items, got %d", len(items))
56 }
57}
58
59func TestGitHubSource_FilterByDateRange(t *testing.T) {
60 // Create items with different dates
61 items := []activity.ActivityItem{
62 {Title: "Old PR", Timestamp: time.Date(2026, 1, 10, 0, 0, 0, 0, time.UTC)},
63 {Title: "Recent PR", Timestamp: time.Date(2026, 1, 25, 0, 0, 0, 0, time.UTC)},
64 {Title: "Future PR", Timestamp: time.Date(2026, 2, 1, 0, 0, 0, 0, time.UTC)},
65 }
66
67 start := time.Date(2026, 1, 20, 0, 0, 0, 0, time.UTC)
68 end := time.Date(2026, 1, 31, 23, 59, 59, 0, time.UTC)
69
70 filtered := filterByDateRange(items, start, end)
71
72 if len(filtered) != 1 {
73 t.Errorf("expected 1 item in range, got %d", len(filtered))
74 }
75 if len(filtered) > 0 && filtered[0].Title != "Recent PR" {
76 t.Errorf("expected 'Recent PR', got %q", filtered[0].Title)
77 }
78}
79
80func TestGitHubSource_ParseDiscussionJSON(t *testing.T) {
81 jsonData := `[
82 {
83 "title": "How to configure CI/CD?",
84 "url": "https://github.com/tektoncd/pipeline/discussions/123",
85 "createdAt": "2026-01-25T14:30:00Z",
86 "repository": "tektoncd/pipeline",
87 "category": "Q&A"
88 }
89 ]`
90
91 items, err := parseDiscussionJSON([]byte(jsonData))
92 if err != nil {
93 t.Fatalf("parseDiscussionJSON() error = %v", err)
94 }
95
96 if len(items) != 1 {
97 t.Fatalf("expected 1 item, got %d", len(items))
98 }
99
100 item := items[0]
101 if item.Title != "How to configure CI/CD?" {
102 t.Errorf("Title = %q, want %q", item.Title, "How to configure CI/CD?")
103 }
104 if item.Type != "discussion" {
105 t.Errorf("Type = %q, want %q", item.Type, "discussion")
106 }
107 if item.Category != activity.CategoryGitHub {
108 t.Errorf("Category = %q, want %q", item.Category, activity.CategoryGitHub)
109 }
110 if item.Metadata["category"] != "Q&A" {
111 t.Errorf("category = %q, want %q", item.Metadata["category"], "Q&A")
112 }
113}
114
115func TestGitHubSource_ParseCommentJSON(t *testing.T) {
116 jsonData := `[
117 {
118 "body": "Thanks for the fix!",
119 "url": "https://github.com/tektoncd/pipeline/issues/456#issuecomment-123",
120 "createdAt": "2026-01-26T10:15:00Z",
121 "repository": "tektoncd/pipeline",
122 "issueTitle": "Bug in pipeline controller",
123 "issueNumber": 456
124 }
125 ]`
126
127 items, err := parseCommentJSON([]byte(jsonData))
128 if err != nil {
129 t.Fatalf("parseCommentJSON() error = %v", err)
130 }
131
132 if len(items) != 1 {
133 t.Fatalf("expected 1 item, got %d", len(items))
134 }
135
136 item := items[0]
137 if item.Title != "Comment on: Bug in pipeline controller" {
138 t.Errorf("Title = %q, want %q", item.Title, "Comment on: Bug in pipeline controller")
139 }
140 if item.Type != "comment" {
141 t.Errorf("Type = %q, want %q", item.Type, "comment")
142 }
143 if item.Metadata["issue_number"] != "456" {
144 t.Errorf("issue_number = %q, want %q", item.Metadata["issue_number"], "456")
145 }
146}
147
148// Integration test - requires gh CLI
149func TestGitHubSource_RealData(t *testing.T) {
150 // Check if gh CLI is available
151 if _, err := exec.LookPath("gh"); err != nil {
152 t.Skip("gh CLI not found, skipping integration test")
153 }
154
155 cfg := &config.GitHubConfig{
156 Enabled: true,
157 IncludePRs: true,
158 IncludeIssues: false,
159 IncludeReviews: false,
160 IncludeCommits: false,
161 }
162
163 source := NewGitHubSource(cfg)
164
165 // Last 7 days
166 now := time.Now()
167 start := time.Date(now.Year(), now.Month(), now.Day()-7, 0, 0, 0, 0, now.Location())
168
169 act, err := source.Fetch(t.Context(), start, now)
170 if err != nil {
171 t.Fatalf("Fetch error: %v", err)
172 }
173
174 t.Logf("Found %d GitHub items", len(act.Items))
175 for i, item := range act.Items {
176 if i < 5 {
177 t.Logf(" [%s] %s (%s)", item.Type, item.Title, item.Metadata["repository"])
178 }
179 }
180}
181
182// Integration test for discussions and comments
183func TestGitHubSource_DiscussionsAndComments(t *testing.T) {
184 if _, err := exec.LookPath("gh"); err != nil {
185 t.Skip("gh CLI not found, skipping integration test")
186 }
187
188 cfg := &config.GitHubConfig{
189 Enabled: true,
190 IncludePRs: false,
191 IncludeIssues: false,
192 IncludeReviews: false,
193 IncludeCommits: false,
194 IncludeDiscussions: true,
195 IncludeComments: true,
196 }
197
198 source := NewGitHubSource(cfg)
199
200 // Last 7 days
201 now := time.Now()
202 start := time.Date(now.Year(), now.Month(), now.Day()-7, 0, 0, 0, 0, now.Location())
203
204 act, err := source.Fetch(t.Context(), start, now)
205 if err != nil {
206 t.Fatalf("Fetch error: %v", err)
207 }
208
209 t.Logf("Found %d discussion/comment items", len(act.Items))
210 for i, item := range act.Items {
211 if i < 10 {
212 t.Logf(" [%s] %s (%s)", item.Type, item.Title, item.Metadata["repository"])
213 }
214 }
215}