TestHandleStreamDrainsAfterCancel: buffered stream events can arrive after Ctrl+C returned phase to idle. Processing them would write ghost tokens, re- populate m.pending, and credit a cancelled turn's usage to sessionTokens. handleStream must drain-only.
(t *testing.T)
| 2543 | |
| 2544 | // TestToolCallFlushesStreamedContent: a tool-call event ends the content phase. |
| 2545 | // Whatever streamed before it is rendered and committed *now*, so the user sees |
| 2546 | // styled text *before* the inline tool-call status, not all at once at turn end. |
| 2547 | func TestToolCallFlushesStreamedContent(t *testing.T) { |
| 2548 | m := newTestModel(t, func(http.ResponseWriter, *http.Request) {}) |
| 2549 | m.phase = phaseStreaming |
| 2550 | m.streaming.WriteString("I'll run bash.") |
| 2551 | call := chmctx.ToolCall{ID: "c1", Name: "bash"} |
| 2552 | out, _ := m.handleStream(llm.Event{Kind: llm.EventToolCall, ToolCall: &call}) |
| 2553 | om := out.(Model) |
| 2554 | if om.streaming.Len() != 0 { |
| 2555 | t.Fatal("tool-call must flush streaming buffer into scroll") |
| 2556 | } |
| 2557 | if !strings.Contains(stripANSI(om.scroll.String()), "I'll run bash") { |
| 2558 | t.Fatalf("content should be committed to scroll before tool-call: %q", om.scroll.String()) |
| 2559 | } |
| 2560 | if len(om.pending) != 1 || om.pending[0].Name != "bash" { |
| 2561 | t.Fatalf("tool-call should land in pending: %+v", om.pending) |
| 2562 | } |
| 2563 | } |
| 2564 | |
| 2565 | // TestCancelMidStreamPreservesStreamedText: Ctrl+C while content is streaming |
| 2566 | // keeps the partial response visible (flushed to scroll) and appends the |
| 2567 | // cancelled marker. The user never loses context they've already read. |
| 2568 | func TestCancelMidStreamPreservesStreamedText(t *testing.T) { |
nothing calls this directly
no test coverage detected