aboutsummaryrefslogtreecommitdiff
path: root/tests
Commit message (Collapse)AuthorAgeFilesLines
...
* fix: restore display state in the buffer setup ran inCraig Jennings2026-05-051-0/+53
| | | | | | | | | | | | | | | | | | org-drill--setup-display saved buffer-local state (mode-line, variable-pitch-mode) into global defvars and called setq-local on the current buffer. org-drill--restore-display read those globals and ran setq-local against whatever buffer happened to be current at restore time. If the user switched buffers mid-session, the restore wrote to the wrong buffer — leaving the original drill buffer's mode-line still hidden and trampling the destination buffer's mode-line with whatever was saved from elsewhere. Captured the buffer at setup in org-drill--saved-display-buffer. Restore now wraps mode-line and variable-pitch restoration in with-current-buffer against that saved buffer. Text-scale stays global (the underlying face attribute is process-wide).
* fix: recover from corrupted persist file at package load (upstream #45)Craig Jennings2026-05-051-0/+51
| | | | | | | | | | | | | Issue #45 (2021): persist-load raised End of file during parsing at persist.el:413 in some configurations, likely from a corrupted persist data file. Pre-fix, this propagated up through the top-level (persist-defvar org-drill-sm5-optimal-factor-matrix ...) form at file-load time and broke the entire package's load. Wrapped the persist-defvar form in condition-case. On failure, the matrix falls back to a fresh nil binding via plain defvar, and a message tells the user what happened. org-drill continues to load normally.
* fix: guard org-drill-again and org-drill-resume against nil last-sessionCraig Jennings2026-05-051-0/+39
| | | | | | | | | | | | Both functions bound session to org-drill-last-session and immediately called setf / org-drill-entries-pending-p on it without checking for nil. First-time invocation (or after Emacs restart with no active session) threw an obscure eieio-oset / nil-slot type error instead of a clear message. Added (unless session (user-error ...)) at the top of each function. A user running M-x org-drill-resume cold now sees a sensible message telling them to run org-drill first.
* fix: hide-drawers ignores drawers with no :END:Craig Jennings2026-05-051-0/+66
| | | | | | | | | | | | | drawer-end was captured as (save-excursion (re-search-forward ':END:' end t) (point)) which always returns a number — (point) is always defined. The subsequent (when drawer-end ...) guard was dead, so a malformed drawer (typo in :END:, mid-edit truncation) ended up with a junk overlay covering whatever range point happened to land in. Captured the search result itself and gate on it. Malformed drawers are now skipped silently; well-formed drawers still get their normal overlay.
* fix: default DRILL_LEITNER_BOX to 0 in leitner-reboxCraig Jennings2026-05-051-0/+43
| | | | | | | | | | | When the property is absent, org-entry-get returns nil and string-to-number errors with wrong-type-argument. Reachable when a user removes the property mid-session, or when a Leitner-tagged entry is rebox'd before its DRILL_LEITNER_BOX has been set. Wrapped the org-entry-get with (or ... "0"). Box 0 makes the rating semantics still sensible: a downgrade stays at 0, a promotion goes to 1.
* fix: drop dead translate_number entry from card-type alist (upstream #43)Craig Jennings2026-05-051-0/+47
| | | | | | | | | | | | | | | | | | | The card-type alist mapped translate_number to a function that no longer exists in the file. Cards with DRILL_CARD_TYPE: translate_number crashed with void-function during drill instead of being skipped. Reporter (issue #43, 2021) said they had old decks using the documented translate_number type and were getting the crash on restore. The function was apparently removed at some point without clearing the alist entry. Removed the alist entry so entry-f's no-presentation-fn branch fires and returns skip after messaging the user. Legacy decks now degrade gracefully instead of crashing the session. Tests in tests/test-org-drill-translate-number-regression.el lock the behavior in (entry-f returns skip on translate_number, alist no longer carries the entry).
* test: org-drill-entry-f per-card dispatcherCraig Jennings2026-05-051-0/+102
| | | | | | | | | | | 5 ERT tests for the per-entry dispatcher: - unknown DRILL_CARD_TYPE returns 'skip and doesn't call answer-fn - presenter returns nil (quit) → entry-f returns nil - presenter returns 'edit → propagates unchanged - presenter returns 'skip → propagates unchanged - presenter returns t (successful) → default answer presenter runs and the complete-func (reschedule) is invoked with the session
* test: org-drill-entries main loop queue-routing logicCraig Jennings2026-05-051-0/+130
| | | | | | | | | | | | | | 5 ERT tests for the session loop body: - quit return (nil) sets end-pos = :quit and exits the loop - edit return ('edit) sets end-pos to a marker and exits - passing rating (>failure-quality) routes marker to done-entries - failing rating (<= failure-quality) skips done-entries - skip return clears current-item without queueing Tests use a tempfile-backed buffer because pop-next-pending-entry calls org-drill-entry-p on each marker, which requires real org buffer state.
* test: replace-multi, map-entry-function, sm2/simple8 schedulersCraig Jennings2026-05-051-0/+167
| | | | | | | | | | | | | 9 ERT tests filling small gaps in coverage: - replace-entry-text-multi: N replacements → N overlays, each showing the matching string via display prop - map-entry-function: virgin entry → new-entries, future-scheduled entry → dormant-entry-count (not new), non-drill skipped - smart-reschedule with org-drill-spaced-repetition-algorithm bound to sm2 and simple8 (default tests covered sm5) - smart-reschedule with DRILL_CARD_WEIGHT - entries-pending-p: overdue queue alone keeps session pending
* test: prompt-for-string, leitner-capture, and resume coverageCraig Jennings2026-05-051-0/+143
| | | | | | | | | | | 7 ERT tests covering the last batch of testable smaller helpers: - presentation-prompt-for-string: stores typed answer in session->drill-answer, uses default prompt when arg is nil - map-leitner-capture: unboxed entry goes to unboxed list, box-3 entry goes to boxed list, box>5 (graduated) skipped, non-drill entry silently skipped - org-drill-resume: with pending entries, calls org-drill resume-p=t
* test: final-report message format and warning-branch zero-guardCraig Jennings2026-05-051-0/+162
| | | | | | | | | | | | 6 ERT tests covering org-drill-final-report: - Reviewed-count from done-entries appears in the message - Pending-queue line lists per-queue counts (1 new, 2 young, etc.) - 100% pass rate doesn't trigger the WARNING branch - Below forgetting-index pass rate triggers the warning prompt - Per-quality counts produce correct percentages (1/4 = 25%) - Warning-branch with zero dormant+due survives (locks in the zero-divisor guard fix)
* test: explain-text helpers and SM-or-Leitner dispatchCraig Jennings2026-05-051-0/+161
| | | | | | | | | | | | | 9 ERT tests covering: - get-explain-text: no :explain: parent returns existing-text, parent with :explain: tag adds its body, recursion stops at top-level outline depth - explain-answer-presenter: creates after-string overlay with Explanation: prefix, replaces prior overlay on second call - explain-cleaner: removes the overlay, no-op on missing overlay - sm-or-leitner: runs SM (via org-drill-again) when pending entries exceed leitner-completed, falls through to Leitner otherwise
* test: Spanish verb presenter and top-level drill commandsCraig Jennings2026-05-051-0/+151
| | | | | | | | | | | | | | 10 ERT tests: - present-spanish-verb (six-way cl-random branch): 0=present-translate, 2=past-translate, 4=future-perfect (mocked cl-random + presentation prompt) - org-drill-cram: passes cram=t to org-drill, accepts scope arg - org-drill-cram-tree: delegates to cram with scope=tree - org-drill-tree: passes scope=tree to org-drill - org-drill-directory: passes scope=directory - org-drill-again: resumes (resume-p=t) when prior session has pending entries, starts fresh otherwise
* test: language card presenters (verb conjugation, noun declension)Craig Jennings2026-05-051-0/+159
| | | | | | | | | | | | | 7 ERT tests covering the language-card presenters and answer-show helpers: - present-verb-conjugation: runs cleanly with all required VERB_ properties, formats tense+mood string when both set - show-answer-verb-conjugation: calls reschedule-fn - present-noun-declension: runs cleanly, includes definite/indefinite suffix when DECLINE_DEFINITE is set, skips suffix when neither extra property is present - show-answer-noun-declension: calls reschedule-fn
* test: card presenters with mocked presentation-promptCraig Jennings2026-05-051-0/+210
| | | | | | | | | | | | | 9 ERT tests covering the per-card-type presentation functions: - present-simple-card: clozes hidden during prompt, return value passthrough, overlays cleaned up after via with-hidden-cloze-text - present-default-answer: drill-answer slot path (overlay-displays the answer), unhide path (reveals body, calls reschedule-fn) - present-card-using-text: replaces body with question, sets drill-answer slot when ANSWER arg provided - present-two-sided-card and present-multi-sided-card: run cleanly on 2-side and 3-side cards
* test: add multicloze hide-n and hide-nth coverageCraig Jennings2026-05-051-0/+163
| | | | | | | | | | | | | 9 ERT tests with org-drill-presentation-prompt mocked to bypass interactive prompts: - hide-n with positive N: hides exactly N cloze overlays, no-op when buffer has no cloze - hide-n with negative N (show-mode): hides total-N pieces, leaving abs(N) visible - force-show-first + force-hide-first → user-visible error - hide-nth: hides only the Nth piece, no-op when out of range, negative N counts from the end
* test: presentation-prompt return values and dispatcherCraig Jennings2026-05-051-0/+125
| | | | | | | | | | | | 7 ERT tests covering the card-prompt return-value contract: - org-drill-presentation-prompt-in-mini-buffer with input-pending-p and read-key-sequence both mocked: quit → nil, edit → 'edit, skip → 'skip, any-other-key → t - explicit PROMPT arg appears in the formatted full-prompt - org-drill-presentation-prompt dispatcher routes by org-drill-presentation-prompt-with-typing (nil → mini-buffer variant, non-nil → in-buffer variant)
* test: add multicloze weighted-presenter dispatch coverageCraig Jennings2026-05-051-0/+143
| | | | | | | | | | | | | | | | | 8 ERT tests covering hide1-firstmore, show1-lastmore, show1-firstless. Each wraps a cond that selects between common and uncommon multicloze presenters based on org-drill-cloze-text-weight and the entry's total-repeats counter. Underlying presenter functions are mocked to no-op stubs that record which one was selected — the branch logic is what's under test, not the (interactive) cloze-prompt itself. Cases covered per function: - nil weight → fall back to non-weighted variant - invalid weight (non-positive int) → error - non-trigger rep → common path (hide-first / show-last / skip-first) - trigger rep → uncommon path (hide-n with appropriate force flags)
* test: add coverage for org-drill-reschedule rating loopCraig Jennings2026-05-051-0/+143
| | | | | | | | | | | | 10 ERT tests covering the rating function (read-key-sequence mocked): - Quality 0/3/5 each returns the integer rating - Quit key returns nil, edit key returns 'edit - Successful rating pushes quality onto session->qualities - Non-cram rating sets a SCHEDULED stamp via smart-reschedule - Cram mode skips the reschedule (no SCHEDULED set) - Failure with >= leech-failure-threshold tags entry :leech: - Failure under threshold doesn't tag :leech:
* test: add navigation, key-binding, push-end, and leitner-rebox coverageCraig Jennings2026-05-051-0/+191
| | | | | | | | | | | | | | 15 ERT tests covering: - org-drill-goto-entry: marker → buffer + position - org-drill-goto-drill-entry-heading: stays put on the drill heading, walks up from a child sub-heading, errors outside any drill entry - org-drill-command-keybinding-to-string: nil for unbound, string for bound commands - org-drill-push-end: appends to non-empty and empty lists - org-drill-leitner-rebox (interactive — read-key-sequence mocked): rating 0 resets to box 1, rating 1 decrements (with floor at 1), rating 2 stays, ratings 3-5 promote, quit-key returns 'quit
* test: add minibuffer prompt, relearn-item, and progress-message coverageCraig Jennings2026-05-051-0/+145
| | | | | | | | | | | 10 ERT tests covering: - org-drill--make-minibuffer-prompt: status char (N/Y/o/!/F), cram-mode shows C, done-entries count, prompt-text passthrough - org-drill-relearn-item: resets DRILL_LAST_INTERVAL to 0, unschedules the entry (days-ahead = 0 path through smart-reschedule) - org-drill-progress-message: emits on multiples of 50, silent otherwise, includes the COLLECTED count
* test: add coverage for org-drill-smart-rescheduleCraig Jennings2026-05-051-0/+119
| | | | | | | | | | | | | | 6 ERT tests covering all four days-ahead branches: - 0 → unschedule (treat as new again) - negative → schedule today (current-time) - positive → schedule N days ahead - nil → use the algorithm-computed next-interval (locks in the numberp guard fix) Plus property side-effects: writes DRILL_LAST_INTERVAL / EASE / TOTAL_REPEATS via store-item-data, and TOTAL_REPEATS increments on each call.
* test: queue popping, fontification, ID creation, strip-all-dataCraig Jennings2026-05-051-0/+219
| | | | | | | | | | | | | | | | | 12 ERT tests covering: - org-drill-pop-next-pending-entry: empty session → nil, failed prioritized over new/old, again-entries fallback, max-item limit gates primary queues but again-entries bypasses - org-drill-card-tag-caller: dispatches per-tag hook fn from alist, unknown tag is silent no-op (falls through to ignore) - org-drill-id-get-create-with-warning: creates ID and flips warned-about-id-creation flag, doesn't re-warn (uses tempfile- backed buffer because org-id-get requires file-visiting) - org-drill-add-cloze-fontification: sets buffer-local cloze-regexp and cloze-keywords from current delimiters - org-drill-strip-all-data: yes-or-no-p gate (no-confirm = no-op, confirm = wipes scheduling props)
* test: add explain-entry-p, end-of-entry-pos, and language card info coverageCraig Jennings2026-05-051-0/+176
| | | | | | | | | | | | | 14 ERT tests covering: - org-drill-explain-entry-p: with/without :explain: tag, no-inherit flag rejects parent's tag - org-drill-end-of-entry-pos: single-heading and multi-heading subtree bounds - org-drill-get-verb-conjugation-info: full property read, tense-only (mood optional), missing-required errors, tense-color highlight face - org-drill-get-noun-info: full property read, missing-required errors, feminine-gender orchid color from alist, unknown-gender red fallback
* test: add list-utility, hide-comments/drawers, and Leitner promotion coverageCraig Jennings2026-05-051-0/+175
| | | | | | | | | | | | | 17 ERT tests covering: - org-drill-swap: distinct indices, same-index no-op, end-to-start - org-drill-shuffle: preserves element multiset, empty list, singleton - org-drill-pop-random: removes-one, nil-on-empty, empties singleton - org-drill-hide-comments: per-line overlay, no-op on comment-free buffer - org-drill-hide-drawers: PROPERTIES drawer, multiple drawers, no-op on drawer-free entry - org-drill-leitner-promote: box-N → box-(N+1), graduation at box 5 (with and without org-drill-leitner-promote-to-drill-p flag)
* test: add entry-status, days-since-creation, and overdue ordering coverageCraig Jennings2026-05-051-0/+212
| | | | | | | | | | | | | | | | | | | | | | Plus a docs fix to org-drill-order-overdue-entries' header comment. 16 ERT tests covering: - org-drill-entry-status: non-drill nil, empty entry nil, virgin :new, future :future, low-quality :failed, due+short-interval :young, due+long-interval :old, very-overdue :overdue, skipped-leech :unscheduled, three-element return shape - org-drill-entry-days-since-creation: with DATE_ADDED, missing without flag (nil), missing with use-last-interval-p flag (overdue+interval) - org-drill-order-overdue-entries: empty stays empty, non-lapsed sorted by DUE desc, lapsed split (by DUE crossing threshold, not AGE) appearing after sorted by AGE desc Fixed misleading header comment at line 2888 — it claimed the lapse split was by AGE, but the code uses DUE (cl-second). This matches the semantic gate in org-drill--entry-lapsed-p, so the code was right and the comment was stale. Updated the comment to state the actual three-step sort.
* test: add session-state predicate coverageCraig Jennings2026-05-051-0/+265
| | | | | | | | | | | | | | | 23 ERT tests covering the queue control flow: - org-drill-entries-pending-p: empty session, current-item slot, again-entries bypassing limits, item-count limit interaction - org-drill-pending-entry-count: empty, sums all queues, current-item marker check - org-drill-maximum-duration-reached-p: nil-duration disables, cram bypasses, fresh session under limit, old session over limit - org-drill-maximum-item-count-reached-p: nil disables, cram bypasses, under/at limit, includes-failed-items-p flag - org-drill--entry-lapsed-p: feature flag gate, threshold respected - org-drill-free-markers: explicit list, t-frees-everything
* test: add overlay coverage for cloze hide/show and entry text replacementCraig Jennings2026-05-051-0/+222
| | | | | | | | | | | | | | | | | 19 ERT tests covering the buffer-overlay machinery behind card presentation: - org-drill-hide-region / unhide-text: bounds, optional display text, no-op on clean buffers, leaves unrelated overlays alone - org-drill-hide-clozed-text / unhide-clozed-text: hides every cloze span with org-drill-cloze-overlay-defaults category, clean round-trip - org-drill-hide-cloze-hints: hides only the ||hint portion when present, no-op when absent (locks in the production fix) - org-drill-replace-entry-text / unreplace-entry-text: covers entry body with placeholder string overlay - org-drill-get-entry-text: returns body text, strips text-properties by default
* test: add tests for due/overdue predicates and scope translationCraig Jennings2026-05-051-0/+257
| | | | | | | | | | | | | | | 27 ERT tests covering the predicates that decide whether a card appears in today's drill session: - org-drill-days-since-last-review / hours-since-last-review with current-time mocked for determinism - org-drill-entry-days-overdue: normal mode (scheduled future/past/now, leech skip), cram mode (recent vs stale review windows) - org-drill-entry-due-p: scheduled in past/future, non-drill, virgin - org-drill-entry-overdue-p: factor-based threshold across last-interval and days-overdue - org-drill-current-scope: file → nil, file-no-restriction → file, symbol passthrough
* test: add tests for cloze regex, hypothetical scheduling, and entry strippingCraig Jennings2026-05-051-0/+185
| | | | | | | | | | | | | | 15 ERT tests covering: - org-drill--compute-cloze-regexp: match default and custom delimiters, hint separator, three-capture-group structure for fontification - org-drill--compute-cloze-keywords: font-lock spec shape - org-drill-hypothetical-next-review-date: virgin-card scheduling, quality-monotonic next-interval, DRILL_CARD_WEIGHT damping - org-drill-hypothetical-next-review-dates: 6-element non-decreasing list driving the rating-prompt preview - org-drill-strip-entry-data: scheduling-property cleanup, no-op on virgin entry
* test: add round-trip tests for item-data save/loadCraig Jennings2026-05-051-0/+177
| | | | | | | | | | | | | | | 11 ERT tests covering org-drill-get-item-data and store-item-data. The user-facing contract: rate a card → state persists across sessions. Three branches tested: virgin item (zero-list sentinel), modern DRILL_* properties (read all six fields, partial-set falls back to defaults), and legacy LEARN_DATA backward compat (precedence over modern, graceful fallthrough on malformed data). Round-trip tests document a deliberate type quirk: rounded fields (interval, meanq, ease) come back as floats because org-drill-round-float returns float; counters (repeats, failures, total-repeats) stay int. Numerically lossless and scheduler-safe.
* test: add unit tests for entry-property accessorsCraig Jennings2026-05-051-0/+214
| | | | | | | | | | | 30 ERT tests covering org-drill-entry-last-quality, entry-failure-count, entry-average-quality, entry-last-interval, entry-repeats-since-fail, entry-total-repeats, entry-ease, entry-leech-p, and entry-new-p. Documents each function's missing-property fallback behavior — three distinct shapes: nil-by-default (last-quality, average-quality, ease), hardcoded-zero-by-default (failure-count, last-interval, repeats-since- fail, total-repeats), or computed from other state (new-p, leech-p).
* test: add direct unit tests for SM2/SM5 scheduler helpersCraig Jennings2026-05-051-0/+222
| | | | | | | | | | | | 35 ERT tests covering org-drill-round-float, org-drill-modify-e-factor, org-drill-modify-of, org-drill-set-optimal-factor, org-drill-initial-optimal-factor-sm5, org-drill-get-optimal-factor-sm5, org-drill-inter-repetition-interval-sm5, org-drill-early-interval-factor, org-drill-random-dispersal-factor, and org-drill--safe-read-learn-data. These helpers were exercised transitively by the existing top-level scheduler tests but had no direct unit coverage. Direct tests give faster feedback when a helper breaks and pin each helper's contract.
* fix: include child subtree in entry-empty-p search bound (upstream #13)Craig Jennings2026-05-051-0/+135
| | | | | | | | | | | | kqr (2019-07-22) reported that drill entries whose answer lives inside a child sub-heading were silently skipped. Their example: a question in the heading text and the answer under `** The Answer`. The function returned t (empty) for such entries, so they never got presented during drill sessions. The cause is `(outline-next-heading)` in `org-drill-entry-empty-p`. That primitive lands on the first heading at any level, including children. So the search range was metadata-end up to the child's heading line, which excluded the child's body. Bodies that lived in child sub-headings never got searched. I switched the bound to `(org-end-of-subtree t t)`, which covers the whole subtree of the current heading and degrades gracefully at the last heading in the buffer. The reporter suggested `outline-forward-same-level`, but that primitive errors at the last sibling, which would be its own regression. `org-end-of-subtree` is the canonical Emacs idiom for this kind of bound and handles end-of-buffer correctly. I added `tests/test-org-drill-entry-empty-p.el` with 6 ERT tests across Normal, Boundary (kqr's exact fixture), and edge categories. The two regression tests fail at HEAD before the fix and pass after. One semantic note worth flagging: any subtree content now counts as non-empty, including bare child headings with no body of their own. The bug report is silent on that case and I expect it to be rare in practice. If anyone reports the new behavior as a regression, the fix would be to filter heading lines out of the graphical-character search.
* fix: preserve default-input-method during key reads (upstream #52, #58)Craig Jennings2026-05-051-0/+108
| | | | | | | | | | Two reports from breadncup (issue #52 in 2023, issue #58 in 2024) said that running an org-drill session silently nulled out their `default-input-method`. The reproduction is exact: every rating prompt clears the user's persistent setting. The cause is `(set-input-method nil)` in `org-drill--read-key-sequence`. When `current-input-method` is nil, calling `set-input-method` with nil clears `default-input-method` as a documented side effect. The unwind-protect on the way back has the symmetric problem, since it passes the captured nil. The fix is to use the primitives that are scoped to current state. `deactivate-input-method` and `activate-input-method` don't touch `default-input-method`, and I wrap each call in a guard so the function is a no-op when no input method is active. The same pattern lives in `org-drill-response-get-buffer-create`, which propagates the caller's input method into the response buffer. When the caller has no input method active, the captured value is nil and `(set-input-method nil)` runs in the new buffer, clearing `default-input-method` again. I applied the same guard there. I added `tests/test-org-drill-read-key-sequence.el` with 6 ERT tests across Normal, Boundary (the bug case), and Error categories. The four regression tests fail at HEAD before the fix and pass after.
* test: cover org-drill-time-to-inactive-org-timestamp (upstream #59)Craig Jennings2026-05-051-0/+90
| | | | | | | | I added a regression test for `org-drill-time-to-inactive-org-timestamp` to lock in the cherry-pick from commit 4c6e62a, which fixed upstream issue #59 on the GitLab tracker. Chipschap reported timestamps like `[Y-08-27 Wed 16:%]` getting written into DRILL_LAST_REVIEWED. The root cause is that Org 9.6+ dropped the angle brackets around `(cdr org-time-stamp-formats)`, so the original `(substring ... 1 -1)` started slicing off the leading `%` of `%Y` and the trailing `M` of `%M`. The fix took the Org 9.6+ branch via `(org-time-stamp-format t 'no-bracket)` instead. The new test file has 7 ERT tests across Normal, Boundary, and Error categories. The Error cases assert the output has no stray `%` characters and no literal `Y` in place of the year. I confirmed the same tests fail when I drop in the original buggy implementation, so they catch the bug shape from the report.
* build: add make coverage target via undercoverCraig Jennings2026-05-051-0/+33
| | | | | | | | | | I want to track test coverage as I work through the upstream issue backlog, so I added an undercover-based flow that mirrors how `make test-unit` already runs each file in its own Cask Emacs process. The Makefile gets `make coverage` and `make coverage-clean`. A new helper at `tests/run-coverage-file.el` instruments `org-drill.el` before the source is loaded. Undercover merges per-file results into a single simplecov JSON at `.coverage/simplecov.json`. I added `undercover` as a Cask development dep and `.coverage/` to `.gitignore` so the report stays local. I also renamed `make install` to `make setup`. The old name read like "deploy the package onto my system," but the target only installs Cask deps into the local `.cask/` directory. `setup` is closer to what it actually does, and all the internal `: install` prerequisites move with it. Baseline at this commit is 10.8% (208/1928 lines on org-drill.el).
* test: expect totaln increment on Simple8 failure pathCraig Jennings2026-04-291-4/+5
| | | | The failure-path assertion in the totaln test now expects the count to increment on both success and failure, matching SM2 and SM5. The updated test goes red against the current source. The source fix follows in the next commit.
* test: add Simple8 scheduler testsCraig Jennings2026-04-291-0/+303
| | | | | | | | | | The Simple8 algorithm at org-drill-determine-next-interval-simple8 had no direct test coverage, completing the trio after SM2 (37 tests) and SM5 (32 tests, just landed). Adds a per-function test file with 34 tests across Normal, Boundary, Error, algorithm-verification, and helper-specific categories. Simple8-specific surface gets dedicated coverage. The function returns a 6-element list (not 7 like SM2/SM5) and recomputes ease from meanq each call rather than carrying an EF parameter through. Failure does not increment totaln (different from SM2/SM5, which always increment). The four delta-days configurations (nil, positive × flag, negative × flag) each take a distinct code path, including a late-review use-n adjustment that SM5 doesn't have. The three pure-math helpers (simple8-first-interval, simple8-interval-factor, simple8-quality->ease) get five direct tests so polynomial-coefficient typos can't drift silently. All 34 pass on first run as characterization. Full suite at 214 of 214 (was 180, +34).
* refactor: extract shared scheduler test extractorsCraig Jennings2026-04-293-157/+156
| | | | | | | | Three test files (SM2, SM5, and the upcoming Simple8) all extract the same fields from a scheduler result list. Pull the shared extractors into tests/testutil-scheduler.el so each algorithm's test file can use them. Position 2 holds an EF in SM2 and SM5 and an EASE in Simple8. Both names are exposed as aliases pointing at the same nth position so each call site reads accurately. SM2 and SM5 test files now require testutil-scheduler and call the shared helpers. 69 of 69 scheduler tests still green. Full unit suite at 180 of 180.
* test: add SM5 scheduler testsCraig Jennings2026-04-291-0/+337
| | | | | | | | The SM5 algorithm at org-drill-determine-next-interval-sm5 had no direct test coverage. SM2 has 37 tests. SM5 has zero. Adds a per-function test file that mirrors the SM2 file's structure. 32 tests cover Normal, Boundary, Error, and algorithm-verification categories. The SM5-specific surface gets dedicated coverage. Failure preserves the input EF, not the modified one. The of-matrix is copied, not mutated. The four delta-days configurations (nil, positive, negative-with-flag, negative-without-flag) each take a different code path. The Error category includes should-error cases for the cl-assert preconditions on n and quality, which is a gap SM2's tests still have. All 32 pass on first run as characterization. Full suite at 180 of 180.
* test: Add boundary, error, and edge case testsCraig Jennings2025-11-135-0/+1082
| | | | | | | | Added 66 comprehensive tests covering: - Entry detection with extreme values and Unicode - SM2 algorithm with boundary conditions - Workflow error handling with malformed data - Card types with complex content structures
* test: Complete Phase 2 card type testsCraig Jennings2025-11-133-0/+271
| | | | | | | | | - Add unit tests for show1cloze card type (6 tests) - Add unit tests for multicloze variants (12 tests) - Add integration test for card type system (5 tests) Phase 2 complete: All major card types tested Total: 114 tests (98 unit + 16 integration), all passing
* test: Add Phase 2 card type testsCraig Jennings2025-11-133-0/+478
| | | | | | | | - Add unit tests for simple card type (11 tests) - Add unit tests for twosided card type (11 tests) - Add unit tests for hide1cloze card type (4 tests) Total: 91 tests (80 unit + 11 integration), all passing
* test: Add Phase 1 foundation tests for critical functionsCraig Jennings2025-11-135-0/+1068
| | | | | | | | | | | - Add unit tests for org-drill-entry-p (14 tests) - Add unit tests for org-drill-part-of-drill-entry-p (14 tests) - Add unit tests for SM2 scheduling algorithm (23 tests) - Add integration test for basic drill workflow (11 tests) - Update Makefile to support test-*.el naming pattern - Rename org-drill-test.el to test-org-drill.el for consistency Total: 65 tests, all passing
* refactor: Improve test infrastructure and fix all compiler warningsCraig Jennings2025-11-133-0/+701
This commit modernizes the test infrastructure and eliminates all compilation warnings to prepare for comprehensive test coverage. Test Infrastructure Improvements: - Reorganize tests from test/ to tests/ directory (standard convention) - Modernize Makefile with patterns from chime.el - Add convenient test targets (test-file, test-name) - Support unit and integration test separation - Better help documentation with examples - Auto-detect Cask installation location - Add comprehensive test-strategy.org document - 6-week implementation plan - Critical function prioritization - Integration test scenarios - Coverage goals (80% target) Compiler Warning Fixes (org-drill.el): - Replace obsolete org-mode functions: - org-show-subtree → org-fold-show-subtree - org-show-entry → org-fold-show-entry - org-get-tags-at → org-get-tags - org-remove-latex-fragment-image-overlays → org-clear-latex-preview - org-toggle-latex-fragment → org-latex-preview - org-bracket-link-regexp → org-link-bracket-re - Fix ~31 unescaped single quotes in docstrings (use \=') - Remove unused lexical variables (cb, drawer-name, session, orig-fun) - Remove obsolete outline-view-change-hook binding - Wrap org 8.x compatibility shim in with-no-warnings - Fix long docstring at line 1085 Test Status: - All 3 existing tests passing - Zero compilation warnings (was ~40 warnings) - Ready for Phase 1 implementation (foundation tests)