1// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
  2//
  3// SPDX-License-Identifier: AGPL-3.0-or-later
  4
  5package cli_test
  6
  7import (
  8	"strings"
  9	"testing"
 10	"time"
 11
 12	"git.secluded.site/np/internal/cli"
 13	"git.secluded.site/np/internal/goal"
 14	"git.secluded.site/np/internal/task"
 15)
 16
 17func TestRenderPlanWithGoalAndTasks(t *testing.T) {
 18	title := "Build reliable planning workflow"
 19	description := "Capture context from ticket and operator input.\nPrioritise determinism."
 20	goalDoc := goal.Document{
 21		Title:       title,
 22		Description: description,
 23		UpdatedAt:   time.Now(),
 24	}
 25
 26	tasks := []task.Task{
 27		{
 28			ID:          "alpha1",
 29			Title:       "Add initial goal",
 30			Description: "Use `np g s` to capture summary.",
 31			Status:      task.StatusCompleted,
 32			CreatedAt:   time.Now(),
 33			UpdatedAt:   time.Now(),
 34			CreatedSeq:  1,
 35		},
 36		{
 37			ID:          "beta2",
 38			Title:       "Implement task list",
 39			Description: "Track progress for each major change.\nRemember to cite files.",
 40			Status:      task.StatusInProgress,
 41			CreatedAt:   time.Now(),
 42			UpdatedAt:   time.Now(),
 43			CreatedSeq:  2,
 44		},
 45		{
 46			ID:          "gamma3",
 47			Title:       "Polish output",
 48			Description: "Ensure legend only includes relevant statuses.",
 49			Status:      task.StatusPending,
 50			CreatedAt:   time.Now(),
 51			UpdatedAt:   time.Now(),
 52			CreatedSeq:  3,
 53		},
 54		{
 55			ID:          "delta4",
 56			Title:       "Document edge cases",
 57			Description: "Explain handling for cancelled operations.",
 58			Status:      task.StatusCancelled,
 59			CreatedAt:   time.Now(),
 60			UpdatedAt:   time.Now(),
 61			CreatedSeq:  4,
 62		},
 63	}
 64
 65	result := cli.RenderPlan(cli.PlanState{
 66		Goal:  &goalDoc,
 67		Tasks: tasks,
 68	})
 69
 70	expectedLegend := "Legend: ☐ pending  ⟳ in progress  ☑ completed  ⊗ cancelled"
 71	if !strings.Contains(result, expectedLegend) {
 72		t.Fatalf("expected legend %q in output:\n%s", expectedLegend, result)
 73	}
 74
 75	if !strings.Contains(result, title) {
 76		t.Fatalf("expected goal title in output")
 77	}
 78
 79	if !strings.Contains(result, "Add initial goal [alpha1]") {
 80		t.Fatalf("expected completed task line")
 81	}
 82
 83	if !strings.Contains(result, "  Track progress for each major change.") {
 84		t.Fatalf("expected indented description line")
 85	}
 86
 87	if strings.Contains(result, "☒ failed") {
 88		t.Fatalf("failed legend entry should not appear without failed tasks")
 89	}
 90}
 91
 92func TestRenderPlanWithoutGoalOrTasks(t *testing.T) {
 93	result := cli.RenderPlan(cli.PlanState{})
 94
 95	if !strings.Contains(result, "No goal set yet") {
 96		t.Fatalf("expected placeholder goal")
 97	}
 98	if !strings.Contains(result, "No tasks yet.") {
 99		t.Fatalf("expected placeholder task message")
100	}
101}