agent_integration_test.go
1//go:build integration
2
3package main
4
5import (
6 "os"
7 "os/exec"
8 "strings"
9 "testing"
10
11 "github.com/git-bug/git-bug/entities/bug"
12 "github.com/git-bug/git-bug/repository"
13)
14
15// TestAgentNewCommand_WithFlags creates a bug as agent using flags
16func TestAgentNewCommand_WithFlags(t *testing.T) {
17 tmpDir := t.TempDir()
18
19 // Initialize a git repo
20 initCmd := exec.Command("git", "init")
21 initCmd.Dir = tmpDir
22 if err := initCmd.Run(); err != nil {
23 t.Fatalf("failed to init git repo: %v", err)
24 }
25
26 // Initialize git-bug with both user and agent identities
27 if err := createIdentity(tmpDir, "Test User", "[email protected]", true); err != nil {
28 t.Fatalf("failed to create user identity: %v", err)
29 }
30 if err := createIdentity(tmpDir, "agent", "", false); err != nil {
31 t.Fatalf("failed to create agent identity: %v", err)
32 }
33
34 // Create a bug as agent using flags
35 title := "Agent Created Bug"
36 message := "This bug was created by an automated agent"
37 if err := runAgentNew(tmpDir, title, message, "", "", false); err != nil {
38 t.Fatalf("runAgentNew failed: %v", err)
39 }
40
41 // Verify bug was created with agent as author
42 repo, err := repository.OpenGoGitRepo(tmpDir, "", nil)
43 if err != nil {
44 t.Fatalf("failed to open repo: %v", err)
45 }
46 defer repo.Close()
47
48 // Count bugs
49 bugCount := 0
50 for streamedBug := range bug.ReadAll(repo) {
51 if streamedBug.Err != nil {
52 t.Fatalf("failed to read bug: %v", streamedBug.Err)
53 }
54 b := streamedBug.Entity
55 snap := b.Compile()
56
57 if snap.Title == title {
58 bugCount++
59 if snap.Comments[0].Message != message {
60 t.Errorf("message = %q, want %q", snap.Comments[0].Message, message)
61 }
62 if snap.Author.Name() != "agent" {
63 t.Errorf("author = %q, want %q", snap.Author.Name(), "agent")
64 }
65 if snap.Author.Email() != "" {
66 t.Errorf("author email = %q, want empty", snap.Author.Email())
67 }
68 }
69 }
70
71 if bugCount != 1 {
72 t.Errorf("expected 1 bug with title %q, found %d", title, bugCount)
73 }
74}
75
76// TestAgentNewCommand_MissingAgentIdentity tests error when agent not initialized
77func TestAgentNewCommand_MissingAgentIdentity(t *testing.T) {
78 tmpDir := t.TempDir()
79
80 // Initialize a git repo
81 initCmd := exec.Command("git", "init")
82 initCmd.Dir = tmpDir
83 if err := initCmd.Run(); err != nil {
84 t.Fatalf("failed to init git repo: %v", err)
85 }
86
87 // Only create user identity, NOT agent
88 if err := createIdentity(tmpDir, "Test User", "[email protected]", true); err != nil {
89 t.Fatalf("failed to create user identity: %v", err)
90 }
91
92 // Try to create a bug as agent (should fail)
93 err := runAgentNew(tmpDir, "Title", "Message", "", "", false)
94 if err == nil {
95 t.Error("expected error when agent identity not found, got nil")
96 }
97
98 if !strings.Contains(err.Error(), "agent identity not found") {
99 t.Errorf("expected 'agent identity not found' error, got: %v", err)
100 }
101}
102
103// TestAgentNewCommand_EmptyTitleError tests error for empty title
104func TestAgentNewCommand_EmptyTitleError(t *testing.T) {
105 tmpDir := t.TempDir()
106
107 // Initialize a git repo
108 initCmd := exec.Command("git", "init")
109 initCmd.Dir = tmpDir
110 if err := initCmd.Run(); err != nil {
111 t.Fatalf("failed to init git repo: %v", err)
112 }
113
114 // Initialize identities
115 if err := createIdentity(tmpDir, "Test User", "[email protected]", true); err != nil {
116 t.Fatalf("failed to create user identity: %v", err)
117 }
118 if err := createIdentity(tmpDir, "agent", "", false); err != nil {
119 t.Fatalf("failed to create agent identity: %v", err)
120 }
121
122 // Try with empty title
123 err := runAgentNew(tmpDir, " ", "Message", "", "", false)
124 if err == nil {
125 t.Error("expected error for empty title, got nil")
126 }
127
128 if !strings.Contains(err.Error(), "title cannot be empty") {
129 t.Errorf("expected 'title cannot be empty' error, got: %v", err)
130 }
131}
132
133// TestAgentNewCommand_EmptyMessageError tests error for empty message
134func TestAgentNewCommand_EmptyMessageError(t *testing.T) {
135 tmpDir := t.TempDir()
136
137 // Initialize a git repo
138 initCmd := exec.Command("git", "init")
139 initCmd.Dir = tmpDir
140 if err := initCmd.Run(); err != nil {
141 t.Fatalf("failed to init git repo: %v", err)
142 }
143
144 // Initialize identities
145 if err := createIdentity(tmpDir, "Test User", "[email protected]", true); err != nil {
146 t.Fatalf("failed to create user identity: %v", err)
147 }
148 if err := createIdentity(tmpDir, "agent", "", false); err != nil {
149 t.Fatalf("failed to create agent identity: %v", err)
150 }
151
152 // Try with empty message
153 err := runAgentNew(tmpDir, "Title", " ", "", "", false)
154 if err == nil {
155 t.Error("expected error for empty message, got nil")
156 }
157
158 if !strings.Contains(err.Error(), "message cannot be empty") {
159 t.Errorf("expected 'message cannot be empty' error, got: %v", err)
160 }
161}
162
163// TestGetAgentIdentity_Success tests retrieving agent identity
164func TestGetAgentIdentity_Success(t *testing.T) {
165 tmpDir := t.TempDir()
166
167 // Initialize a git repo
168 initCmd := exec.Command("git", "init")
169 initCmd.Dir = tmpDir
170 if err := initCmd.Run(); err != nil {
171 t.Fatalf("failed to init git repo: %v", err)
172 }
173
174 // Create user and agent identities
175 if err := createIdentity(tmpDir, "Test User", "[email protected]", true); err != nil {
176 t.Fatalf("failed to create user identity: %v", err)
177 }
178 if err := createIdentity(tmpDir, "agent", "", false); err != nil {
179 t.Fatalf("failed to create agent identity: %v", err)
180 }
181
182 // Open repo and get agent identity
183 repo, err := repository.OpenGoGitRepo(tmpDir, "", nil)
184 if err != nil {
185 t.Fatalf("failed to open repo: %v", err)
186 }
187 defer repo.Close()
188
189 agent, err := getAgentIdentity(repo)
190 if err != nil {
191 t.Fatalf("getAgentIdentity failed: %v", err)
192 }
193
194 if agent.Name() != "agent" {
195 t.Errorf("agent name = %q, want %q", agent.Name(), "agent")
196 }
197
198 if agent.Email() != "" {
199 t.Errorf("agent email = %q, want empty", agent.Email())
200 }
201}
202
203// TestGetAgentIdentity_NotFound tests error when agent doesn't exist
204func TestGetAgentIdentity_NotFound(t *testing.T) {
205 tmpDir := t.TempDir()
206
207 // Initialize a git repo
208 initCmd := exec.Command("git", "init")
209 initCmd.Dir = tmpDir
210 if err := initCmd.Run(); err != nil {
211 t.Fatalf("failed to init git repo: %v", err)
212 }
213
214 // Only create user identity
215 if err := createIdentity(tmpDir, "Test User", "[email protected]", true); err != nil {
216 t.Fatalf("failed to create user identity: %v", err)
217 }
218
219 // Open repo and try to get agent identity
220 repo, err := repository.OpenGoGitRepo(tmpDir, "", nil)
221 if err != nil {
222 t.Fatalf("failed to open repo: %v", err)
223 }
224 defer repo.Close()
225
226 _, err = getAgentIdentity(repo)
227 if err == nil {
228 t.Error("expected error when agent identity not found, got nil")
229 }
230
231 if !strings.Contains(err.Error(), "agent identity not found") {
232 t.Errorf("expected 'agent identity not found' error, got: %v", err)
233 }
234}
235
236// TestReadMessageSource_FromFile tests reading message from file
237func TestReadMessageSource_FromFile(t *testing.T) {
238 tmpDir := t.TempDir()
239
240 // Create a test file with message content
241 messageContent := "This is a test message from file\nWith multiple lines\nAnd **markdown** formatting!"
242 testFile := tmpDir + "/test_message.txt"
243 if err := os.WriteFile(testFile, []byte(messageContent), 0644); err != nil {
244 t.Fatalf("failed to create test file: %v", err)
245 }
246
247 // Test reading from file
248 result, err := readMessageSource(testFile, false, "", true)
249 if err != nil {
250 t.Fatalf("readMessageSource failed: %v", err)
251 }
252
253 // Content should be trimmed of whitespace
254 expected := strings.TrimSpace(messageContent)
255 if result != expected {
256 t.Errorf("result = %q, want %q", result, expected)
257 }
258}
259
260// TestReadMessageSource_FromFile_NotFound tests error when file doesn't exist
261func TestReadMessageSource_FromFile_NotFound(t *testing.T) {
262 result, err := readMessageSource("/nonexistent/path/file.txt", false, "", true)
263 if err == nil {
264 t.Error("expected error for non-existent file, got nil")
265 }
266
267 if result != "" {
268 t.Errorf("expected empty result, got %q", result)
269 }
270
271 if !strings.Contains(err.Error(), "failed to read message from file") {
272 t.Errorf("expected 'failed to read message from file' error, got: %v", err)
273 }
274}
275
276// TestReadMessageSource_MessageFlag tests using message flag
277func TestReadMessageSource_MessageFlag(t *testing.T) {
278 message := "Test message from flag"
279 result, err := readMessageSource("", false, message, true)
280 if err != nil {
281 t.Fatalf("readMessageSource failed: %v", err)
282 }
283
284 if result != message {
285 t.Errorf("result = %q, want %q", result, message)
286 }
287}
288
289// TestReadMessageSource_MultipleSources tests error when multiple sources specified
290func TestReadMessageSource_MultipleSources(t *testing.T) {
291 // Test --message and --stdin
292 _, err := readMessageSource("", true, "message", true)
293 if err == nil {
294 t.Error("expected error for multiple sources, got nil")
295 }
296 if !strings.Contains(err.Error(), "multiple message sources specified") {
297 t.Errorf("expected 'multiple message sources specified' error, got: %v", err)
298 }
299
300 // Test --message and --from-file
301 _, err = readMessageSource("/path/to/file", false, "message", true)
302 if err == nil {
303 t.Error("expected error for multiple sources, got nil")
304 }
305 if !strings.Contains(err.Error(), "multiple message sources specified") {
306 t.Errorf("expected 'multiple message sources specified' error, got: %v", err)
307 }
308
309 // Test --stdin and --from-file
310 _, err = readMessageSource("/path/to/file", true, "", true)
311 if err == nil {
312 t.Error("expected error for multiple sources, got nil")
313 }
314 if !strings.Contains(err.Error(), "multiple message sources specified") {
315 t.Errorf("expected 'multiple message sources specified' error, got: %v", err)
316 }
317}
318
319// TestReadMessageSource_NoSource tests error when no source specified but required
320func TestReadMessageSource_NoSource(t *testing.T) {
321 _, err := readMessageSource("", false, "", true)
322 if err == nil {
323 t.Error("expected error for no source, got nil")
324 }
325 if !strings.Contains(err.Error(), "message content required") {
326 t.Errorf("expected 'message content required' error, got: %v", err)
327 }
328}
329
330// TestReadMessageSource_NoSourceOptional tests no error when no source and not required
331func TestReadMessageSource_NoSourceOptional(t *testing.T) {
332 result, err := readMessageSource("", false, "", false)
333 if err != nil {
334 t.Fatalf("readMessageSource failed: %v", err)
335 }
336 if result != "" {
337 t.Errorf("expected empty result, got %q", result)
338 }
339}