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
| | ;;; test-org-element-parser.el --- Tests for org-element.el parser
;; Copyright (C) 2021 Ihor Radchenko
;; Author: Ihor Radchenko <yantar92 at gmail dot com>
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;; Code:
(require 'org-element)
(defvar test-org-element-parser-properties
'((:global :begin :end :contents-begin :contents-end :pre-blank :post-blank :post-affiliated)
(headline :raw-value :title :level :priority :tags :todo-keyword :todo-type :footnote-section-p :archivedp :commentedp))
"List of important properties that should be parsed.")
(defvar test-org-element-parser-source-directory "../lisp/test-org-element-parser-sources/"
"Path to directory containing all the test Org files.
The expected parsed representation is stored alongside in .el files.
For example, parsed representation of file.org is in file.el.")
(defun test-org-element-parser-generate-syntax-sexp ()
"Return SEXP with important parts of parsed representation of current Org buffer."
(unless (derived-mode-p 'org-mode) (user-error "Not an Org buffer."))
(let ((datum (org-element-parse-buffer 'object))
(strip-func (lambda (el)
(let ((type (org-element-type el))
(plist (when (listp el) (nth 1 el)))
prop value tmpalist)
(if (eq type 'plain-text)
(set-text-properties 0 (length el) nil el)
(while plist
(setq prop (car plist))
(setq value (cadr plist))
(when (stringp value) (setq value (substring-no-properties value)))
(setq plist (cddr plist))
(when (or (memq prop (alist-get :global test-org-element-parser-properties))
(memq prop (alist-get type test-org-element-parser-properties)))
(push (cons prop value) tmpalist)))
(setq tmpalist (sort tmpalist (lambda (a b) (string< (symbol-name (car a))
(symbol-name (car b))))))
(setf (nth 1 el)
(apply #'append
(mapcar (lambda (c) (list (car c) (cdr c)))
tmpalist))))))))
(org-element-map datum (append '(plain-text) org-element-all-elements org-element-all-objects)
strip-func nil nil nil 'with-affiliated)
;; `org-element-map' never maps over `org-data'. Update it separately.
(funcall strip-func datum)
datum))
(defun test-org-element-parser-save-expected-result (&optional file)
"Save reference parsed representation of current Org buffer or FILE.
The parsed representation will be saved alongside with the buffer file."
(interactive)
(with-current-buffer (if file
(get-buffer-create file)
(current-buffer))
(save-buffer)
(let ((datum (test-org-element-parser-generate-syntax-sexp))
(path (buffer-file-name))
newpath)
(unless (and path (file-exists-p path)) (user-error "Not in a file buffer."))
(setq newpath (format "%s.el" (file-name-base path)))
(with-temp-file newpath
(condition-case err
(progn
(pp datum (current-buffer))
(message "Parsed representation saved to %s" (expand-file-name newpath)))
(err (message "Failed to save parsed representation: \"%S\"" err)))))))
(defmacro org-test-element-verify (&optional file)
"Verify `org-element-parse-buffer' for current Org buffer or FILE."
`(progn
(unless ,file
(setq file (buffer-file-name))
(save-buffer))
(unless (and ,file (file-exists-p ,file))
(user-error "%s does not exist." ,file))
(let ((reference-file (format "%s%s.el"
(file-name-directory ,file)
(file-name-base ,file))))
(unless (file-exists-p reference-file)
(user-error "Reference result file %s does not exist." reference-file))
(with-temp-buffer
(insert-file-contents ,file)
(org-mode)
(should
(equal (test-org-element-parser-generate-syntax-sexp)
(with-temp-buffer
(insert-file-contents reference-file)
(read (current-buffer)))))))))
(defmacro test-org-element-parser-files (&rest files)
"Run `org-test-element-verify' for each file in FILES."
`(progn
(unless (and test-org-element-parser-source-directory
(file-exists-p test-org-element-parser-source-directory))
(error "%s does not exist." test-org-element-parser-source-directory))
(dolist (file '(,@files))
(setq file (format "%s%s.org"
(file-name-as-directory test-org-element-parser-source-directory)
(file-name-base file)))
(org-test-element-verify file))))
\f
(ert-deftest test-org-element-parser/simple-headlines ()
"Basic tests for Org files with headings and plain text paragraphs."
(test-org-element-parser-files "simple-heading"))
(ert-deftest test-org-element-parser/README ()
"Test README.org in the example file repo."
(test-org-element-parser-files "README"))
(provide 'test-org-element-parser)
;;; test-org-element-parser.el ends here
|