Skip to content

Commit a2d685e

Browse files
authored
Merge pull request #29 from phantom5099/fork-pr-337-1776410957
test: 提高 PR #337 覆盖率
2 parents 6d9f3e8 + dd7e3b9 commit a2d685e

3 files changed

Lines changed: 162 additions & 0 deletions

File tree

internal/session/input_preparer_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,31 @@ func TestInputPreparerPrepareImagePathAndMimeValidation(t *testing.T) {
308308
})
309309
}
310310

311+
func TestAssetSaveErrorMethods(t *testing.T) {
312+
t.Parallel()
313+
314+
if err := (*AssetSaveError)(nil).Unwrap(); err != nil {
315+
t.Fatalf("expected nil asset save error unwrap to return nil, got %v", err)
316+
}
317+
if msg := (*AssetSaveError)(nil).Error(); msg != "session: asset save failed" {
318+
t.Fatalf("unexpected nil asset save error message: %q", msg)
319+
}
320+
321+
inner := errors.New("boom")
322+
assetErr := &AssetSaveError{
323+
SessionID: "session-1",
324+
Index: 2,
325+
Path: "/tmp/image.png",
326+
Err: inner,
327+
}
328+
if !errors.Is(assetErr, inner) {
329+
t.Fatalf("expected asset save error to unwrap inner error")
330+
}
331+
if !strings.Contains(assetErr.Error(), "image.png") || !strings.Contains(assetErr.Error(), "index 2") {
332+
t.Fatalf("unexpected asset save error message: %q", assetErr.Error())
333+
}
334+
}
335+
311336
func minimalPNGBytes() []byte {
312337
return []byte{
313338
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a,

internal/tui/core/app/input_features_test.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,53 @@ func TestAbsorbInlineImageReferencesSupportsQuotedPathWithSpaces(t *testing.T) {
301301
}
302302
}
303303

304+
func TestParseInlineImagePathToken(t *testing.T) {
305+
app, _ := newTestApp(t)
306+
root := t.TempDir()
307+
app.state.CurrentWorkdir = root
308+
309+
relative, ok := app.parseInlineImagePathToken(`@image:"charts/sales q1.png"`)
310+
if !ok {
311+
t.Fatalf("expected quoted relative token to parse")
312+
}
313+
if relative != filepath.Join(root, filepath.FromSlash("charts/sales q1.png")) {
314+
t.Fatalf("unexpected resolved path: %q", relative)
315+
}
316+
317+
absolutePath := filepath.Join(root, "abs.png")
318+
absolute, ok := app.parseInlineImagePathToken("@image:" + absolutePath)
319+
if !ok || absolute != absolutePath {
320+
t.Fatalf("expected absolute token to pass through, got %q ok=%v", absolute, ok)
321+
}
322+
323+
if _, ok := app.parseInlineImagePathToken("@image:notes.txt"); ok {
324+
t.Fatalf("expected non-image token to be rejected")
325+
}
326+
app.state.CurrentWorkdir = ""
327+
if _, ok := app.parseInlineImagePathToken("@image:relative.png"); ok {
328+
t.Fatalf("expected missing workdir to reject relative token")
329+
}
330+
if _, ok := app.parseInlineImagePathToken("not-image-token"); ok {
331+
t.Fatalf("expected invalid token to be rejected")
332+
}
333+
}
334+
335+
func TestParseInlineImageReferenceAtBranches(t *testing.T) {
336+
if _, _, ok := parseInlineImageReferenceAt("x@image:a.png", 1); ok {
337+
t.Fatalf("expected token without boundary whitespace to be rejected")
338+
}
339+
path, end, ok := parseInlineImageReferenceAt(`@image:folder\ with\ space.png next`, 0)
340+
if !ok {
341+
t.Fatalf("expected escaped-space token to parse")
342+
}
343+
if path != "folder with space.png" || end <= 0 {
344+
t.Fatalf("unexpected escaped path parse result path=%q end=%d", path, end)
345+
}
346+
if _, _, ok := parseInlineImageReferenceAt(`@image:""`, 0); ok {
347+
t.Fatalf("expected empty quoted token to fail")
348+
}
349+
}
350+
304351
func TestGetAndClearImageAttachments(t *testing.T) {
305352
app, _ := newTestApp(t)
306353
app.pendingImageAttachments = []pendingImageAttachment{

internal/tui/core/app/update_runtime_events_test.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package tui
22

33
import (
4+
"strings"
45
"testing"
56

67
agentruntime "neo-code/internal/runtime"
@@ -161,3 +162,92 @@ func TestShouldHandleRuntimeEventFiltersBySessionAndRun(t *testing.T) {
161162
t.Fatalf("expected matched event to be handled")
162163
}
163164
}
165+
166+
func TestRuntimeEventMultimodalHandlers(t *testing.T) {
167+
t.Parallel()
168+
169+
app, _ := newTestApp(t)
170+
171+
if handled := runtimeEventInputNormalizedHandler(&app, agentruntime.RuntimeEvent{Payload: "bad"}); handled {
172+
t.Fatalf("expected invalid normalized payload to return false")
173+
}
174+
runtimeEventInputNormalizedHandler(&app, agentruntime.RuntimeEvent{
175+
RunID: "run-1",
176+
Payload: agentruntime.InputNormalizedPayload{
177+
TextLength: 12,
178+
ImageCount: 2,
179+
},
180+
})
181+
if app.state.ActiveRunID != "run-1" {
182+
t.Fatalf("expected active run id to be updated, got %q", app.state.ActiveRunID)
183+
}
184+
if len(app.activities) == 0 {
185+
t.Fatalf("expected input normalized activity to be appended")
186+
}
187+
last := app.activities[len(app.activities)-1]
188+
if last.Title != "Input normalized" || !strings.Contains(last.Detail, "images=2") {
189+
t.Fatalf("unexpected normalized activity: %+v", last)
190+
}
191+
192+
before := len(app.activities)
193+
runtimeEventAssetSavedHandler(&app, agentruntime.RuntimeEvent{
194+
Payload: agentruntime.AssetSavedPayload{
195+
AssetID: "asset-1",
196+
Path: "/tmp/chart.png",
197+
},
198+
})
199+
if len(app.activities) != before+1 {
200+
t.Fatalf("expected saved attachment activity appended")
201+
}
202+
last = app.activities[len(app.activities)-1]
203+
if last.Title != "Saved attachment" || !strings.Contains(last.Detail, "chart.png") {
204+
t.Fatalf("unexpected asset saved activity: %+v", last)
205+
}
206+
if handled := runtimeEventAssetSavedHandler(&app, agentruntime.RuntimeEvent{Payload: 123}); handled {
207+
t.Fatalf("expected invalid asset_saved payload to return false")
208+
}
209+
210+
runtimeEventAssetSaveFailedHandler(&app, agentruntime.RuntimeEvent{
211+
Payload: agentruntime.AssetSaveFailedPayload{Message: " failed "},
212+
})
213+
if app.state.ExecutionError != "failed" || app.state.StatusText != "failed" {
214+
t.Fatalf("expected failed status to be surfaced, got status=%q err=%q", app.state.StatusText, app.state.ExecutionError)
215+
}
216+
last = app.activities[len(app.activities)-1]
217+
if !last.IsError || last.Title != "Failed to save attachment" {
218+
t.Fatalf("unexpected asset save failed activity: %+v", last)
219+
}
220+
runtimeEventAssetSaveFailedHandler(&app, agentruntime.RuntimeEvent{
221+
Payload: agentruntime.AssetSaveFailedPayload{},
222+
})
223+
if app.state.ExecutionError != "failed to save attachment" || app.state.StatusText != "failed to save attachment" {
224+
t.Fatalf("expected default failed message, got status=%q err=%q", app.state.StatusText, app.state.ExecutionError)
225+
}
226+
if handled := runtimeEventAssetSaveFailedHandler(&app, agentruntime.RuntimeEvent{Payload: true}); handled {
227+
t.Fatalf("expected invalid asset_save_failed payload to return false")
228+
}
229+
}
230+
231+
func TestHandleRuntimeEventSetsSessionAndRoutesByRegistry(t *testing.T) {
232+
t.Parallel()
233+
234+
app, _ := newTestApp(t)
235+
handled := app.handleRuntimeEvent(agentruntime.RuntimeEvent{
236+
Type: agentruntime.EventAssetSaved,
237+
SessionID: "session-1",
238+
Payload: agentruntime.AssetSavedPayload{AssetID: "asset-1"},
239+
})
240+
if handled {
241+
t.Fatalf("expected asset_saved handler to return false")
242+
}
243+
if app.state.ActiveSessionID != "session-1" {
244+
t.Fatalf("expected active session to be set from event, got %q", app.state.ActiveSessionID)
245+
}
246+
if len(app.activities) == 0 || app.activities[len(app.activities)-1].Title != "Saved attachment" {
247+
t.Fatalf("expected saved attachment activity")
248+
}
249+
250+
if app.handleRuntimeEvent(agentruntime.RuntimeEvent{Type: "unknown_event", SessionID: "session-1"}) {
251+
t.Fatalf("expected unknown event handler result to be false")
252+
}
253+
}

0 commit comments

Comments
 (0)