142 lines
4.1 KiB
Go
142 lines
4.1 KiB
Go
package wizard
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"testing"
|
|
|
|
"gitlab.hive-brain.de/MDietermann/Archduino/internal/module"
|
|
"gitlab.hive-brain.de/MDietermann/Archduino/internal/modules/hello"
|
|
"gitlab.hive-brain.de/MDietermann/Archduino/internal/tui"
|
|
)
|
|
|
|
func TestSyncSelected(t *testing.T) {
|
|
orig := []tui.ModuleChoice{
|
|
{ID: "a", Selected: false},
|
|
{ID: "b", Selected: true},
|
|
{ID: "c", Selected: true},
|
|
}
|
|
got := syncSelected(orig, []string{"a", "c"})
|
|
want := map[string]bool{"a": true, "b": false, "c": true}
|
|
for _, m := range got {
|
|
if m.Selected != want[m.ID] {
|
|
t.Errorf("%s selected=%v, want %v", m.ID, m.Selected, want[m.ID])
|
|
}
|
|
}
|
|
if orig[0].Selected {
|
|
t.Error("orig mutated")
|
|
}
|
|
}
|
|
|
|
func TestRenderPlanWithHello(t *testing.T) {
|
|
reg := module.NewRegistry()
|
|
_ = reg.Register(hello.Module{Path: t.TempDir() + "/marker"})
|
|
out := renderPlanCached(context.Background(), reg, []string{"hello"}, newPlanCache())
|
|
if !strings.Contains(out, "hello") {
|
|
t.Fatalf("output missing hello: %q", out)
|
|
}
|
|
}
|
|
|
|
func TestRenderPlanEmpty(t *testing.T) {
|
|
if got := renderPlanCached(context.Background(), module.NewRegistry(), nil, newPlanCache()); got != "No modules selected." {
|
|
t.Fatalf("got %q", got)
|
|
}
|
|
}
|
|
|
|
func TestParseIntClamp(t *testing.T) {
|
|
cases := map[string]int{
|
|
"": 1,
|
|
" ": 1,
|
|
"abc": 1,
|
|
"3abc": 1, // partial match is rejected (strconv.Atoi, not Sscanf)
|
|
"0": 1,
|
|
"-5": 1,
|
|
"3": 3,
|
|
"12": 12,
|
|
"99999999999999999999": 1, // overflow → fallback
|
|
}
|
|
for in, want := range cases {
|
|
got := parseIntClamp(in, 1)
|
|
if got != want {
|
|
t.Errorf("parseIntClamp(%q) = %d, want %d", in, got, want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestRenderPlanCachesDetectAndPlan(t *testing.T) {
|
|
var detects, plans int
|
|
m := countingModule{
|
|
meta: module.Meta{ID: "count", Name: "Count"},
|
|
onDetect: func() { detects++ },
|
|
onPlan: func() { plans++ },
|
|
}
|
|
reg := module.NewRegistry()
|
|
if err := reg.Register(m); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
cache := newPlanCache()
|
|
_ = renderPlanCached(context.Background(), reg, []string{"count"}, cache)
|
|
_ = renderPlanCached(context.Background(), reg, []string{"count"}, cache)
|
|
_ = renderPlanCached(context.Background(), reg, []string{"count"}, cache)
|
|
if detects != 1 || plans != 1 {
|
|
t.Fatalf("want 1 detect and 1 plan, got detects=%d plans=%d", detects, plans)
|
|
}
|
|
}
|
|
|
|
func TestRenderPlanInvalidatesOnSelectionChange(t *testing.T) {
|
|
var detects int
|
|
m := countingModule{
|
|
meta: module.Meta{ID: "count", Name: "Count"},
|
|
onDetect: func() { detects++ },
|
|
}
|
|
reg := module.NewRegistry()
|
|
_ = reg.Register(m)
|
|
cache := newPlanCache()
|
|
_ = renderPlanCached(context.Background(), reg, []string{"count"}, cache)
|
|
_ = renderPlanCached(context.Background(), reg, []string{}, cache)
|
|
_ = renderPlanCached(context.Background(), reg, []string{"count"}, cache)
|
|
if detects != 2 {
|
|
t.Fatalf("deselect+reselect should re-detect; detects=%d (want 2)", detects)
|
|
}
|
|
}
|
|
|
|
type countingModule struct {
|
|
meta module.Meta
|
|
onDetect func()
|
|
onPlan func()
|
|
}
|
|
|
|
func (c countingModule) Meta() module.Meta { return c.meta }
|
|
func (c countingModule) Detect(context.Context) (module.State, error) {
|
|
if c.onDetect != nil {
|
|
c.onDetect()
|
|
}
|
|
return nil, nil
|
|
}
|
|
func (c countingModule) Plan(context.Context, module.State) (module.Plan, error) {
|
|
if c.onPlan != nil {
|
|
c.onPlan()
|
|
}
|
|
return module.Plan{}, nil
|
|
}
|
|
func (c countingModule) PlanForce(context.Context) (module.Plan, error) {
|
|
if c.onPlan != nil {
|
|
c.onPlan()
|
|
}
|
|
return module.Plan{}, nil
|
|
}
|
|
func (c countingModule) Apply(context.Context, module.Plan, module.Reporter) error { return nil }
|
|
func (c countingModule) Verify(context.Context) error { return nil }
|
|
|
|
func TestRunCancelledContextReturnsNoConfirmation(t *testing.T) {
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
cancel()
|
|
_, confirmed, err := Run(ctx, module.NewRegistry(), tui.WizardState{})
|
|
if err != nil && err != context.Canceled {
|
|
t.Fatalf("unexpected err: %v", err)
|
|
}
|
|
if confirmed {
|
|
t.Fatal("confirmed=true on cancelled context")
|
|
}
|
|
}
|