11
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
package cc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func withRunner(fn func(ctx context.Context, cwd string, args []string) ([]byte, []byte, error)) func() {
|
||||
orig := RunClaude
|
||||
RunClaude = fn
|
||||
return func() { RunClaude = orig }
|
||||
}
|
||||
|
||||
func TestSpawnClaude_CleanJSON(t *testing.T) {
|
||||
restore := withRunner(func(_ context.Context, _ string, _ []string) ([]byte, []byte, error) {
|
||||
return []byte(`{"result":"ok","session_id":"abc123"}`), nil, nil
|
||||
})
|
||||
defer restore()
|
||||
|
||||
res, err := SpawnClaude(context.Background(), Opts{Prompt: "hello"})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if res.SessionID != "abc123" {
|
||||
t.Errorf("SessionID = %q, want abc123", res.SessionID)
|
||||
}
|
||||
if res.ResultText != "ok" {
|
||||
t.Errorf("ResultText = %q, want ok", res.ResultText)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSpawnClaude_NDJSONTail(t *testing.T) {
|
||||
ndjson := `{"type":"progress","data":"thinking"}
|
||||
{"type":"progress","data":"still thinking"}
|
||||
{"result":"done","session_id":"sess99"}`
|
||||
|
||||
restore := withRunner(func(_ context.Context, _ string, _ []string) ([]byte, []byte, error) {
|
||||
return []byte(ndjson), nil, nil
|
||||
})
|
||||
defer restore()
|
||||
|
||||
res, err := SpawnClaude(context.Background(), Opts{Prompt: "go"})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if res.SessionID != "sess99" {
|
||||
t.Errorf("SessionID = %q, want sess99", res.SessionID)
|
||||
}
|
||||
if res.ResultText != "done" {
|
||||
t.Errorf("ResultText = %q, want done", res.ResultText)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSpawnClaude_NonZeroExit(t *testing.T) {
|
||||
restore := withRunner(func(_ context.Context, _ string, _ []string) ([]byte, []byte, error) {
|
||||
return nil, []byte("something went wrong"), errors.New("exit status 1")
|
||||
})
|
||||
defer restore()
|
||||
|
||||
_, err := SpawnClaude(context.Background(), Opts{Prompt: "hi"})
|
||||
if err == nil {
|
||||
t.Fatal("expected error, got nil")
|
||||
}
|
||||
var ce *ClaudeError
|
||||
if !errors.As(err, &ce) {
|
||||
t.Errorf("expected ClaudeError, got %T: %v", err, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSpawnClaude_Timeout(t *testing.T) {
|
||||
restore := withRunner(func(ctx context.Context, _ string, _ []string) ([]byte, []byte, error) {
|
||||
// Respect context cancellation — as the real runner would.
|
||||
<-ctx.Done()
|
||||
return nil, nil, ctx.Err()
|
||||
})
|
||||
defer restore()
|
||||
|
||||
_, err := SpawnClaude(context.Background(), Opts{Prompt: "slow", TimeoutMs: 1})
|
||||
if err == nil {
|
||||
t.Fatal("expected timeout error, got nil")
|
||||
}
|
||||
var te *ClaudeTimeoutError
|
||||
if !errors.As(err, &te) {
|
||||
t.Errorf("expected ClaudeTimeoutError, got %T: %v", err, err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user