TestCmdDoResumeSpawnFailureKeepsSessionID is the inverse of the fresh-bootstrap case: when a RESUME spawn fails (the session_id already pointed at a real jsonl from a previous successful spawn), the DB row must be left untouched. A transient osascript failure should not cost the user their conversat
(t *testing.T)
| 398 | os.Stderr = w |
| 399 | t.Cleanup(func() { |
| 400 | os.Stderr = origStderr |
| 401 | }) |
| 402 | return func() string { |
| 403 | _ = w.Close() |
| 404 | var buf bytes.Buffer |
| 405 | _, _ = io.Copy(&buf, r) |
| 406 | _ = r.Close() |
| 407 | return buf.String() |
| 408 | } |
| 409 | } |
| 410 | |
| 411 | // TestCmdDoFreshAllocatesSessionID verifies the pre-allocation contract: |
| 412 | // a fresh task gets a UUID written to tasks.session_id and spawns |
| 413 | // `claude --session-id <uuid> "<prompt>"` so the jsonl file claude creates |
| 414 | // lands at the deterministic path keyed on that UUID. |
| 415 | func TestCmdDoFreshAllocatesSessionID(t *testing.T) { |
| 416 | setupFlowRoot(t) |
| 417 | seedTask(t, "fresh-task") |
| 418 | _, getScript := stubITerm(t) |
| 419 | |
| 420 | const pinnedSID = "11111111-2222-3333-4444-555555555555" |
| 421 | stubNewUUID(t, pinnedSID) |
| 422 | |
| 423 | if rc := cmdDo([]string{"fresh-task"}); rc != 0 { |
| 424 | t.Fatalf("rc=%d", rc) |
| 425 | } |
| 426 | |
| 427 | db := openFlowDB(t) |
| 428 | task, err := flowdb.GetTask(db, "fresh-task") |
| 429 | if err != nil { |
| 430 | t.Fatal(err) |
| 431 | } |
| 432 | if !task.SessionID.Valid || task.SessionID.String != pinnedSID { |
| 433 | t.Errorf("session_id after fresh spawn: got %+v, want %s", task.SessionID, pinnedSID) |
| 434 | } |
| 435 | if !task.SessionStarted.Valid { |
| 436 | t.Error("session_started should be set after fresh spawn") |
| 437 | } |
| 438 | if task.Status != "in-progress" { |
| 439 | t.Errorf("status: got %q, want in-progress", task.Status) |
| 440 | } |
nothing calls this directly
no test coverage detected