// internal/frame/frame_test.go package frame import ( "context" "strings" "testing" "keel/internal/knowledge" "keel/internal/tasks" ) // fakeTasks is a tasks.Provider returning a fixed list. type fakeTasks struct{ list []tasks.Task } // emptyKnowledge is a knowledge.Source that returns no text for any path, so // Assemble emits neither a Goals nor a Life-domains section regardless of what // files exist on the host. type emptyKnowledge struct{} func (emptyKnowledge) Load(context.Context, string) (knowledge.Profile, error) { return knowledge.Profile{}, nil } func (f fakeTasks) Today(context.Context) ([]tasks.Task, error) { return f.list, nil } func (f fakeTasks) Create(context.Context, tasks.Task) error { return nil } func TestAssembleListsTodaysTasks(t *testing.T) { tp := fakeTasks{list: []tasks.Task{{Title: "write the keel spec"}}} got := Assemble(context.Background(), nil, tp) if !strings.Contains(got, "## Today's tasks") { t.Fatalf("missing tasks header:\n%s", got) } if !strings.Contains(got, "write the keel spec") { t.Fatalf("missing task title:\n%s", got) } } // With no knowledge source and no tasks, Assemble degrades to a short brief and // never panics — both ports may be nil. func TestAssembleToleratesNilPorts(t *testing.T) { got := Assemble(context.Background(), nil, nil) if !strings.Contains(got, "## Today's tasks") { t.Fatalf("expected a tasks header even with no ports:\n%s", got) } if !strings.Contains(got, "(none)") { t.Fatalf("expected (none) for absent tasks:\n%s", got) } } func TestAssembleWithEmptyKnowledge(t *testing.T) { got := Assemble(context.Background(), emptyKnowledge{}, fakeTasks{}) if strings.Contains(got, "## Goals") { t.Fatalf("empty knowledge should not emit a Goals section:\n%s", got) } if strings.Contains(got, "## Life domains") { t.Fatalf("empty knowledge should not emit a Life domains section:\n%s", got) } } func TestTruncateClipsWithMarker(t *testing.T) { in := strings.Repeat("x", MaxBriefBytes+100) got := Truncate(in, MaxBriefBytes) if len(got) > MaxBriefBytes+len("\n…(truncated)") { t.Fatalf("truncate did not clip: len=%d", len(got)) } if !strings.HasSuffix(got, "(truncated)") { t.Fatalf("missing truncation marker: %q", got[len(got)-20:]) } }