Skip to content

[REQ-001] Add currentStreak and bestStreak pure functions with unit tests#3

Merged
markoub merged 1 commit into
mainfrom
feat/issue-1-streak-functions
Jun 2, 2026
Merged

[REQ-001] Add currentStreak and bestStreak pure functions with unit tests#3
markoub merged 1 commit into
mainfrom
feat/issue-1-streak-functions

Conversation

@markoub

@markoub markoub commented Jun 2, 2026

Copy link
Copy Markdown
Owner

Summary

  • Adds currentStreak(habit, today) to src/habits.ts: counts consecutive completed days ending on or just before today; returns 0 if neither today nor yesterday is completed.
  • Adds bestStreak(habit) to src/habits.ts: returns the length of the longest ever consecutive run of completions; returns 0 for an empty habit.
  • Both functions are pure (no DOM, no localStorage, no Date reads — today is always passed as a parameter).
  • Adds a private shiftDay helper for date arithmetic using UTC to avoid DST issues.

How I tested

Ran npm ci && npm test && npm run build — all 17 tests pass, build succeeds with no TypeScript errors.

New test cases added to src/habits.test.ts:

  • Empty habit → 0 (both functions)
  • Single completion today → 1
  • Single completion yesterday, today not done → currentStreak = 1, bestStreak = 1
  • Streak broken by a gap → only the contiguous tail counts for currentStreak; best segment for bestStreak
  • Active streak of 6 days ending today
  • Past best-run longer than current run

Closes #1


Generated by Claude Code

Implements REQ-001 streak logic in src/habits.ts (pure, no DOM/storage).
Adds 12 unit tests covering empty habits, single days, gaps, active runs,
and best-past-run scenarios.

Closes #1
@markoub markoub added agent Created/handled by the autonomous pipeline needs-review PR awaiting the Reviewer agent labels Jun 2, 2026 — with Claude

@markoub markoub left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review — PR #3: Add currentStreak and bestStreak

This is a clean, well-structured implementation. All acceptance criteria from issue #1 are met, CI is green, and the code is genuinely pleasant to read. Here's the full walkthrough.


Correctness ✅

currentStreak (src/habits.ts:49–67) — logic is correct in all required cases:

  • Starts from today; if not in the set, falls back one day; if still not found, returns 0 immediately. No infinite loop risk.
  • The backwards while walk correctly counts the contiguous tail. Traced manually through all 6 test scenarios — all produce the right result.

bestStreak (src/habits.ts:74–88) — also correct:

  • The early-return guard for empty completions is clean.
  • The [...habit.completions].sort() defensive copy is good hygiene even though toggleCompletion already sorts; costs nothing.
  • The in-place best / run scan is O(n) and readable. Confirmed it handles the single-element case (loop body never executes, returns best = 1) and the "past best longer than current run" case correctly.

shiftDay (src/habits.ts:48–53) — the UTC anchoring ("T00:00:00Z" + setUTCDate) is exactly right to avoid DST surprises. Good call.


Purity ✅

src/habits.ts remains completely free of DOM, localStorage, window, and clock reads. today is always injected as a YYYY-MM-DD string parameter. shiftDay uses Date only for arithmetic, never to read wall-clock time. The purity invariant holds.


Test coverage ✅

All six cases required by the acceptance criteria are present for both functions:

Case currentStreak bestStreak
Empty habit → 0
Single day today → 1
Single day yesterday, today not done
Streak broken in the middle
Active streak of several days ending today ✅ (3-day + 6-day) ✅ (6-day)
Best streak is a past run n/a
Gap two days ago → 0 for current n/a

12 tests total, all meaningful and non-redundant.


Style & scope ✅

  • Single focused commit feat: add currentStreak and bestStreak pure functions — conventional commit format, good body, Closes #1 wired up correctly.
  • Diff touches only src/habits.ts and src/habits.test.ts. No stray changes.
  • Immutable patterns consistent with the rest of the codebase.

Non-blocking nit

The JSDoc blocks on currentStreak and bestStreak are multi-line (3 lines and 2 lines respectively), which is a minor departure from CLAUDE.md's "one short line max" comment guideline. The content is genuinely useful for exported API functions, so this is not a blocker — just worth keeping in mind for future contributions.


Verdict: ready to merge. CI passed, all acceptance criteria satisfied, purity maintained, edge cases covered. Tagging ready-to-merge and squash-merging now.


Generated by Claude Code

@markoub markoub added ready-to-merge Approved by the Reviewer agent and removed needs-review PR awaiting the Reviewer agent labels Jun 2, 2026 — with Claude
@markoub markoub merged commit bbef990 into main Jun 2, 2026
1 check passed
@markoub markoub deleted the feat/issue-1-streak-functions branch June 2, 2026 06:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent Created/handled by the autonomous pipeline ready-to-merge Approved by the Reviewer agent

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[REQ-001] Add currentStreak and bestStreak pure functions with unit tests

2 participants