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}