diff --git a/internal/progress/tracker_test.go b/internal/progress/tracker_test.go index b3c231b..9a0d0e1 100644 --- a/internal/progress/tracker_test.go +++ b/internal/progress/tracker_test.go @@ -260,12 +260,56 @@ func TestTracker_EveryTransitionIsLoggedByTheSameCall(t *testing.T) { tr.Begin("audio", 0) clk.tick(3 * time.Second) tr.Done("audio") + tr.Begin("decide", 5) + clk.tick(2 * time.Second) + tr.FailRunning() + tr.Finish() out := buf.String() - require.Contains(t, out, "step=audio") - require.Contains(t, out, "started") - require.Contains(t, out, "finished") - require.Contains(t, out, "elapsed=3s") + for _, want := range []string{ + `msg="job started"`, + `msg="step started" step=audio`, + `msg="step finished" step=audio elapsed=3s`, + `msg="step started" step=decide total=5`, + `msg="step failed" step=decide elapsed=2s`, + `msg="job finished"`, + } { + require.Contains(t, out, want, "a transition with no log line is invisible to the operator") + } +} + +func TestTracker_AKeyedFailIsSavedAtOnceNotOnTheNextTransition(t *testing.T) { + tr, sink, _, _ := newTracker(t) + tr.Start() + tr.Begin("audio", 0) + before := sink.saveCount() + + tr.Fail("audio", errors.New("down")) + + require.Equal(t, before+1, sink.saveCount(), "a soft-failed phase must show as failed on the page now") + require.Equal(t, domain.StepFailed, stateOf(sink.last(t), "audio")) +} + +// retainingSink keeps the very slice it is handed, like a sink that queues it for later. +type retainingSink struct{ got [][]domain.ProgressStep } + +func (r *retainingSink) SaveProgress(_ context.Context, steps []domain.ProgressStep, _ time.Time) error { + r.got = append(r.got, steps) + return nil +} +func (r *retainingSink) Beat(context.Context) error { return nil } + +func TestTracker_ASnapshotHandedToTheSinkIsNotChangedByLaterTransitions(t *testing.T) { + sink := &retainingSink{} + tr := progress.NewTracker(context.Background(), sink, slog.New(slog.NewTextHandler(&syncBuf{}, nil)), plan(), + progress.WithClock(newClock().now)) + tr.Start() + first := sink.got[0] + + tr.Begin("audio", 0) + tr.Done("audio") + + require.Equal(t, domain.StepPending, first[0].State, "a sink that keeps a snapshot must not see it change under it") } func TestTracker_AdvanceIsLoggedAtMostOncePerMinute(t *testing.T) {