ความคืบหน้างาน ไฟล์ต้นฉบับ

tracker/task_brief_test.go

package main

import (
	"encoding/json"
	"html"
	"net/http/httptest"
	"os"
	"strings"
	"testing"
)

func TestTaskBriefDisplaysQuestionsAndDeliverables(t *testing.T) {
	data, err := os.ReadFile("data/milestones.json")
	if err != nil {
		t.Fatal(err)
	}
	var milestones []Milestone
	if err = json.Unmarshal(data, &milestones); err != nil {
		t.Fatal(err)
	}
	var target *Task
	for _, m := range milestones {
		for _, e := range m.Epics {
			for i := range e.Tasks {
				if e.Tasks[i].ID == "T-303" {
					copy := e.Tasks[i]
					target = &copy
				}
			}
		}
	}
	if target == nil || target.Description == "" || len(target.Deliverables) == 0 || len(target.Questions) == 0 {
		t.Fatal("T-303 needs an actionable brief, deliverables and questions")
	}
	for _, q := range target.Questions {
		if q.ID == "" || q.AskedOf == "" || q.Question == "" || q.Why == "" {
			t.Fatal("questions must identify recipient and impact")
		}
	}
	mux := newMux(NewStore("data"), NewHub())
	w := httptest.NewRecorder()
	mux.ServeHTTP(w, httptest.NewRequest("GET", "/tasks/T-303", nil))
	for _, text := range []string{"รายละเอียดงาน", "ผลลัพธ์ที่ต้องส่งมอบ", "คำถามที่ต้องการข้อมูล", target.Questions[0].ID, target.Questions[0].AskedOf} {
		if !strings.Contains(html.UnescapeString(w.Body.String()), text) {
			t.Fatal("missing brief section", text)
		}
	}
}

func TestPreparationBriefsHaveTraceableQuestions(t *testing.T) {
	data, err := os.ReadFile("data/milestones.json")
	if err != nil {
		t.Fatal(err)
	}
	var milestones []Milestone
	if err = json.Unmarshal(data, &milestones); err != nil {
		t.Fatal(err)
	}
	known := map[string]bool{}
	for _, m := range milestones {
		for _, e := range m.Epics {
			for _, task := range e.Tasks {
				known[task.ID] = true
			}
		}
	}
	seen := map[string]bool{}

	for _, m := range milestones {
		for _, e := range m.Epics {
			for _, task := range e.Tasks {
				if task.Status == StatusTodo {

					if task.Summary == "" || task.Description == "" || len(task.Steps) == 0 || len(task.Deliverables) == 0 || len(task.Questions) == 0 {
						t.Fatalf("unactionable pending task %s", task.ID)
					}
				}
				for _, id := range task.Dependencies {
					if !known[id] || id == task.ID {
						t.Fatalf("invalid dependency %s -> %s", task.ID, id)
					}
				}
				for _, q := range task.Questions {
					if q.ID == "" || seen[q.ID] || q.AskedOf == "" || q.Why == "" || q.Question == "" {
						t.Fatalf("untraceable question in %s", task.ID)
					}
					seen[q.ID] = true
					if q.State == "answered" && q.Answer == "" {
						t.Fatalf("false answer in %s", q.ID)
					}
				}
			}
		}
	}
	if len(seen) == 0 {
		t.Fatal("no task questions loaded")
	}
}