org-export: Allow to toggle inlinetasks inclusion in export output
[org-mode.git] / testing / lisp / test-org-element.el
blob6c2b39f598c4671ef4bb059bef79c81ae69ef95e
1 ;;; test-org-element.el --- Tests for org-element.el
3 ;; Copyright (C) 2012 Nicolas Goaziou
5 ;; Author: Nicolas Goaziou <n.goaziou at gmail dot com>
7 ;; This program is free software; you can redistribute it and/or modify
8 ;; it under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation, either version 3 of the License, or
10 ;; (at your option) any later version.
12 ;; This program is distributed in the hope that it will be useful,
13 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ;; GNU General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
20 (unless (featurep 'org-element)
21 (signal 'missing-test-dependency "org-element"))
23 (defun org-test-parse-and-interpret (text)
24 "Parse TEXT as Org syntax and interpret it.
25 Return interpreted string."
26 (with-temp-buffer
27 (org-mode)
28 (insert text)
29 (org-element-interpret-data (org-element-parse-buffer))))
33 ;;; Test `org-element-map'
35 (ert-deftest test-org-element/map ()
36 "Test `org-element-map'."
37 ;; Can map to `plain-text' objects.
38 (should
39 (= 2
40 (org-test-with-temp-text "Some text \alpha
41 #+BEGIN_CENTER
42 Some other text
43 #+END_CENTER"
44 (let ((count 0))
45 (org-element-map
46 (org-element-parse-buffer) 'plain-text
47 (lambda (s) (when (string-match "text" s) (incf count))))
48 count))))
49 ;; Applies to secondary strings
50 (should
51 (org-element-map '("some " (bold nil "bold") "text") 'bold 'identity))
52 ;; Enter secondary strings before entering contents.
53 (should
54 (equal
55 "alpha"
56 (org-element-property
57 :name
58 (org-test-with-temp-text "* Some \\alpha headline\n\\beta entity."
59 (org-element-map (org-element-parse-buffer) 'entity 'identity nil t)))))
60 ;; Apply NO-RECURSION argument.
61 (should-not
62 (org-test-with-temp-text "#+BEGIN_CENTER\n\\alpha\n#+END_CENTER"
63 (org-element-map
64 (org-element-parse-buffer) 'entity 'identity nil nil 'center-block))))
68 ;;; Test Setters
70 (ert-deftest test-org-element/put-property ()
71 "Test `org-element-put-property' specifications."
72 (org-test-with-temp-text "* Headline\n *a*"
73 (let ((tree (org-element-parse-buffer)))
74 (org-element-put-property
75 (org-element-map tree 'bold 'identity nil t) :test 1)
76 (should (org-element-property
77 :test (org-element-map tree 'bold 'identity nil t))))))
79 (ert-deftest test-org-element/set-contents ()
80 "Test `org-element-set-contents' specifications."
81 ;; Accept multiple entries.
82 (should
83 (equal '("b" (italic nil "a"))
84 (org-test-with-temp-text "* Headline\n *a*"
85 (let ((tree (org-element-parse-buffer)))
86 (org-element-set-contents
87 (org-element-map tree 'bold 'identity nil t) "b" '(italic nil "a"))
88 (org-element-contents
89 (org-element-map tree 'bold 'identity nil t))))))
90 ;; Accept atoms and elements.
91 (should
92 (equal '("b")
93 (org-test-with-temp-text "* Headline\n *a*"
94 (let ((tree (org-element-parse-buffer)))
95 (org-element-set-contents
96 (org-element-map tree 'bold 'identity nil t) "b")
97 (org-element-contents
98 (org-element-map tree 'bold 'identity nil t))))))
99 (should
100 (equal '((italic nil "b"))
101 (org-test-with-temp-text "* Headline\n *a*"
102 (let ((tree (org-element-parse-buffer)))
103 (org-element-set-contents
104 (org-element-map tree 'bold 'identity nil t) '(italic nil "b"))
105 (org-element-contents
106 (org-element-map tree 'bold 'identity nil t))))))
107 ;; Allow nil contents.
108 (should-not
109 (org-test-with-temp-text "* Headline\n *a*"
110 (let ((tree (org-element-parse-buffer)))
111 (org-element-set-contents (org-element-map tree 'bold 'identity nil t))
112 (org-element-contents (org-element-map tree 'bold 'identity nil t))))))
114 (ert-deftest test-org-element/set-element ()
115 "Test `org-element-set-element' specifications."
116 (org-test-with-temp-text "* Headline\n*a*"
117 (let ((tree (org-element-parse-buffer)))
118 (org-element-set-element
119 (org-element-map tree 'bold 'identity nil t)
120 '(italic nil "b"))
121 ;; Check if object is correctly replaced.
122 (should (org-element-map tree 'italic 'identity))
123 (should-not (org-element-map tree 'bold 'identity))
124 ;; Check if new object's parent is correctly set.
125 (should
127 (org-element-property :parent
128 (org-element-map tree 'italic 'identity nil t))
129 (org-element-map tree 'paragraph 'identity nil t))))))
131 (ert-deftest test-org-element/adopt-element ()
132 "Test `org-element-adopt-element' specifications."
133 ;; Adopt an element.
134 (should
135 (equal '(italic plain-text)
136 (org-test-with-temp-text "* Headline\n *a*"
137 (let ((tree (org-element-parse-buffer)))
138 (org-element-adopt-element
139 (org-element-map tree 'bold 'identity nil t) '(italic nil "a"))
140 (mapcar (lambda (blob) (org-element-type blob))
141 (org-element-contents
142 (org-element-map tree 'bold 'identity nil t)))))))
143 ;; Adopt a string.
144 (should
145 (equal '("b" "a")
146 (org-test-with-temp-text "* Headline\n *a*"
147 (let ((tree (org-element-parse-buffer)))
148 (org-element-adopt-element
149 (org-element-map tree 'bold 'identity nil t) "b")
150 (org-element-contents
151 (org-element-map tree 'bold 'identity nil t))))))
152 ;; Test APPEND optional argument.
153 (should
154 (equal '("a" "b")
155 (org-test-with-temp-text "* Headline\n *a*"
156 (let ((tree (org-element-parse-buffer)))
157 (org-element-adopt-element
158 (org-element-map tree 'bold 'identity nil t) "b" t)
159 (org-element-contents
160 (org-element-map tree 'bold 'identity nil t)))))))
164 ;;; Test Parsers
166 ;;;; Babel Call
168 (ert-deftest test-org-element/babel-call-parser ()
169 "Test `babel-call' parsing."
170 ;; Standard test.
171 (should
172 (org-test-with-temp-text "#+CALL: test()"
173 (org-element-map (org-element-parse-buffer) 'babel-call 'identity)))
174 ;; Ignore case.
175 (should
176 (org-test-with-temp-text "#+call: test()"
177 (org-element-map (org-element-parse-buffer) 'babel-call 'identity))))
180 ;;;; Bold
182 (ert-deftest test-org-element/bold-parser ()
183 "Test `bold' parser."
184 ;; Standard test.
185 (should
186 (let ((org-emph-re "\\([ ('\"{]\\|^\\)\\(\\([+*/_=~]\\)\\([^ \n,\"']\\|[^ \n,\"'].*?\\(?:\n.*?\\)\\{0,1\\}[^ \n,\"']\\)\\3\\)\\([- .,:!?;'\")}\\]\\|$\\)"))
187 (org-test-with-temp-text "*bold*"
188 (org-element-map (org-element-parse-buffer) 'bold 'identity nil t))))
189 ;; Multi-line markup.
190 (should
191 (equal
192 (org-element-contents
193 (let ((org-emph-re "\\([ ('\"{]\\|^\\)\\(\\([+*/_=~]\\)\\([^ \n,\"']\\|[^ \n,\"'].*?\\(?:\n.*?\\)\\{0,1\\}[^ \n,\"']\\)\\3\\)\\([- .,:!?;'\")}\\]\\|$\\)"))
194 (org-test-with-temp-text "*first line\nsecond line*"
195 (org-element-map (org-element-parse-buffer) 'bold 'identity nil t))))
196 '("first line\nsecond line"))))
199 ;;;; Center Block
201 (ert-deftest test-org-element/center-block-parser ()
202 "Test `center-block' parser."
203 ;; Standard test.
204 (should
205 (org-test-with-temp-text "#+BEGIN_CENTER\nText\n#+END_CENTER"
206 (org-element-map (org-element-parse-buffer) 'center-block 'identity)))
207 ;; Ignore case.
208 (should
209 (org-test-with-temp-text "#+begin_center\nText\n#+end_center"
210 (org-element-map (org-element-parse-buffer) 'center-block 'identity)))
211 ;; Test folded block.
212 (org-test-with-temp-text "#+BEGIN_CENTER\nText\n#+END_CENTER"
213 (org-cycle)
214 (should
215 (org-element-property
216 :hiddenp
217 (org-element-map
218 (org-element-parse-buffer) 'center-block 'identity nil t))))
219 ;; Ignore incomplete block.
220 (should-not
221 (org-test-with-temp-text "#+BEGIN_CENTER"
222 (org-element-map
223 (org-element-parse-buffer) 'center-block 'identity nil t))))
226 ;;;; Clock
228 (ert-deftest test-org-element/clock-parser ()
229 "Test `clock' parser."
230 ;; Running clock.
231 (let* ((org-clock-string "CLOCK:")
232 (clock (org-test-with-temp-text "CLOCK: [2012-01-01 sun. 00:01]"
233 (org-element-map
234 (org-element-parse-buffer) 'clock 'identity nil t))))
235 (should (eq (org-element-property :status clock) 'running))
236 (should (equal (org-element-property :value clock)
237 "[2012-01-01 sun. 00:01]"))
238 (should-not (org-element-property :time clock)))
239 ;; Closed clock.
240 (let* ((org-clock-string "CLOCK:")
241 (clock (org-test-with-temp-text "
242 CLOCK: [2012-01-01 sun. 00:01]--[2012-01-01 sun. 00:02] => 0:01"
243 (org-element-map
244 (org-element-parse-buffer) 'clock 'identity nil t))))
245 (should (eq (org-element-property :status clock) 'closed))
246 (should (equal (org-element-property :value clock)
247 "[2012-01-01 sun. 00:01]--[2012-01-01 sun. 00:02]"))
248 (should (equal (org-element-property :time clock) "0:01"))))
251 ;;;; Code
253 (ert-deftest test-org-element/code-parser ()
254 "Test `code' parser."
255 ;; Regular test.
256 (should
257 (let ((org-emph-re "\\([ ('\"{]\\|^\\)\\(\\([+*/_=~]\\)\\([^ \n,\"']\\|[^ \n,\"'].*?\\(?:\n.*?\\)\\{0,1\\}[^ \n,\"']\\)\\3\\)\\([- .,:!?;'\")}\\]\\|$\\)"))
258 (org-test-with-temp-text "~code~"
259 (org-element-map (org-element-parse-buffer) 'code 'identity))))
260 ;; Multi-line markup.
261 (should
262 (equal
263 (org-element-property
264 :value
265 (let ((org-emph-re "\\([ ('\"{]\\|^\\)\\(\\([+*/_=~]\\)\\([^ \n,\"']\\|[^ \n,\"'].*?\\(?:\n.*?\\)\\{0,1\\}[^ \n,\"']\\)\\3\\)\\([- .,:!?;'\")}\\]\\|$\\)"))
266 (org-test-with-temp-text "~first line\nsecond line~"
267 (org-element-map
268 (org-element-parse-buffer) 'code 'identity nil t))))
269 "first line\nsecond line")))
272 ;;;; Comment
274 (ert-deftest test-org-element/comment-parser ()
275 "Test `comment' parser."
276 ;; Regular comment.
277 (should
278 (org-test-with-temp-text "# Comment"
279 (org-element-map (org-element-parse-buffer) 'comment 'identity)))
280 ;; Inline comment.
281 (should
282 (org-test-with-temp-text " # Comment"
283 (org-element-map (org-element-parse-buffer) 'comment 'identity)))
284 ;; Preserve indentation.
285 (should
286 (equal
287 (org-element-property
288 :value
289 (org-test-with-temp-text "# No blank\n# One blank"
290 (org-element-map (org-element-parse-buffer) 'comment 'identity nil t)))
291 "No blank\n One blank"))
292 ;; Comment with blank lines.
293 (should
294 (equal
295 (org-element-property
296 :value
297 (org-test-with-temp-text "# First part\n# \n#\n# Second part"
298 (org-element-map (org-element-parse-buffer) 'comment 'identity nil t)))
299 "First part\n\n\nSecond part"))
300 ;; Keywords without colons are treated as comments.
301 (should
302 (org-test-with-temp-text "#+wrong_keyword something"
303 (org-element-map (org-element-parse-buffer) 'comment 'identity)))
304 ;; Do not mix comments and keywords.
305 (should
306 (eq 1
307 (org-test-with-temp-text "#+keyword: value\n# comment\n#+keyword: value"
308 (length (org-element-map
309 (org-element-parse-buffer) 'comment 'identity)))))
310 (should
311 (equal "comment"
312 (org-test-with-temp-text "#+keyword: value\n# comment\n#+keyword: value"
313 (org-element-property
314 :value
315 (org-element-map
316 (org-element-parse-buffer) 'comment 'identity nil t))))))
319 ;;;; Comment Block
321 (ert-deftest test-org-element/comment-block-parser ()
322 "Test `comment-block' parser."
323 ;; Standard test.
324 (should
325 (org-test-with-temp-text "#+BEGIN_COMMENT\nText\n#+END_COMMENT"
326 (org-element-map
327 (org-element-parse-buffer) 'comment-block 'identity)))
328 ;; Ignore case.
329 (should
330 (org-test-with-temp-text "#+begin_comment\nText\n#+end_comment"
331 (org-element-map
332 (org-element-parse-buffer) 'comment-block 'identity)))
333 ;; Test folded block.
334 (org-test-with-temp-text "#+BEGIN_COMMENT\nText\n#+END_COMMENT"
335 (org-cycle)
336 (should
337 (org-element-property
338 :hiddenp
339 (org-element-map
340 (org-element-parse-buffer) 'comment-block 'identity nil t))))
341 ;; Ignore incomplete block.
342 (should-not
343 (org-test-with-temp-text "#+BEGIN_COMMENT"
344 (org-element-map
345 (org-element-parse-buffer) 'comment-block 'identity nil t))))
348 ;;;; Drawer
350 (ert-deftest test-org-element/drawer-parser ()
351 "Test `drawer' parser."
352 ;; Standard test.
353 (should
354 (let ((org-drawers '("TEST")))
355 (org-test-with-temp-text ":TEST:\nText\n:END:"
356 (org-element-map (org-element-parse-buffer) 'drawer 'identity))))
357 ;; Do not mix regular drawers and property drawers.
358 (should-not
359 (let ((org-drawers '("PROPERTIES")))
360 (org-test-with-temp-text ":PROPERTIES:\n:prop: value\n:END:"
361 (org-element-map
362 (org-element-parse-buffer) 'drawer 'identity nil t))))
363 ;; Ignore incomplete drawer.
364 (should-not
365 (let ((org-drawers '("TEST")))
366 (org-test-with-temp-text ":TEST:"
367 (org-element-map
368 (org-element-parse-buffer) 'drawer 'identity nil t)))))
371 ;;;; Dynamic Block
373 (ert-deftest test-org-element/dynamic-block-parser ()
374 "Test `dynamic-block' parser."
375 ;; Standard test.
376 (should
377 (org-test-with-temp-text
378 "#+BEGIN: myblock :param1 val1 :param2 val2\nText\n#+END:"
379 (org-element-map (org-element-parse-buffer) 'dynamic-block 'identity)))
380 ;; Folded view
381 (org-test-with-temp-text
382 "#+BEGIN: myblock :param1 val1 :param2 val2\nText\n#+END:"
383 (org-cycle)
384 (should
385 (org-element-property
386 :hiddenp
387 (org-element-map
388 (org-element-parse-buffer) 'dynamic-block 'identity nil t))))
389 ;; Ignore case.
390 (should
391 (org-test-with-temp-text
392 "#+begin: myblock :param1 val1 :param2 val2\nText\n#+end:"
393 (org-element-map (org-element-parse-buffer) 'dynamic-block 'identity)))
394 ;; Ignore incomplete block.
395 (should-not
396 (org-test-with-temp-text "#+BEGIN: myblock :param1 val1 :param2 val2"
397 (org-element-map
398 (org-element-parse-buffer) 'dynamic-block 'identity nil t))))
401 ;;;; Entity
403 (ert-deftest test-org-element/entity-parser ()
404 "Test `entity' parser."
405 ;; Without brackets.
406 (should
407 (org-test-with-temp-text "\\sin"
408 (org-element-map (org-element-parse-buffer) 'entity 'identity)))
409 ;; With brackets.
410 (should
411 (org-element-property
412 :use-brackets-p
413 (org-test-with-temp-text "\\alpha{}text"
414 (org-element-map (org-element-parse-buffer) 'entity 'identity nil t))))
415 ;; User-defined entity.
416 (should
417 (equal
418 (org-element-property
419 :name
420 (let ((org-entities-user
421 '(("test" "test" nil "test" "test" "test" "test"))))
422 (org-test-with-temp-text "\\test"
423 (org-element-map (org-element-parse-buffer) 'entity 'identity nil t))))
424 "test")))
427 ;;;; Example Block
429 (ert-deftest test-org-element/example-block-parser ()
430 "Test `example-block' parser."
431 ;; Standard test.
432 (should
433 (org-test-with-temp-text "#+BEGIN_EXAMPLE\nText\n#+END_EXAMPLE"
434 (org-element-map (org-element-parse-buffer) 'example-block 'identity)))
435 ;; Test folded block.
436 (org-test-with-temp-text "#+BEGIN_EXAMPLE\nText\n#+END_EXAMPLE"
437 (org-cycle)
438 (should
439 (org-element-property
440 :hiddenp
441 (org-element-map
442 (org-element-parse-buffer) 'example-block 'identity nil t))))
443 ;; Ignore incomplete block.
444 (should-not
445 (org-test-with-temp-text "#+BEGIN_EXAMPLE"
446 (org-element-map
447 (org-element-parse-buffer) 'example-block 'identity nil t))))
449 (ert-deftest test-org-element/block-switches ()
450 "Test `example-block' and `src-block' switches parsing."
451 (let ((org-coderef-label-format "(ref:%s)"))
452 ;; 1. Test "-i" switch.
453 (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp\n(+ 1 1)\n#+END_SRC"
454 (should-not
455 (org-element-property :preserve-indent (org-element-at-point))))
456 (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp -i\n(+ 1 1)\n#+END_SRC"
457 (should (org-element-property :preserve-indent (org-element-at-point))))
458 (org-test-with-temp-text "#+BEGIN_EXAMPLE\nText.\n#+END_EXAMPLE"
459 (should-not
460 (org-element-property :preserve-indent (org-element-at-point))))
461 (org-test-with-temp-text "#+BEGIN_EXAMPLE -i\nText.\n#+END_EXAMPLE"
462 (should (org-element-property :preserve-indent (org-element-at-point))))
463 ;; 2. "-n -r -k" combination should number lines, retain labels but
464 ;; not use them in coderefs.
465 (org-test-with-temp-text "#+BEGIN_EXAMPLE -n -r -k\nText.\n#+END_EXAMPLE"
466 (let ((element (org-element-at-point)))
467 (should (and (org-element-property :number-lines element)
468 (org-element-property :retain-labels element)
469 (not (org-element-property :use-labels element))))))
470 (org-test-with-temp-text
471 "#+BEGIN_SRC emacs-lisp -n -r -k\n(+ 1 1)\n#+END_SRC"
472 (let ((element (org-element-at-point)))
473 (should (and (org-element-property :number-lines element)
474 (org-element-property :retain-labels element)
475 (not (org-element-property :use-labels element))))))
476 ;; 3. "-n -r" combination should number-lines remove labels and not
477 ;; use them in coderefs.
478 (org-test-with-temp-text "#+BEGIN_EXAMPLE -n -r\nText.\n#+END_EXAMPLE"
479 (let ((element (org-element-at-point)))
480 (should (and (org-element-property :number-lines element)
481 (not (org-element-property :retain-labels element))
482 (not (org-element-property :use-labels element))))))
483 (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp -n -r\n(+ 1 1)\n#+END_SRC"
484 (let ((element (org-element-at-point)))
485 (should (and (org-element-property :number-lines element)
486 (not (org-element-property :retain-labels element))
487 (not (org-element-property :use-labels element))))))
488 ;; 4. "-n" or "+n" should number lines, retain labels and use them
489 ;; in coderefs.
490 (org-test-with-temp-text "#+BEGIN_EXAMPLE -n\nText.\n#+END_EXAMPLE"
491 (let ((element (org-element-at-point)))
492 (should (and (org-element-property :number-lines element)
493 (org-element-property :retain-labels element)
494 (org-element-property :use-labels element)))))
495 (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp -n\n(+ 1 1)\n#+END_SRC"
496 (let ((element (org-element-at-point)))
497 (should (and (org-element-property :number-lines element)
498 (org-element-property :retain-labels element)
499 (org-element-property :use-labels element)))))
500 (org-test-with-temp-text "#+BEGIN_EXAMPLE +n\nText.\n#+END_EXAMPLE"
501 (let ((element (org-element-at-point)))
502 (should (and (org-element-property :number-lines element)
503 (org-element-property :retain-labels element)
504 (org-element-property :use-labels element)))))
505 (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp +n\n(+ 1 1)\n#+END_SRC"
506 (let ((element (org-element-at-point)))
507 (should (and (org-element-property :number-lines element)
508 (org-element-property :retain-labels element)
509 (org-element-property :use-labels element)))))
510 ;; 5. No switch should not number lines, but retain labels and use
511 ;; them in coderefs.
512 (org-test-with-temp-text "#+BEGIN_EXAMPLE\nText.\n#+END_EXAMPLE"
513 (let ((element (org-element-at-point)))
514 (should (and (not (org-element-property :number-lines element))
515 (org-element-property :retain-labels element)
516 (org-element-property :use-labels element)))))
517 (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp\n(+ 1 1)\n#+END_SRC"
518 (let ((element (org-element-at-point)))
519 (should (and (not (org-element-property :number-lines element))
520 (org-element-property :retain-labels element)
521 (org-element-property :use-labels element)))))
522 ;; 6. "-r" switch only: do not number lines, remove labels, and
523 ;; don't use labels in coderefs.
524 (org-test-with-temp-text "#+BEGIN_EXAMPLE -r\nText.\n#+END_EXAMPLE"
525 (let ((element (org-element-at-point)))
526 (should (and (not (org-element-property :number-lines element))
527 (not (org-element-property :retain-labels element))
528 (not (org-element-property :use-labels element))))))
529 (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp -r\n(+ 1 1)\n#+END_SRC"
530 (let ((element (org-element-at-point)))
531 (should (and (not (org-element-property :number-lines element))
532 (not (org-element-property :retain-labels element))
533 (not (org-element-property :use-labels element))))))
534 ;; 7. Recognize coderefs with user-defined syntax.
535 (org-test-with-temp-text
536 "#+BEGIN_EXAMPLE -l \"[ref:%s]\"\nText [ref:text]\n#+END_EXAMPLE"
537 (let ((element (org-element-at-point)))
538 (should
539 (equal (org-element-property :label-fmt element) "[ref:%s]"))))
540 (org-test-with-temp-text
541 "#+BEGIN_SRC emacs-lisp -l \"[ref:%s]\"\n(+ 1 1) [ref:text]\n#+END_SRC"
542 (let ((element (org-element-at-point)))
543 (should
544 (equal (org-element-property :label-fmt element) "[ref:%s]"))))))
547 ;;;; Export Block
549 (ert-deftest test-org-element/export-block-parser ()
550 "Test `export-block' parser."
551 ;; Standard test.
552 (should
553 (org-test-with-temp-text "#+BEGIN_LATEX\nText\n#+END_LATEX"
554 (org-element-map
555 (let ((org-element-block-name-alist
556 '(("LATEX" . org-element-export-block-parser))))
557 (org-element-parse-buffer))
558 'export-block 'identity)))
559 ;; Test folded block.
560 (org-test-with-temp-text "#+BEGIN_LATEX\nText\n#+END_LATEX"
561 (org-cycle)
562 (should
563 (org-element-property
564 :hiddenp
565 (org-element-map
566 (let ((org-element-block-name-alist
567 '(("LATEX" . org-element-export-block-parser))))
568 (org-element-parse-buffer))
569 'export-block 'identity nil t))))
570 ;; Ignore case.
571 (should
572 (org-test-with-temp-text "#+begin_latex\nText\n#+end_latex"
573 (org-element-map
574 (let ((org-element-block-name-alist
575 '(("LATEX" . org-element-export-block-parser))))
576 (org-element-parse-buffer))
577 'export-block 'identity)))
578 ;; Ignore incomplete block.
579 (should-not
580 (org-test-with-temp-text "#+BEGIN_LATEX"
581 (org-element-map
582 (let ((org-element-block-name-alist
583 '(("LATEX" . org-element-export-block-parser))))
584 (org-element-parse-buffer))
585 'export-block 'identity nil t))))
588 ;;;; Export Snippet
590 (ert-deftest test-org-element/export-snippet-parser ()
591 "Test `export-snippet' parser."
592 (should
593 (equal
594 '("back-end" . "contents")
595 (org-test-with-temp-text "@@back-end:contents@@"
596 (org-element-map
597 (org-element-parse-buffer) 'export-snippet
598 (lambda (snippet) (cons (org-element-property :back-end snippet)
599 (org-element-property :value snippet)))
600 nil t)))))
603 ;;;; Fixed Width
605 (ert-deftest test-org-element/fixed-width ()
606 "Test fixed-width area parsing."
607 ;; Preserve indentation.
608 (should
609 (org-test-with-temp-text ": no blank\n: one blank"
610 (org-element-map (org-element-parse-buffer) 'fixed-width 'identity)))
611 ;; Fixed-width with empty lines.
612 (should
613 (org-test-with-temp-text ": first part\n:\n: \n: second part"
614 (org-element-map (org-element-parse-buffer) 'fixed-width 'identity)))
615 ;; Parse indented fixed-width markers.
616 (should
617 (org-test-with-temp-text "Text\n : no blank\n : one blank"
618 (org-element-map (org-element-parse-buffer) 'fixed-width 'identity)))
619 ;; Distinguish fixed-width areas within a list and outside of it.
620 (should
621 (= 2
622 (length
623 (org-test-with-temp-text "
624 - Item
625 : fixed-width inside
626 : fixed-width outside"
627 (org-element-map
628 (org-element-parse-buffer) 'fixed-width 'identity))))))
631 ;;;; Footnote Definition
633 (ert-deftest test-org-element/footnote-definition-parser ()
634 "Test `footnote-definition' parser."
635 (should
636 (org-test-with-temp-text "[fn:1] Definition"
637 (org-element-map
638 (org-element-parse-buffer) 'footnote-definition 'identity nil t)))
639 ;; Footnote with more contents
640 (should
641 (= 28
642 (org-element-property
643 :end
644 (org-test-with-temp-text "[fn:1] Definition\n| a | b |"
645 (org-element-map
646 (org-element-parse-buffer)
647 'footnote-definition 'identity nil t))))))
650 ;;;; Footnotes Reference.
652 (ert-deftest test-org-element/footnote-reference-parser ()
653 "Test `footnote-reference' parser."
654 ;; 1. Parse a standard reference.
655 (org-test-with-temp-text "Text[fn:label]"
656 (should
657 (org-element-map
658 (org-element-parse-buffer) 'footnote-reference 'identity)))
659 ;; 2. Parse a normalized reference.
660 (org-test-with-temp-text "Text[1]"
661 (should
662 (org-element-map
663 (org-element-parse-buffer) 'footnote-reference 'identity)))
664 ;; 3. Parse an inline reference.
665 (org-test-with-temp-text "Text[fn:test:def]"
666 (should
667 (org-element-map
668 (org-element-parse-buffer) 'footnote-reference 'identity)))
669 ;; 4. Parse an anonymous reference.
670 (org-test-with-temp-text "Text[fn::def]"
671 (should
672 (org-element-map
673 (org-element-parse-buffer) 'footnote-reference 'identity)))
674 ;; 5. Parse nested footnotes.
675 (org-test-with-temp-text "Text[fn::def [fn:label]]"
676 (should
677 (= 2
678 (length
679 (org-element-map
680 (org-element-parse-buffer) 'footnote-reference 'identity)))))
681 ;; 6. Parse adjacent footnotes.
682 (org-test-with-temp-text "Text[fn:label1][fn:label2]"
683 (should
684 (= 2
685 (length
686 (org-element-map
687 (org-element-parse-buffer) 'footnote-reference 'identity)))))
688 ;; 7. Only properly closed footnotes are recognized as such.
689 (org-test-with-temp-text "Text[fn:label"
690 (should-not
691 (org-element-map
692 (org-element-parse-buffer) 'footnote-reference 'identity))))
695 ;;;; Headline
697 (ert-deftest test-org-element/headline-quote-keyword ()
698 "Test QUOTE keyword recognition."
699 ;; Reference test.
700 (org-test-with-temp-text "* Headline"
701 (let ((org-quote-string "QUOTE"))
702 (should-not (org-element-property :quotedp (org-element-at-point)))))
703 ;; Standard position.
704 (org-test-with-temp-text "* QUOTE Headline"
705 (let ((org-quote-string "QUOTE"))
706 (let ((headline (org-element-at-point)))
707 (should (org-element-property :quotedp headline))
708 ;; Test removal from raw value.
709 (should (equal (org-element-property :raw-value headline) "Headline"))))
710 ;; Case sensitivity.
711 (let ((org-quote-string "Quote"))
712 (should-not (org-element-property :quotedp (org-element-at-point)))))
713 ;; With another keyword.
714 (org-test-with-temp-text "* TODO QUOTE Headline"
715 (let ((org-quote-string "QUOTE")
716 (org-todo-keywords '((sequence "TODO" "DONE"))))
717 (should (org-element-property :quotedp (org-element-at-point))))))
719 (ert-deftest test-org-element/headline-comment-keyword ()
720 "Test COMMENT keyword recognition."
721 ;; Reference test.
722 (org-test-with-temp-text "* Headline"
723 (let ((org-comment-string "COMMENT"))
724 (should-not (org-element-property :commentedp (org-element-at-point)))))
725 ;; Standard position.
726 (org-test-with-temp-text "* COMMENT Headline"
727 (let ((org-comment-string "COMMENT"))
728 (let ((headline (org-element-at-point)))
729 (should (org-element-property :commentedp headline))
730 ;; Test removal from raw value.
731 (should (equal (org-element-property :raw-value headline) "Headline"))))
732 ;; Case sensitivity.
733 (let ((org-comment-string "Comment"))
734 (should-not (org-element-property :commentedp (org-element-at-point)))))
735 ;; With another keyword.
736 (org-test-with-temp-text "* TODO COMMENT Headline"
737 (let ((org-comment-string "COMMENT")
738 (org-todo-keywords '((sequence "TODO" "DONE"))))
739 (should (org-element-property :commentedp (org-element-at-point))))))
741 (ert-deftest test-org-element/headline-archive-tag ()
742 "Test ARCHIVE tag recognition."
743 ;; Reference test.
744 (org-test-with-temp-text "* Headline"
745 (let ((org-archive-tag "ARCHIVE"))
746 (should-not (org-element-property :archivedp (org-element-at-point)))))
747 ;; Single tag.
748 (org-test-with-temp-text "* Headline :ARCHIVE:"
749 (let ((org-archive-tag "ARCHIVE"))
750 (let ((headline (org-element-at-point)))
751 (should (org-element-property :archivedp headline))
752 ;; Test tag removal.
753 (should-not (org-element-property :tags headline))))
754 (let ((org-archive-tag "Archive"))
755 (should-not (org-element-property :archivedp (org-element-at-point)))))
756 ;; Multiple tags.
757 (org-test-with-temp-text "* Headline :test:ARCHIVE:"
758 (let ((org-archive-tag "ARCHIVE"))
759 (let ((headline (org-element-at-point)))
760 (should (org-element-property :archivedp headline))
761 ;; Test tag removal.
762 (should (equal (org-element-property :tags headline) '("test")))))))
765 ;;;; Horizontal Rule
767 (ert-deftest test-org-element/horizontal-rule-parser ()
768 "Test `horizontal-rule' parser."
769 ;; Standard.
770 (should
771 (org-test-with-temp-text "-----"
772 (org-element-map (org-element-parse-buffer) 'horizontal-rule 'identity)))
773 ;; Indented.
774 (should
775 (org-test-with-temp-text " -----"
776 (org-element-map (org-element-parse-buffer) 'horizontal-rule 'identity)))
777 ;; Hyphen must be alone on the line.
778 (should-not
779 (org-test-with-temp-text "-----wrong"
780 (org-element-map (org-element-parse-buffer) 'horizontal-rule 'identity)))
781 ;; 4 hyphens is too small.
782 (should-not
783 (org-test-with-temp-text "----"
784 (org-element-map (org-element-parse-buffer) 'horizontal-rule 'identity))))
787 ;;;; Inline Babel Call
789 (ert-deftest test-org-element/inline-babel-call-parser ()
790 "Test `inline-babel-call' parser."
791 (should
792 (org-test-with-temp-text "call_test()"
793 (org-element-map
794 (org-element-parse-buffer) 'inline-babel-call 'identity))))
797 ;;;; Inline Src Block
799 (ert-deftest test-org-element/inline-src-block-parser ()
800 "Test `inline-src-block' parser."
801 (should
802 (org-test-with-temp-text "src_emacs-lisp{(+ 1 1)}"
803 (org-element-map (org-element-parse-buffer) 'inline-src-block 'identity))))
806 ;;;; Inlinetask
808 (ert-deftest test-org-element/inlinetask-parser ()
809 "Test `inlinetask' parser."
810 (when (featurep 'org-inlinetask)
811 (let ((org-inlinetask-min-level 15))
812 ;; 1. Regular inlinetask.
813 (should
814 (org-test-with-temp-text
815 "*************** Task\nTest\n*************** END"
816 (org-element-map (org-element-parse-buffer) 'inlinetask 'identity)))
817 ;; 2. Degenerate inlinetask.
818 (should
819 (org-test-with-temp-text "*************** Task"
820 (org-element-map (org-element-parse-buffer) 'inlinetask 'identity)))
821 ;; TODO keyword.
822 (should
823 (equal
824 "TODO"
825 (let ((org-todo-keywords '((sequence "TODO" "DONE"))))
826 (org-test-with-temp-text "*************** TODO Task"
827 (org-element-property
828 :todo-keyword
829 (org-element-map
830 (org-element-parse-buffer) 'inlinetask 'identity nil t))))))
831 ;; Planning info.
832 (should
833 (equal
834 "2012-03-29 thu."
835 (org-test-with-temp-text "
836 *************** Task
837 DEADLINE: <2012-03-29 thu.>"
838 (org-element-property
839 :deadline
840 (org-element-map
841 (org-element-parse-buffer) 'inlinetask 'identity nil t)))))
842 ;; Priority.
843 (should
844 (equal
846 (org-test-with-temp-text "
847 *************** [#A] Task"
848 (org-element-property
849 :priority
850 (org-element-map
851 (org-element-parse-buffer) 'inlinetask 'identity nil t)))))
852 ;; Tags.
853 (should
854 (equal
855 '("test")
856 (org-test-with-temp-text "
857 *************** Task :test:"
858 (org-element-property
859 :tags
860 (org-element-map
861 (org-element-parse-buffer) 'inlinetask 'identity nil t))))))))
864 ;;;; Italic
866 (ert-deftest test-org-element/italic-parser ()
867 "Test `italic' parser."
868 ;; Regular test.
869 (should
870 (let ((org-emph-re "\\([ ('\"{]\\|^\\)\\(\\([+*/_=~]\\)\\([^ \n,\"']\\|[^ \n,\"'].*?\\(?:\n.*?\\)\\{0,1\\}[^ \n,\"']\\)\\3\\)\\([- .,:!?;'\")}\\]\\|$\\)"))
871 (org-test-with-temp-text "/italic/"
872 (org-element-map (org-element-parse-buffer) 'italic 'identity nil t))))
873 ;; Multi-line markup.
874 (should
875 (equal
876 (org-element-contents
877 (let ((org-emph-re "\\([ ('\"{]\\|^\\)\\(\\([+*/_=~]\\)\\([^ \n,\"']\\|[^ \n,\"'].*?\\(?:\n.*?\\)\\{0,1\\}[^ \n,\"']\\)\\3\\)\\([- .,:!?;'\")}\\]\\|$\\)"))
878 (org-test-with-temp-text "/first line\nsecond line/"
879 (org-element-map (org-element-parse-buffer) 'italic 'identity nil t))))
880 '("first line\nsecond line"))))
883 ;;;; Item
885 (ert-deftest test-org-element/item-parser ()
886 "Test `item' parser."
887 ;; Standard test.
888 (should
889 (org-test-with-temp-text "- item"
890 (org-element-map (org-element-parse-buffer) 'item 'identity)))
891 ;; Counter.
892 (should
893 (= 6
894 (org-element-property
895 :counter
896 (org-test-with-temp-text "6. [@6] item"
897 (org-element-map (org-element-parse-buffer) 'item 'identity nil t)))))
898 ;; Tag
899 (should
900 (equal
901 '("tag")
902 (org-element-property
903 :tag
904 (org-test-with-temp-text "- tag :: description"
905 (org-element-map (org-element-parse-buffer) 'item 'identity nil t)))))
906 ;; Check-boxes
907 (should
908 (equal
909 '(trans on off)
910 (org-test-with-temp-text "
911 - [-] item 1
912 - [X] item 1.1
913 - [ ] item 1.2"
914 (org-element-map
915 (org-element-parse-buffer) 'item
916 (lambda (item) (org-element-property :checkbox item))))))
917 ;; Folded state.
918 (org-test-with-temp-text "* Headline
919 - item
921 paragraph below"
922 (forward-line)
923 (let ((org-cycle-include-plain-lists t)) (org-cycle))
924 (should
925 (org-element-property
926 :hiddenp
927 (org-element-map (org-element-parse-buffer) 'item 'identity nil t)))))
930 ;;;; Keyword
932 (ert-deftest test-org-element/keyword-parser ()
933 "Test `keyword' parser."
934 ;; Standard test.
935 (should
936 (org-test-with-temp-text "#+KEYWORD: value"
937 (org-element-map (org-element-parse-buffer) 'keyword 'identity)))
938 ;; Keywords are case-insensitive.
939 (should
940 (org-test-with-temp-text "#+keyword: value"
941 (org-element-map (org-element-parse-buffer) 'keyword 'identity)))
942 ;; Affiliated keywords are not keywords.
943 (should-not
944 (org-test-with-temp-text "#+NAME: value
945 Paragraph"
946 (org-element-map (org-element-parse-buffer) 'keyword 'identity)))
947 ;; Do not mix keywords with Babel calls and dynamic blocks.
948 (should-not
949 (org-test-with-temp-text "#+CALL: fun()"
950 (org-element-map (org-element-parse-buffer) 'keyword 'identity)))
951 (should-not
952 (org-test-with-temp-text "#+BEGIN: my-fun\nBody\n#+END:"
953 (org-element-map (org-element-parse-buffer) 'keyword 'identity))))
956 ;;;; Latex Environment
958 (ert-deftest test-org-element/latex-environment-parser ()
959 "Test `latex-environment' parser."
960 (should
961 (org-test-with-temp-text "\\begin{equation}\ne^{i\\pi}+1=0\n\\end{equation}"
962 (org-element-map
963 (org-element-parse-buffer) 'latex-environment 'identity)))
964 ;; Allow nested environments.
965 (should
966 (equal
967 "\\begin{outer}
968 \\begin{inner}
969 e^{i\\pi}+1=0
970 \\end{inner}
971 \\end{outer}"
972 (org-test-with-temp-text "
973 \\begin{outer}
974 \\begin{inner}
975 e^{i\\pi}+1=0
976 \\end{inner}
977 \\end{outer}"
978 (org-element-property
979 :value
980 (org-element-map
981 (org-element-parse-buffer) 'latex-environment 'identity nil t))))))
984 ;;;; Latex Fragment
986 (ert-deftest test-org-element/latex-fragment-parser ()
987 "Test `latex-fragment' parser."
988 (let ((org-latex-regexps
989 '(("begin" "^[ ]*\\(\\\\begin{\\([a-zA-Z0-9\\*]+\\)[^