diff --git a/cmd/mecatui/customization/lifecycle_test.go b/cmd/mecatui/customization/lifecycle_test.go index dd985815b1..8d447cd595 100644 --- a/cmd/mecatui/customization/lifecycle_test.go +++ b/cmd/mecatui/customization/lifecycle_test.go @@ -25,18 +25,21 @@ func TestStatusLine_Scenario4_DebounceTemplateRefreshAndClock(t *testing.T) { t.Fatalf("command footer = %q, want latest refresh", got) } - templates := NewTemplateSource(TemplateSet{Footer: SurfaceTemplates{Full: ``}}, time.Second) + // Interval ticks carry the clock value; drive them by hand so the refresh + // never lands in the same wall-clock second as the first render. + ticks := make(chan time.Time) + templates := newTemplateSourceWithTicks(TemplateSet{Footer: SurfaceTemplates{Full: ``}}, ticks) t.Cleanup(func() { _ = templates.Close(context.Background()) }) + templates.now = func() time.Time { return time.Date(2026, time.August, 28, 12, 0, 0, 0, time.UTC) } templates.Submit(Input{Terminal: Terminal{FooterAvailCols: 80}}) waitStatusChange(t, templates) - first := statusSurfaceText(templates.Latest().Footer) - select { - case <-templates.Changed(): - case <-time.After(1500 * time.Millisecond): - t.Fatal("template clock did not refresh on its interval") + if got := statusSurfaceText(templates.Latest().Footer); got != "12:00:00" { + t.Fatalf("template footer = %q, want submit-time clock", got) } - if got := statusSurfaceText(templates.Latest().Footer); got == first { - t.Fatalf("template clock did not advance: %q", got) + ticks <- time.Date(2026, time.August, 28, 12, 0, 1, 0, time.UTC) + waitStatusChange(t, templates) + if got := statusSurfaceText(templates.Latest().Footer); got != "12:00:01" { + t.Fatalf("template footer = %q, want interval-tick clock", got) } } diff --git a/cmd/mecatui/customization/template.go b/cmd/mecatui/customization/template.go index f195155d8b..6d3b423b71 100644 --- a/cmd/mecatui/customization/template.go +++ b/cmd/mecatui/customization/template.go @@ -33,16 +33,20 @@ func newTemplateSource(templates TemplateSet, interval time.Duration) *statusLin ticker = time.NewTicker(interval) ticks = ticker.C } + s := newTemplateSourceWithTicks(templates, ticks) + if ticker != nil { + s.stopTicker = ticker.Stop + } + return s +} + +func newTemplateSourceWithTicks(templates TemplateSet, ticks <-chan time.Time) *statusLineSource { defaults := defaultTemplateSet() header := compileVariants(templates.Header, defaults.Header) footer := compileVariants(templates.Footer, defaults.Footer) - s := newSource(ticks, func(ctx context.Context, input Input) Result { + return newSource(ticks, func(ctx context.Context, input Input) Result { return renderTemplates(ctx, header, footer, input) }) - if ticker != nil { - s.stopTicker = ticker.Stop - } - return s } type templateVariants struct{ full, compact, minimal statusTemplate }