summaryrefslogtreecommitdiff
path: root/tests/test-org-drill-first-function.el
blob: 925cdf84b66da41cad56b571abc2b42d0f2a86d4 (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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
;;; test-org-drill-first-function.el --- Test org-drill 'first' function compatibility -*- lexical-binding: t -*-

;;; Commentary:
;;
;; Tests to reproduce and verify the fix for org-drill's use of deprecated
;; 'first' function which was removed in modern Emacs.
;;
;; Original error: "mapcar: Symbol's function definition is void: first"
;;
;; The error occurred because org-drill (or its dependencies) use old Common Lisp
;; functions like 'first' instead of the modern 'cl-first' from cl-lib.

;;; Code:

(require 'ert)

(ert-deftest test-org-drill-first-function-not-defined-without-compat ()
  "Verify that 'first' function doesn't exist by default in modern Emacs.

This test documents the original problem - the 'first' function from the
old 'cl' package is not available in modern Emacs, which only provides
'cl-first' from cl-lib."
  (let ((first-defined (fboundp 'first)))
    ;; In a clean Emacs without our compatibility shim, 'first' should not exist
    ;; (unless the old 'cl' package was loaded, which is deprecated)
    (should (or (not first-defined)
                ;; If it IS defined, it should be our compatibility alias
                (eq (symbol-function 'first) 'cl-first)))))

(ert-deftest test-org-drill-cl-first-is-available ()
  "Verify that cl-first is available from cl-lib.

The modern cl-lib package provides cl-first as the replacement for
the deprecated 'first' function."
  (require 'cl-lib)
  (should (fboundp 'cl-first))
  ;; Test it works
  (should (eq 'a (cl-first '(a b c)))))

(ert-deftest test-org-drill-first-compatibility-alias ()
  "Verify that our compatibility alias makes 'first' work like 'cl-first'.

This is the fix we applied - creating an alias so that code using the
old 'first' function will work with the modern 'cl-first'."
  (require 'cl-lib)

  ;; Create the compatibility alias (same as in org-drill-config.el)
  (unless (fboundp 'first)
    (defalias 'first 'cl-first))

  ;; Now 'first' should be defined
  (should (fboundp 'first))

  ;; And it should behave like cl-first
  (should (eq 'a (first '(a b c))))
  (should (eq 'x (first '(x y z))))
  (should (eq nil (first '()))))

(ert-deftest test-org-drill-mapcar-with-first ()
  "Test the exact error scenario: (mapcar 'first ...).

This reproduces the original error that occurred during org-drill's
item collection phase where it uses mapcar with the 'first' function."
  (require 'cl-lib)

  ;; Create the compatibility alias
  (unless (fboundp 'first)
    (defalias 'first 'cl-first))

  ;; Simulate org-drill data structure: list of (status data) pairs
  (let ((drill-entries '((:new 0 0)
                         (:young 5 3)
                         (:overdue 10 2)
                         (:mature 20 1))))

    ;; This is the kind of operation that was failing
    ;; Extract first element from each entry
    (let ((statuses (mapcar 'first drill-entries)))
      (should (equal statuses '(:new :young :overdue :mature))))))

(ert-deftest test-org-drill-second-and-third-aliases ()
  "Verify that second and third compatibility aliases also work.

org-drill might use other deprecated cl functions too, so we create
aliases for second and third as well."
  (require 'cl-lib)

  ;; Create all compatibility aliases
  (unless (fboundp 'first)
    (defalias 'first 'cl-first))
  (unless (fboundp 'second)
    (defalias 'second 'cl-second))
  (unless (fboundp 'third)
    (defalias 'third 'cl-third))

  (let ((test-list '(a b c d e)))
    (should (eq 'a (first test-list)))
    (should (eq 'b (second test-list)))
    (should (eq 'c (third test-list)))))

(ert-deftest test-org-drill-config-loads-without-error ()
  "Verify that org-drill-config.el loads successfully with our fix.

This test ensures that the :init block in our use-package form
doesn't cause any loading errors."
  ;; This should not throw an error
  (should-not (condition-case err
                  (progn
                    (load (expand-file-name "modules/org-drill-config.el"
                                            user-emacs-directory))
                    nil)
                (error err))))

(ert-deftest test-org-drill-data-structure-operations ()
  "Verify that common org-drill data structure operations work with our fix.

org-drill works with data structures that require extracting elements.
This test ensures our compatibility aliases work with typical patterns."
  (require 'cl-lib)

  ;; Create compatibility aliases
  (unless (fboundp 'first)
    (defalias 'first 'cl-first))

  ;; Test that we can work with org-drill-like data structures
  ;; (similar to what persist-defvar would store)
  (let ((test-data '((:status-1 data-1)
                     (:status-2 data-2)
                     (:status-3 data-3))))
    ;; This kind of operation should work
    (should (equal '(:status-1 :status-2 :status-3)
                   (mapcar 'first test-data)))))

(provide 'test-org-drill-first-function)
;;; test-org-drill-first-function.el ends here