summaryrefslogtreecommitdiff
path: root/tests/test-org-refile-build-targets.el
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test-org-refile-build-targets.el')
-rw-r--r--tests/test-org-refile-build-targets.el305
1 files changed, 0 insertions, 305 deletions
diff --git a/tests/test-org-refile-build-targets.el b/tests/test-org-refile-build-targets.el
deleted file mode 100644
index e7ab5c42..00000000
--- a/tests/test-org-refile-build-targets.el
+++ /dev/null
@@ -1,305 +0,0 @@
-;;; test-org-refile-build-targets.el --- Tests for cj/build-org-refile-targets -*- lexical-binding: t; -*-
-
-;;; Commentary:
-;; Unit tests for cj/build-org-refile-targets caching logic.
-;; Tests cache behavior, TTL expiration, force rebuild, and async build flag.
-
-;;; Code:
-
-(require 'ert)
-
-;; Add modules to load path
-(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory))
-
-;; Stub dependencies before loading the module
-(defvar inbox-file "/tmp/test-inbox.org")
-(defvar reference-file "/tmp/test-reference.org")
-(defvar schedule-file "/tmp/test-schedule.org")
-(defvar user-emacs-directory "/tmp/test-emacs.d/")
-(defvar code-dir "/tmp/test-code/")
-(defvar projects-dir "/tmp/test-projects/")
-
-;; Now load the actual production module
-(require 'org-refile-config)
-
-;;; Setup and Teardown
-
-(defun test-org-refile-setup ()
- "Reset cache and state before each test."
- (setq cj/org-refile-targets-cache nil)
- (setq cj/org-refile-targets-cache-time nil)
- (setq cj/org-refile-targets-building nil)
- (setq org-refile-targets nil))
-
-(defun test-org-refile-teardown ()
- "Clean up after each test."
- (setq cj/org-refile-targets-cache nil)
- (setq cj/org-refile-targets-cache-time nil)
- (setq cj/org-refile-targets-building nil)
- (setq org-refile-targets nil))
-
-;;; Normal Cases
-
-(ert-deftest test-org-refile-build-targets-normal-first-call-builds-cache ()
- "Test that first call builds cache from scratch.
-
-When cache is empty, function should:
-1. Scan directories for todo.org files
-2. Build refile targets list
-3. Populate cache
-4. Set cache timestamp"
- (test-org-refile-setup)
- (unwind-protect
- (cl-letf (((symbol-function 'directory-files-recursively)
- (lambda (_dir _pattern) '("/tmp/todo.org")))
- ((symbol-function 'fboundp) (lambda (_sym) nil)))
-
- ;; Before call: cache empty
- (should (null cj/org-refile-targets-cache))
- (should (null cj/org-refile-targets-cache-time))
-
- ;; Build targets
- (cj/build-org-refile-targets)
-
- ;; After call: cache populated
- (should cj/org-refile-targets-cache)
- (should cj/org-refile-targets-cache-time)
- (should org-refile-targets)
-
- ;; Cache matches org-refile-targets
- (should (equal cj/org-refile-targets-cache org-refile-targets))
-
- ;; Contains base files (inbox, reference, schedule)
- (should (>= (length org-refile-targets) 3)))
- (test-org-refile-teardown)))
-
-(ert-deftest test-org-refile-build-targets-normal-second-call-uses-cache ()
- "Test that second call uses cache instead of rebuilding.
-
-When cache is valid (not expired):
-1. Should NOT scan directories again
-2. Should restore targets from cache
-3. Should NOT update cache timestamp"
- (test-org-refile-setup)
- (unwind-protect
- (let ((scan-count 0))
- (cl-letf (((symbol-function 'directory-files-recursively)
- (lambda (_dir _pattern)
- (setq scan-count (1+ scan-count))
- '("/tmp/todo.org")))
- ((symbol-function 'fboundp) (lambda (_sym) nil)))
-
- ;; First call: builds cache
- (cj/build-org-refile-targets)
- (should (= scan-count 3)) ; 3 directories scanned
-
- (let ((cached-time cj/org-refile-targets-cache-time)
- (cached-targets cj/org-refile-targets-cache))
-
- ;; Second call: uses cache
- (cj/build-org-refile-targets)
-
- ;; Scan count unchanged (cache hit)
- (should (= scan-count 3))
-
- ;; Cache unchanged
- (should (equal cj/org-refile-targets-cache-time cached-time))
- (should (equal cj/org-refile-targets-cache cached-targets)))))
- (test-org-refile-teardown)))
-
-(ert-deftest test-org-refile-build-targets-normal-force-rebuild-bypasses-cache ()
- "Test that force-rebuild parameter bypasses cache.
-
-When force-rebuild is non-nil:
-1. Should ignore valid cache
-2. Should rebuild from scratch
-3. Should update cache with new data"
- (test-org-refile-setup)
- (unwind-protect
- (let ((scan-count 0))
- (cl-letf (((symbol-function 'directory-files-recursively)
- (lambda (_dir _pattern)
- (setq scan-count (1+ scan-count))
- (if (> scan-count 3)
- '("/tmp/todo.org" "/tmp/todo2.org") ; New file on rebuild
- '("/tmp/todo.org"))))
- ((symbol-function 'fboundp) (lambda (_sym) nil)))
-
- ;; First call: builds cache
- (cj/build-org-refile-targets)
- (let ((initial-count (length org-refile-targets)))
-
- ;; Force rebuild
- (cj/build-org-refile-targets 'force)
-
- ;; Scanned again (3 more directories)
- (should (= scan-count 6))
-
- ;; New targets include additional file
- (should (> (length org-refile-targets) initial-count)))))
- (test-org-refile-teardown)))
-
-;;; Boundary Cases
-
-(ert-deftest test-org-refile-build-targets-boundary-cache-expires-after-ttl ()
- "Test that cache expires after TTL period.
-
-When cache timestamp exceeds TTL:
-1. Should rebuild targets
-2. Should update cache timestamp
-3. Should rescan directories"
- (test-org-refile-setup)
- (unwind-protect
- (let ((scan-count 0))
- (cl-letf (((symbol-function 'directory-files-recursively)
- (lambda (_dir _pattern)
- (setq scan-count (1+ scan-count))
- '("/tmp/todo.org")))
- ((symbol-function 'fboundp) (lambda (_sym) nil)))
-
- ;; First call: builds cache
- (cj/build-org-refile-targets)
- (should (= scan-count 3))
-
- ;; Simulate cache expiration (set time to 2 hours ago)
- (setq cj/org-refile-targets-cache-time
- (- (float-time) (* 2 3600)))
-
- ;; Second call: cache expired, rebuild
- (cj/build-org-refile-targets)
-
- ;; Scanned again (cache was expired)
- (should (= scan-count 6))
-
- ;; Cache timestamp updated to current time
- (should (< (- (float-time) cj/org-refile-targets-cache-time) 1))))
- (test-org-refile-teardown)))
-
-(ert-deftest test-org-refile-build-targets-boundary-empty-directories-creates-minimal-targets ()
- "Test behavior when directories contain no todo.org files.
-
-When directory scans return empty:
-1. Should still create base targets (inbox, reference, schedule)
-2. Should not fail or error
-3. Should cache the minimal result"
- (test-org-refile-setup)
- (unwind-protect
- (cl-letf (((symbol-function 'directory-files-recursively)
- (lambda (_dir _pattern) nil)) ; No files found
- ((symbol-function 'fboundp) (lambda (_sym) nil)))
-
- (cj/build-org-refile-targets)
-
- ;; Should have base files only
- (should (= (length org-refile-targets) 3))
-
- ;; Cache should contain base files
- (should cj/org-refile-targets-cache)
- (should (= (length cj/org-refile-targets-cache) 3)))
- (test-org-refile-teardown)))
-
-(ert-deftest test-org-refile-build-targets-boundary-building-flag-set-during-build ()
- "Test that building flag is set during build and cleared after.
-
-During build:
-1. Flag should be set to prevent concurrent builds
-2. Flag should clear even if build fails
-3. Flag state should be consistent"
- (test-org-refile-setup)
- (unwind-protect
- (let ((flag-during-build nil))
- (cl-letf (((symbol-function 'directory-files-recursively)
- (lambda (_dir _pattern)
- ;; Capture flag state during directory scan
- (setq flag-during-build cj/org-refile-targets-building)
- '("/tmp/todo.org")))
- ((symbol-function 'fboundp) (lambda (_sym) nil)))
-
- ;; Before build
- (should (null cj/org-refile-targets-building))
-
- ;; Build
- (cj/build-org-refile-targets)
-
- ;; Flag was set during build
- (should flag-during-build)
-
- ;; Flag cleared after build
- (should (null cj/org-refile-targets-building))))
- (test-org-refile-teardown)))
-
-(ert-deftest test-org-refile-build-targets-boundary-building-flag-clears-on-error ()
- "Test that building flag clears even if build errors.
-
-When build encounters error:
-1. Flag should still be cleared (unwind-protect)
-2. Prevents permanently locked state
-3. Next build can proceed"
- (test-org-refile-setup)
- (unwind-protect
- (cl-letf (((symbol-function 'directory-files-recursively)
- (lambda (_dir _pattern)
- (error "Simulated scan failure")))
- ((symbol-function 'fboundp) (lambda (_sym) nil)))
-
- ;; Build will error
- (should-error (cj/build-org-refile-targets))
-
- ;; Flag cleared despite error (unwind-protect)
- (should (null cj/org-refile-targets-building)))
- (test-org-refile-teardown)))
-
-;;; Error Cases
-
-(ert-deftest test-org-refile-build-targets-error-nil-cache-with-old-timestamp ()
- "Test handling of inconsistent state (nil cache but timestamp set).
-
-When cache is nil but timestamp exists:
-1. Should recognize cache as invalid
-2. Should rebuild targets
-3. Should set both cache and timestamp"
- (test-org-refile-setup)
- (unwind-protect
- (cl-letf (((symbol-function 'directory-files-recursively)
- (lambda (_dir _pattern) '("/tmp/todo.org")))
- ((symbol-function 'fboundp) (lambda (_sym) nil)))
-
- ;; Set inconsistent state
- (setq cj/org-refile-targets-cache nil)
- (setq cj/org-refile-targets-cache-time (float-time))
-
- ;; Build should recognize invalid state
- (cj/build-org-refile-targets)
-
- ;; Cache now populated
- (should cj/org-refile-targets-cache)
- (should cj/org-refile-targets-cache-time)
- (should org-refile-targets))
- (test-org-refile-teardown)))
-
-(ert-deftest test-org-refile-build-targets-error-directory-scan-failure-propagates ()
- "Test that directory scan failures propagate as errors.
-
-When directory-files-recursively errors:
-1. Error should propagate to caller
-2. Cache should not be corrupted
-3. Building flag should clear"
- (test-org-refile-setup)
- (unwind-protect
- (cl-letf (((symbol-function 'directory-files-recursively)
- (lambda (_dir _pattern)
- (error "Permission denied")))
- ((symbol-function 'fboundp) (lambda (_sym) nil)))
-
- ;; Should propagate error
- (should-error (cj/build-org-refile-targets))
-
- ;; Cache not corrupted (still nil)
- (should (null cj/org-refile-targets-cache))
-
- ;; Building flag cleared
- (should (null cj/org-refile-targets-building)))
- (test-org-refile-teardown)))
-
-(provide 'test-org-refile-build-targets)
-;;; test-org-refile-build-targets.el ends here