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}