(t *testing.T)
| 373 | } |
| 374 | |
| 375 | func Test_Emitter_CalledOnChanges(t *testing.T) { |
| 376 | mClock := quartz.NewMock(t) |
| 377 | mock := newMockAgentIO() |
| 378 | // Block the write so we can simulate chunks during processing |
| 379 | started, done := mock.BlockWrite() |
| 380 | |
| 381 | emitter := newMockEmitter() |
| 382 | |
| 383 | ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) |
| 384 | defer cancel() |
| 385 | |
| 386 | conv := acpio.NewACPConversation(ctx, mock, nil, nil, emitter, mClock) |
| 387 | conv.Start(ctx) |
| 388 | |
| 389 | // Send blocks, so run in a goroutine |
| 390 | errCh := make(chan error, 1) |
| 391 | go func() { errCh <- conv.Send(screentracker.MessagePartText{Content: "test"}) }() |
| 392 | |
| 393 | // Wait for write to start |
| 394 | <-started |
| 395 | |
| 396 | // Simulate chunks - each should trigger emitter calls |
| 397 | mock.SimulateChunks("chunk1") |
| 398 | mock.SimulateChunks("chunk2") |
| 399 | |
| 400 | emitter.mu.Lock() |
| 401 | messagesCallsBeforeComplete := emitter.messagesCalls |
| 402 | emitter.mu.Unlock() |
| 403 | |
| 404 | // Should have emit calls from chunks (each chunk emits messages, status, and screen) |
| 405 | assert.Equal(t, 2, messagesCallsBeforeComplete) |
| 406 | |
| 407 | // Unblock the write to complete processing |
| 408 | close(done) |
| 409 | require.NoError(t, <-errCh) |
| 410 | |
| 411 | // Wait for completion emit |
| 412 | emitter.WaitForStatus(ctx, t, screentracker.ConversationStatusStable) |
| 413 | |
| 414 | emitter.mu.Lock() |
| 415 | finalMessagesCalls := emitter.messagesCalls |
| 416 | emitter.mu.Unlock() |
| 417 | assert.GreaterOrEqual(t, finalMessagesCalls, 3, "2 from chunks + 1 from completion") |
| 418 | } |
| 419 | |
| 420 | func Test_InitialPrompt_SentOnStart(t *testing.T) { |
| 421 | mClock := quartz.NewMock(t) |
nothing calls this directly
no test coverage detected