aboutsummaryrefslogtreecommitdiff
path: root/tests/test-org-spec-links.el
blob: 6359689f94f4dc0b02b1ef6518705808e4a997c8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
;;; test-org-spec-links.el --- docs/specs org-id resolution -*- lexical-binding: t; -*-

;;; Commentary:
;; Tests for the docs/specs spec-file scanner behind org-id link
;; resolution (org-spec-links.el).  Projects are directories carrying
;; .ai/protocols.org; each contributes its docs/specs/*.org files.  The
;; scanner takes explicit base dirs so the tests run against a sandbox.

;;; Code:

(require 'ert)

(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory))

(require 'org-spec-links)

;; org-id may never load in batch; declare its var special so the
;; let-binding below is dynamic, not a silent lexical shadow.
(defvar org-id-extra-files)

(defun test-org-spec-links--make-sandbox ()
  "Build a sandbox: two projects, one with specs, one without; one non-project."
  (let ((base (make-temp-file "spec-links-" t)))
    ;; p1: a project with two spec files
    (make-directory (expand-file-name "p1/.ai" base) t)
    (write-region "" nil (expand-file-name "p1/.ai/protocols.org" base))
    (make-directory (expand-file-name "p1/docs/specs" base) t)
    (write-region "" nil (expand-file-name "p1/docs/specs/a-spec.org" base))
    (write-region "" nil (expand-file-name "p1/docs/specs/b-spec.org" base))
    ;; p2: a project with no docs/specs
    (make-directory (expand-file-name "p2/.ai" base) t)
    (write-region "" nil (expand-file-name "p2/.ai/protocols.org" base))
    ;; p3: not a project (no protocols.org) but has docs/specs
    (make-directory (expand-file-name "p3/docs/specs" base) t)
    (write-region "" nil (expand-file-name "p3/docs/specs/c-spec.org" base))
    base))

(ert-deftest test-org-spec-links-scanner-finds-project-specs ()
  "Normal: spec files from protocols-carrying projects only, absolute paths."
  (let ((base (test-org-spec-links--make-sandbox)))
    (unwind-protect
        (let ((files (cj/--org-spec-files (list base))))
          (should (= (length files) 2))
          (should (cl-every #'file-name-absolute-p files))
          (should (seq-find (lambda (f) (string-suffix-p "p1/docs/specs/a-spec.org" f)) files))
          (should (seq-find (lambda (f) (string-suffix-p "p1/docs/specs/b-spec.org" f)) files))
          (should-not (seq-find (lambda (f) (string-match-p "p3" f)) files)))
      (delete-directory base t))))

(ert-deftest test-org-spec-links-scanner-empty-base ()
  "Boundary: a base dir with no projects yields nil."
  (let ((base (make-temp-file "spec-links-empty-" t)))
    (unwind-protect
        (should-not (cj/--org-spec-files (list base)))
      (delete-directory base t))))

(ert-deftest test-org-spec-links-scanner-missing-base ()
  "Error: a non-existent base dir is skipped without signaling."
  (should-not (cj/--org-spec-files '("/nonexistent/base/dir"))))

(ert-deftest test-org-spec-links-refresh-sets-extra-files ()
  "Normal: the refresh command points org-id-extra-files at the scan result."
  (let* ((base (test-org-spec-links--make-sandbox))
         (org-id-extra-files nil)
         ;; the default scan appends user-emacs-directory; point it into
         ;; the sandbox so the real config's specs don't leak in
         (user-emacs-directory (expand-file-name "p2/" base)))
    (unwind-protect
        (cl-letf (((symbol-function 'cj/--org-spec-project-base-dirs)
                   (lambda () (list base)))
                  ;; org-id may be absent in batch; the update step is mocked.
                  ((symbol-function 'org-id-update-id-locations)
                   (lambda (&rest _) nil)))
          (cj/org-id-refresh-spec-locations)
          (should (= (length org-id-extra-files) 2)))
      (delete-directory base t))))

(provide 'test-org-spec-links)
;;; test-org-spec-links.el ends here