diff options
Diffstat (limited to 'internal/store/chains_test.go')
| -rw-r--r-- | internal/store/chains_test.go | 68 |
1 files changed, 67 insertions, 1 deletions
diff --git a/internal/store/chains_test.go b/internal/store/chains_test.go index 1d16508..6359d11 100644 --- a/internal/store/chains_test.go +++ b/internal/store/chains_test.go @@ -132,10 +132,19 @@ func TestCompleteNativeTask_PausedChain_DoesNotAdvance(t *testing.T) { t.Error("position 1 should still be locked while chain is paused") } - // Resuming re-enables advancement on the *next* completion. + // Resuming performs the deferred unlock itself -- position 1 becomes + // completable immediately, not only after some future completion. if err := s.SetChainStatus(chain.ID, "active"); err != nil { t.Fatal(err) } + resumed, err := s.GetChainTasks(chain.ID) + if err != nil { + t.Fatal(err) + } + if !resumed[1].ChainUnlocked { + t.Fatal("expected resume to unlock position 1 immediately (deferred advancement catch-up)") + } + if err := s.CompleteNativeTask(tasks[1].ID); err != nil { t.Fatalf("CompleteNativeTask after resume: %v", err) } @@ -148,6 +157,63 @@ func TestCompleteNativeTask_PausedChain_DoesNotAdvance(t *testing.T) { } } +func TestCompleteNativeTask_LockedChainTask_ReturnsErrChainTaskLocked(t *testing.T) { + s := newNativeTasksTestStore(t) + + chain, err := s.CreateChain("Track", chainTasks("Step 1", "Step 2")) + if err != nil { + t.Fatal(err) + } + tasks, err := s.GetChainTasks(chain.ID) + if err != nil { + t.Fatal(err) + } + + if err := s.CompleteNativeTask(tasks[1].ID); err != ErrChainTaskLocked { + t.Errorf("err = %v, want ErrChainTaskLocked", err) + } + + // Confirm nothing was mutated -- still locked, still not completed. + after, err := s.GetChainTasks(chain.ID) + if err != nil { + t.Fatal(err) + } + if after[1].Completed || after[1].ChainUnlocked { + t.Errorf("locked task should be untouched by the rejected completion attempt: %+v", after[1]) + } +} + +func TestSetChainStatus_ResumeWithNothingStuck_DoesNotResetDueDate(t *testing.T) { + s := newNativeTasksTestStore(t) + + chain, err := s.CreateChain("Track", chainTasks("Step 1", "Step 2")) + if err != nil { + t.Fatal(err) + } + tasks, err := s.GetChainTasks(chain.ID) + if err != nil { + t.Fatal(err) + } + originalDueDate := *tasks[0].DueDate + + // Pause and resume with nothing completed yet -- position 0 is already + // unlocked and should be left untouched by the resume catch-up. + if err := s.SetChainStatus(chain.ID, "paused"); err != nil { + t.Fatal(err) + } + if err := s.SetChainStatus(chain.ID, "active"); err != nil { + t.Fatal(err) + } + + after, err := s.GetChainTasks(chain.ID) + if err != nil { + t.Fatal(err) + } + if !after[0].DueDate.Equal(originalDueDate) { + t.Errorf("DueDate = %v, want unchanged %v (resume catch-up should be a no-op when nothing was stuck)", after[0].DueDate, originalDueDate) + } +} + func TestGetUndatedNativeTasks_ExcludesLockedChainTasks(t *testing.T) { s := newNativeTasksTestStore(t) |
