agent_edit_integration_test.go

  1//go:build integration
  2
  3package main
  4
  5import (
  6	"os/exec"
  7	"strings"
  8	"testing"
  9
 10	"github.com/git-bug/git-bug/entities/bug"
 11	"github.com/git-bug/git-bug/entity"
 12	"github.com/git-bug/git-bug/repository"
 13)
 14
 15// TestAgentEditCommand_EditIssue edits an issue as the agent
 16func TestAgentEditCommand_EditIssue(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	// Add origin remote for bug init
 26	remoteCmd := exec.Command("git", "remote", "add", "origin", "[email protected]:test/repo.git")
 27	remoteCmd.Dir = tmpDir
 28	if err := remoteCmd.Run(); err != nil {
 29		t.Fatalf("failed to add origin remote: %v", err)
 30	}
 31
 32	// Initialize git-bug identities (creates both user and agent)
 33	if err := runInitWithReader(tmpDir, strings.NewReader("Test User\[email protected]\n")); err != nil {
 34		t.Fatalf("runInit failed: %v", err)
 35	}
 36
 37	// Create a bug as agent
 38	if err := runAgentNew(tmpDir, "Original Title", "Original description", "", "", false); err != nil {
 39		t.Fatalf("runAgentNew failed: %v", err)
 40	}
 41
 42	// Get the bug ID
 43	repo, err := repository.OpenGoGitRepo(tmpDir, "", nil)
 44	if err != nil {
 45		t.Fatalf("failed to open repo: %v", err)
 46	}
 47
 48	var bugID string
 49	for streamedBug := range bug.ReadAll(repo) {
 50		if streamedBug.Err != nil {
 51			t.Fatalf("failed to read bug: %v", streamedBug.Err)
 52		}
 53		b := streamedBug.Entity
 54		snap := b.Compile()
 55		if snap.Title == "Original Title" {
 56			bugID = b.Id().String()
 57			break
 58		}
 59	}
 60	repo.Close()
 61
 62	if bugID == "" {
 63		t.Fatal("could not find created bug")
 64	}
 65
 66	// Edit as agent
 67	newTitle := "Agent Updated Title"
 68	newMessage := "Agent updated description"
 69	if err := runAgentEdit(tmpDir, bugID, newTitle, newMessage, "", false, ""); err != nil {
 70		t.Fatalf("runAgentEdit failed: %v", err)
 71	}
 72
 73	// Verify both were updated
 74	repo, err = repository.OpenGoGitRepo(tmpDir, "", nil)
 75	if err != nil {
 76		t.Fatalf("failed to open repo: %v", err)
 77	}
 78	defer repo.Close()
 79
 80	b, err := bug.Read(repo, entity.Id(bugID))
 81	if err != nil {
 82		t.Fatalf("failed to read bug: %v", err)
 83	}
 84
 85	snap := b.Compile()
 86	if snap.Title != newTitle {
 87		t.Errorf("title = %q, want %q", snap.Title, newTitle)
 88	}
 89	if len(snap.Comments) == 0 || snap.Comments[0].Message != newMessage {
 90		t.Errorf("description = %q, want %q", snap.Comments[0].Message, newMessage)
 91	}
 92}
 93
 94// TestAgentEditCommand_EditComment edits a comment as the agent
 95func TestAgentEditCommand_EditComment(t *testing.T) {
 96	tmpDir := t.TempDir()
 97
 98	// Initialize a git repo
 99	initCmd := exec.Command("git", "init")
100	initCmd.Dir = tmpDir
101	if err := initCmd.Run(); err != nil {
102		t.Fatalf("failed to init git repo: %v", err)
103	}
104	// Add origin remote for bug init
105	remoteCmd := exec.Command("git", "remote", "add", "origin", "[email protected]:test/repo.git")
106	remoteCmd.Dir = tmpDir
107	if err := remoteCmd.Run(); err != nil {
108		t.Fatalf("failed to add origin remote: %v", err)
109	}
110
111	// Initialize git-bug identities
112	if err := runInitWithReader(tmpDir, strings.NewReader("Test User\[email protected]\n")); err != nil {
113		t.Fatalf("runInit failed: %v", err)
114	}
115
116	// Create a bug as agent
117	if err := runAgentNew(tmpDir, "Test Bug", "Description", "", "", false); err != nil {
118		t.Fatalf("runAgentNew failed: %v", err)
119	}
120
121	// Get the bug ID
122	repo, err := repository.OpenGoGitRepo(tmpDir, "", nil)
123	if err != nil {
124		t.Fatalf("failed to open repo: %v", err)
125	}
126
127	var bugID string
128	for streamedBug := range bug.ReadAll(repo) {
129		if streamedBug.Err != nil {
130			t.Fatalf("failed to read bug: %v", streamedBug.Err)
131		}
132		b := streamedBug.Entity
133		snap := b.Compile()
134		if snap.Title == "Test Bug" {
135			bugID = b.Id().String()
136			break
137		}
138	}
139	repo.Close()
140
141	// Add a comment as agent
142	originalComment := "Original agent comment"
143	if err := runAgentComment(tmpDir, bugID, originalComment, "", false); err != nil {
144		t.Fatalf("runAgentComment failed: %v", err)
145	}
146
147	// Get the comment ID
148	repo, err = repository.OpenGoGitRepo(tmpDir, "", nil)
149	if err != nil {
150		t.Fatalf("failed to open repo: %v", err)
151	}
152
153	b, err := bug.Read(repo, entity.Id(bugID))
154	if err != nil {
155		t.Fatalf("failed to read bug: %v", err)
156	}
157	snap := b.Compile()
158	if len(snap.Comments) < 2 {
159		t.Fatal("expected at least 2 comments")
160	}
161	commentID := snap.Comments[1].CombinedId().String()
162	repo.Close()
163
164	// Edit the comment as agent
165	newComment := "Updated agent comment"
166	if err := runAgentEdit(tmpDir, commentID, "", newComment, "", false, ""); err != nil {
167		t.Fatalf("runAgentEdit failed: %v", err)
168	}
169
170	// Verify comment was updated
171	repo, err = repository.OpenGoGitRepo(tmpDir, "", nil)
172	if err != nil {
173		t.Fatalf("failed to open repo: %v", err)
174	}
175	defer repo.Close()
176
177	b, err = bug.Read(repo, entity.Id(bugID))
178	if err != nil {
179		t.Fatalf("failed to read bug: %v", err)
180	}
181
182	snap = b.Compile()
183	if len(snap.Comments) < 2 {
184		t.Fatal("expected at least 2 comments")
185	}
186	if snap.Comments[1].Message != newComment {
187		t.Errorf("comment = %q, want %q", snap.Comments[1].Message, newComment)
188	}
189}
190
191// TestAgentEditCommand_RequiresMessage tests that agent edit requires at least one field
192func TestAgentEditCommand_RequiresMessage(t *testing.T) {
193	tmpDir := t.TempDir()
194
195	// Initialize a git repo
196	initCmd := exec.Command("git", "init")
197	initCmd.Dir = tmpDir
198	if err := initCmd.Run(); err != nil {
199		t.Fatalf("failed to init git repo: %v", err)
200	}
201	// Add origin remote for bug init
202	remoteCmd := exec.Command("git", "remote", "add", "origin", "[email protected]:test/repo.git")
203	remoteCmd.Dir = tmpDir
204	if err := remoteCmd.Run(); err != nil {
205		t.Fatalf("failed to add origin remote: %v", err)
206	}
207
208	// Initialize git-bug identities
209	if err := runInitWithReader(tmpDir, strings.NewReader("Test User\[email protected]\n")); err != nil {
210		t.Fatalf("runInit failed: %v", err)
211	}
212
213	// Create a bug as agent
214	if err := runAgentNew(tmpDir, "Test Bug", "Description", "", "", false); err != nil {
215		t.Fatalf("runAgentNew failed: %v", err)
216	}
217
218	// Get the bug ID
219	repo, err := repository.OpenGoGitRepo(tmpDir, "", nil)
220	if err != nil {
221		t.Fatalf("failed to open repo: %v", err)
222	}
223
224	var bugID string
225	for streamedBug := range bug.ReadAll(repo) {
226		if streamedBug.Err != nil {
227			t.Fatalf("failed to read bug: %v", streamedBug.Err)
228		}
229		b := streamedBug.Entity
230		snap := b.Compile()
231		if snap.Title == "Test Bug" {
232			bugID = b.Id().String()
233			break
234		}
235	}
236	repo.Close()
237
238	// Add a comment as agent
239	if err := runAgentComment(tmpDir, bugID, "Original comment", "", false); err != nil {
240		t.Fatalf("runAgentComment failed: %v", err)
241	}
242
243	// Get the comment ID
244	repo, err = repository.OpenGoGitRepo(tmpDir, "", nil)
245	if err != nil {
246		t.Fatalf("failed to open repo: %v", err)
247	}
248
249	b, err := bug.Read(repo, entity.Id(bugID))
250	if err != nil {
251		t.Fatalf("failed to read bug: %v", err)
252	}
253	snap := b.Compile()
254	commentID := snap.Comments[1].CombinedId().String()
255	repo.Close()
256
257	// Try to edit comment without message
258	err = runAgentEdit(tmpDir, commentID, "", "", "", false, "")
259	if err == nil {
260		t.Error("expected error when editing comment without message, got nil")
261	}
262
263	if !strings.Contains(err.Error(), "either --title or --message") {
264		t.Errorf("expected 'either --title or --message' error, got: %v", err)
265	}
266}
267
268// TestAgentEditCommand_RequiresAtLeastOneField tests that agent edit requires at least one field
269func TestAgentEditCommand_RequiresAtLeastOneField(t *testing.T) {
270	tmpDir := t.TempDir()
271
272	// Initialize a git repo
273	initCmd := exec.Command("git", "init")
274	initCmd.Dir = tmpDir
275	if err := initCmd.Run(); err != nil {
276		t.Fatalf("failed to init git repo: %v", err)
277	}
278	// Add origin remote for bug init
279	remoteCmd := exec.Command("git", "remote", "add", "origin", "[email protected]:test/repo.git")
280	remoteCmd.Dir = tmpDir
281	if err := remoteCmd.Run(); err != nil {
282		t.Fatalf("failed to add origin remote: %v", err)
283	}
284
285	// Initialize git-bug identities
286	if err := runInitWithReader(tmpDir, strings.NewReader("Test User\[email protected]\n")); err != nil {
287		t.Fatalf("runInit failed: %v", err)
288	}
289
290	// Create a bug as agent
291	if err := runAgentNew(tmpDir, "Test Bug", "Description", "", "", false); err != nil {
292		t.Fatalf("runAgentNew failed: %v", err)
293	}
294
295	// Get the bug ID
296	repo, err := repository.OpenGoGitRepo(tmpDir, "", nil)
297	if err != nil {
298		t.Fatalf("failed to open repo: %v", err)
299	}
300
301	var bugID string
302	for streamedBug := range bug.ReadAll(repo) {
303		if streamedBug.Err != nil {
304			t.Fatalf("failed to read bug: %v", streamedBug.Err)
305		}
306		b := streamedBug.Entity
307		snap := b.Compile()
308		if snap.Title == "Test Bug" {
309			bugID = b.Id().String()
310			break
311		}
312	}
313	repo.Close()
314
315	// Try to edit without any flags
316	err = runAgentEdit(tmpDir, bugID, "", "", "", false, "")
317	if err == nil {
318		t.Error("expected error when editing without any fields, got nil")
319	}
320
321	if !strings.Contains(err.Error(), "at least one of --title, --message, or --parent") {
322		t.Errorf("expected 'at least one of --title, --message, or --parent' error, got: %v", err)
323	}
324}
325
326// TestAgentEditCommand_OnlyTitle edits only the title as agent
327func TestAgentEditCommand_OnlyTitle(t *testing.T) {
328	tmpDir := t.TempDir()
329
330	// Initialize a git repo
331	initCmd := exec.Command("git", "init")
332	initCmd.Dir = tmpDir
333	if err := initCmd.Run(); err != nil {
334		t.Fatalf("failed to init git repo: %v", err)
335	}
336	// Add origin remote for bug init
337	remoteCmd := exec.Command("git", "remote", "add", "origin", "[email protected]:test/repo.git")
338	remoteCmd.Dir = tmpDir
339	if err := remoteCmd.Run(); err != nil {
340		t.Fatalf("failed to add origin remote: %v", err)
341	}
342
343	// Initialize git-bug identities
344	if err := runInitWithReader(tmpDir, strings.NewReader("Test User\[email protected]\n")); err != nil {
345		t.Fatalf("runInit failed: %v", err)
346	}
347
348	// Create a bug as agent
349	originalTitle := "Original Title"
350	originalDesc := "Original description"
351	if err := runAgentNew(tmpDir, originalTitle, originalDesc, "", "", false); err != nil {
352		t.Fatalf("runAgentNew failed: %v", err)
353	}
354
355	// Get the bug ID
356	repo, err := repository.OpenGoGitRepo(tmpDir, "", nil)
357	if err != nil {
358		t.Fatalf("failed to open repo: %v", err)
359	}
360
361	var bugID string
362	for streamedBug := range bug.ReadAll(repo) {
363		if streamedBug.Err != nil {
364			t.Fatalf("failed to read bug: %v", streamedBug.Err)
365		}
366		b := streamedBug.Entity
367		snap := b.Compile()
368		if snap.Title == originalTitle {
369			bugID = b.Id().String()
370			break
371		}
372	}
373	repo.Close()
374
375	// Edit only title as agent
376	newTitle := "New Title"
377	if err := runAgentEdit(tmpDir, bugID, newTitle, "", "", false, ""); err != nil {
378		t.Fatalf("runAgentEdit failed: %v", err)
379	}
380
381	// Verify only title changed
382	repo, err = repository.OpenGoGitRepo(tmpDir, "", nil)
383	if err != nil {
384		t.Fatalf("failed to open repo: %v", err)
385	}
386	defer repo.Close()
387
388	b, err := bug.Read(repo, entity.Id(bugID))
389	if err != nil {
390		t.Fatalf("failed to read bug: %v", err)
391	}
392
393	snap := b.Compile()
394	if snap.Title != newTitle {
395		t.Errorf("title = %q, want %q", snap.Title, newTitle)
396	}
397	if len(snap.Comments) == 0 || snap.Comments[0].Message != originalDesc {
398		t.Errorf("description was changed unexpectedly")
399	}
400}