tracker/workflow_test.go
package main
import (
"fmt"
"testing"
)
func TestCanonicalWorkflowBranches(t *testing.T) {
c, err := loadUseCases("..")
if err != nil {
t.Fatal(err)
}
for id, u := range c.UC {
t.Run(id, func(t *testing.T) {
d := draftDiagram(u)
if err := validateDiagram(d); err != nil {
t.Fatal(err)
}
seen := map[string]bool{"start": true}
for changed := true; changed; {
changed = false
for _, e := range d.Edges {
if seen[e.Source] && !seen[e.Target] {
seen[e.Target] = true
changed = true
}
}
}
for _, n := range d.Nodes {
if !seen[n.ID] {
t.Errorf("unreachable %s", n.ID)
}
if n.Type != "end" {
found := false
for _, e := range d.Edges {
found = found || e.Source == n.ID
}
if !found {
t.Errorf("dead end %s", n.ID)
}
}
}
canFinish := map[string]bool{}
for _, n := range d.Nodes {
if n.Type == "end" {
canFinish[n.ID] = true
}
}
for changed := true; changed; {
changed = false
for _, e := range d.Edges {
if canFinish[e.Target] && !canFinish[e.Source] {
canFinish[e.Source] = true
changed = true
}
}
}
for _, n := range d.Nodes {
if !canFinish[n.ID] {
t.Errorf("no terminal outcome from %s", n.ID)
}
}
for i := range u.Flow {
if !seen[fmt.Sprintf("step-%d", i+1)] {
t.Fatal("source step lost")
}
}
})
}
check := func(id, from, to, label string) {
t.Helper()
for _, e := range draftDiagram(c.UC[id]).Edges {
if e.Source == from && e.Target == to && e.Label == label {
return
}
}
t.Fatalf("missing %s: %s -> %s (%s)", id, from, to, label)
}
check("W-41", "decision-3", "step-4", "ไม่จำเป็น — สมัครด้วยตนเอง")
check("W-77", "step-3", "step-2", "")
check("W-14", "decision-1", "step-5", "ฉุกเฉินเข้าเกณฑ์")
check("W-14", "step-4", "step-6", "")
for _, e := range draftDiagram(c.UC["W-147"]).Edges {
if e.Source == "decision-3" && e.Label == "ต่อสัญญา" && e.Target == "step-3" {
t.Fatal("renewal entered checkout")
}
}
u := c.UC["W-41"]
old := sourceDigest(u)
u.Workflow.Decisions[0].Title += " changed"
if old == sourceDigest(u) {
t.Fatal("workflow missing from approval fingerprint")
}
}
func TestWorkflowChangeStalesApprovalWithoutReplacingSavedDiagram(t *testing.T) {
c, err := loadUseCases("..")
if err != nil {
t.Fatal(err)
}
u := c.UC["W-41"]
ds := &diagramStore{dir: t.TempDir()}
status, err := ds.approve(u, 0, sourceDigest(u), "Test reviewer", "Temporary fixture only", true)
if err != nil || !status.Approved {
t.Fatal(err, status)
}
before, err := ds.load(u.ID, u)
if err != nil {
t.Fatal(err)
}
u.Workflow.Decisions[0].Branches[0].Label += " revised"
if ds.approvalStatus(u).Approved {
t.Fatal("changed condition kept approval")
}
after, err := ds.load(u.ID, u)
if err != nil || digestJSON(before) != digestJSON(after) {
t.Fatal("saved user graph overwritten", err)
}
}