org-element: Add :parent text property to strings in parse tree
[org-mode.git] / testing / lisp / test-org-element.el
blob70a263dcd03e0e0aab9460ea4fbd02c4fc691ce5
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)))
65 ;; Use WITH-AFFILIATED argument.
66 (should
67 (equal
68 '("a" "1" "b" "2")
69 (org-test-with-temp-text "#+CAPTION[a]: 1\n#+CAPTION[b]: 2\nParagraph"
70 (org-element-map
71 (org-element-at-point) 'plain-text 'identity nil nil nil t)))))
75 ;;; Test Setters
77 (ert-deftest test-org-element/put-property ()
78 "Test `org-element-put-property' specifications."
79 ;; Standard test.
80 (org-test-with-temp-text "* Headline\n *a*"
81 (let ((tree (org-element-parse-buffer)))
82 (org-element-put-property
83 (org-element-map tree 'bold 'identity nil t) :test 1)
84 (should (org-element-property
85 :test (org-element-map tree 'bold 'identity nil t)))))
86 ;; Put property on a string.
87 (should
88 (org-element-property :test (org-element-put-property "Paragraph" :test t))))
90 (ert-deftest test-org-element/set-contents ()
91 "Test `org-element-set-contents' specifications."
92 ;; Accept multiple entries.
93 (should
94 (equal '("b" (italic nil "a"))
95 (org-test-with-temp-text "* Headline\n *a*"
96 (let ((tree (org-element-parse-buffer)))
97 (org-element-set-contents
98 (org-element-map tree 'bold 'identity nil t) "b" '(italic nil "a"))
99 (org-element-contents
100 (org-element-map tree 'bold 'identity nil t))))))
101 ;; Accept atoms and elements.
102 (should
103 (equal '("b")
104 (org-test-with-temp-text "* Headline\n *a*"
105 (let ((tree (org-element-parse-buffer)))
106 (org-element-set-contents
107 (org-element-map tree 'bold 'identity nil t) "b")
108 (org-element-contents
109 (org-element-map tree 'bold 'identity nil t))))))
110 (should
111 (equal '((italic nil "b"))
112 (org-test-with-temp-text "* Headline\n *a*"
113 (let ((tree (org-element-parse-buffer)))
114 (org-element-set-contents
115 (org-element-map tree 'bold 'identity nil t) '(italic nil "b"))
116 (org-element-contents
117 (org-element-map tree 'bold 'identity nil t))))))
118 ;; Allow nil contents.
119 (should-not
120 (org-test-with-temp-text "* Headline\n *a*"
121 (let ((tree (org-element-parse-buffer)))
122 (org-element-set-contents (org-element-map tree 'bold 'identity nil t))
123 (org-element-contents (org-element-map tree 'bold 'identity nil t))))))
125 (ert-deftest test-org-element/set-element ()
126 "Test `org-element-set-element' specifications."
127 (org-test-with-temp-text "* Headline\n*a*"
128 (let ((tree (org-element-parse-buffer)))
129 (org-element-set-element
130 (org-element-map tree 'bold 'identity nil t)
131 '(italic nil "b"))
132 ;; Check if object is correctly replaced.
133 (should (org-element-map tree 'italic 'identity))
134 (should-not (org-element-map tree 'bold 'identity))
135 ;; Check if new object's parent is correctly set.
136 (should
138 (org-element-property :parent
139 (org-element-map tree 'italic 'identity nil t))
140 (org-element-map tree 'paragraph 'identity nil t))))))
142 (ert-deftest test-org-element/adopt-elements ()
143 "Test `org-element-adopt-elements' specifications."
144 ;; Adopt an element.
145 (should
146 (equal '(plain-text italic)
147 (org-test-with-temp-text "* Headline\n *a*"
148 (let ((tree (org-element-parse-buffer)))
149 (org-element-adopt-elements
150 (org-element-map tree 'bold 'identity nil t) '(italic nil "a"))
151 (mapcar (lambda (blob) (org-element-type blob))
152 (org-element-contents
153 (org-element-map tree 'bold 'identity nil t)))))))
154 ;; Adopt a string.
155 (should
156 (equal '("a" "b")
157 (org-test-with-temp-text "* Headline\n *a*"
158 (let ((tree (org-element-parse-buffer)))
159 (org-element-adopt-elements
160 (org-element-map tree 'bold 'identity nil t) "b")
161 (org-element-contents
162 (org-element-map tree 'bold 'identity nil t)))))))
166 ;;; Test Parsers
168 ;;;; Affiliated Keywords
170 (ert-deftest test-org-element/affiliated-keywords-parser ()
171 "Test affiliated keywords parsing."
172 ;; Read simple keywords.
173 (should
174 (equal "para"
175 (org-element-property
176 :name
177 (org-test-with-temp-text "#+NAME: para\nParagraph"
178 (org-element-at-point)))))
179 (should
180 (= 1
181 (org-element-property
182 :begin
183 (org-test-with-temp-text "#+NAME: para\nParagraph"
184 (org-element-at-point)))))
185 ;; Parse multiple keywords.
186 (should
187 (equal
188 '("line2" "line1")
189 (org-element-property
190 :attr_ascii
191 (org-test-with-temp-text
192 "#+ATTR_ASCII: line1\n#+ATTR_ASCII: line2\nParagraph"
193 (org-element-at-point)))))
194 ;; Parse "parsed" keywords.
195 (should
196 (equal
197 '(("caption"))
198 (org-test-with-temp-text "#+CAPTION: caption\nParagraph"
199 (car (org-element-property :caption (org-element-at-point))))))
200 ;; Parse dual keywords.
201 (should
202 (equal
203 '((("long") "short"))
204 (org-test-with-temp-text "#+CAPTION[short]: long\nParagraph"
205 (org-element-property :caption (org-element-at-point)))))
206 ;; Allow multiple caption keywords.
207 (should
208 (equal
209 '((("l2") "s2") (("l1") "s1"))
210 (org-test-with-temp-text "#+CAPTION[s1]: l1\n#+CAPTION[s2]: l2\nParagraph"
211 (org-element-property :caption (org-element-at-point))))))
214 ;;;; Babel Call
216 (ert-deftest test-org-element/babel-call-parser ()
217 "Test `babel-call' parsing."
218 ;; Standard test.
219 (should
220 (org-test-with-temp-text "#+CALL: test()"
221 (org-element-map (org-element-parse-buffer) 'babel-call 'identity)))
222 ;; Ignore case.
223 (should
224 (org-test-with-temp-text "#+call: test()"
225 (org-element-map (org-element-parse-buffer) 'babel-call 'identity))))
228 ;;;; Bold
230 (ert-deftest test-org-element/bold-parser ()
231 "Test `bold' parser."
232 ;; Standard test.
233 (should
234 (let ((org-emph-re "\\([ ('\"{]\\|^\\)\\(\\([+*/_=~]\\)\\([^ \n,\"']\\|[^ \n,\"'].*?\\(?:\n.*?\\)\\{0,1\\}[^ \n,\"']\\)\\3\\)\\([- .,:!?;'\")}\\]\\|$\\)"))
235 (org-test-with-temp-text "*bold*"
236 (org-element-map (org-element-parse-buffer) 'bold 'identity nil t))))
237 ;; Multi-line markup.
238 (should
239 (equal
240 (org-element-contents
241 (let ((org-emph-re "\\([ ('\"{]\\|^\\)\\(\\([+*/_=~]\\)\\([^ \n,\"']\\|[^ \n,\"'].*?\\(?:\n.*?\\)\\{0,1\\}[^ \n,\"']\\)\\3\\)\\([- .,:!?;'\")}\\]\\|$\\)"))
242 (org-test-with-temp-text "*first line\nsecond line*"
243 (org-element-map (org-element-parse-buffer) 'bold 'identity nil t))))
244 '("first line\nsecond line"))))
247 ;;;; Center Block
249 (ert-deftest test-org-element/center-block-parser ()
250 "Test `center-block' parser."
251 ;; Standard test.
252 (should
253 (org-test-with-temp-text "#+BEGIN_CENTER\nText\n#+END_CENTER"
254 (org-element-map (org-element-parse-buffer) 'center-block 'identity)))
255 ;; Ignore case.
256 (should
257 (org-test-with-temp-text "#+begin_center\nText\n#+end_center"
258 (org-element-map (org-element-parse-buffer) 'center-block 'identity)))
259 ;; Test folded block.
260 (org-test-with-temp-text "#+BEGIN_CENTER\nText\n#+END_CENTER"
261 (org-cycle)
262 (should
263 (org-element-property
264 :hiddenp
265 (org-element-map
266 (org-element-parse-buffer) 'center-block 'identity nil t))))
267 ;; Ignore incomplete block.
268 (should-not
269 (org-test-with-temp-text "#+BEGIN_CENTER"
270 (org-element-map
271 (org-element-parse-buffer) 'center-block 'identity nil t))))
274 ;;;; Clock
276 (ert-deftest test-org-element/clock-parser ()
277 "Test `clock' parser."
278 ;; Running clock.
279 (let* ((org-clock-string "CLOCK:")
280 (clock (org-test-with-temp-text "CLOCK: [2012-01-01 sun. 00:01]"
281 (org-element-map
282 (org-element-parse-buffer) 'clock 'identity nil t))))
283 (should (eq (org-element-property :status clock) 'running))
284 (should (equal (org-element-property :value clock)
285 "[2012-01-01 sun. 00:01]"))
286 (should-not (org-element-property :time clock)))
287 ;; Closed clock.
288 (let* ((org-clock-string "CLOCK:")
289 (clock (org-test-with-temp-text "
290 CLOCK: [2012-01-01 sun. 00:01]--[2012-01-01 sun. 00:02] => 0:01"
291 (org-element-map
292 (org-element-parse-buffer) 'clock 'identity nil t))))
293 (should (eq (org-element-property :status clock) 'closed))
294 (should (equal (org-element-property :value clock)
295 "[2012-01-01 sun. 00:01]--[2012-01-01 sun. 00:02]"))
296 (should (equal (org-element-property :time clock) "0:01"))))
299 ;;;; Code
301 (ert-deftest test-org-element/code-parser ()
302 "Test `code' parser."
303 ;; Regular test.
304 (should
305 (let ((org-emph-re "\\([ ('\"{]\\|^\\)\\(\\([+*/_=~]\\)\\([^ \n,\"']\\|[^ \n,\"'].*?\\(?:\n.*?\\)\\{0,1\\}[^ \n,\"']\\)\\3\\)\\([- .,:!?;'\")}\\]\\|$\\)"))
306 (org-test-with-temp-text "~code~"
307 (org-element-map (org-element-parse-buffer) 'code 'identity))))
308 ;; Multi-line markup.
309 (should
310 (equal
311 (org-element-property
312 :value
313 (let ((org-emph-re "\\([ ('\"{]\\|^\\)\\(\\([+*/_=~]\\)\\([^ \n,\"']\\|[^ \n,\"'].*?\\(?:\n.*?\\)\\{0,1\\}[^ \n,\"']\\)\\3\\)\\([- .,:!?;'\")}\\]\\|$\\)"))
314 (org-test-with-temp-text "~first line\nsecond line~"
315 (org-element-map
316 (org-element-parse-buffer) 'code 'identity nil t))))
317 "first line\nsecond line")))
320 ;;;; Comment
322 (ert-deftest test-org-element/comment-parser ()
323 "Test `comment' parser."
324 ;; Regular comment.
325 (should
326 (org-test-with-temp-text "# Comment"
327 (org-element-map (org-element-parse-buffer) 'comment 'identity)))
328 ;; Inline comment.
329 (should
330 (org-test-with-temp-text " # Comment"
331 (org-element-map (org-element-parse-buffer) 'comment 'identity)))
332 ;; Preserve indentation.
333 (should
334 (equal
335 (org-element-property
336 :value
337 (org-test-with-temp-text "# No blank\n# One blank"
338 (org-element-map (org-element-parse-buffer) 'comment 'identity nil t)))
339 "No blank\n One blank"))
340 ;; Comment with blank lines.
341 (should
342 (equal
343 (org-element-property
344 :value
345 (org-test-with-temp-text "# First part\n# \n#\n# Second part"
346 (org-element-map (org-element-parse-buffer) 'comment 'identity nil t)))
347 "First part\n\n\nSecond part"))
348 ;; Do not mix comments and keywords.
349 (should
350 (eq 1
351 (org-test-with-temp-text "#+keyword: value\n# comment\n#+keyword: value"
352 (length (org-element-map
353 (org-element-parse-buffer) 'comment 'identity)))))
354 (should
355 (equal "comment"
356 (org-test-with-temp-text "#+keyword: value\n# comment\n#+keyword: value"
357 (org-element-property
358 :value
359 (org-element-map
360 (org-element-parse-buffer) 'comment 'identity nil t))))))
363 ;;;; Comment Block
365 (ert-deftest test-org-element/comment-block-parser ()
366 "Test `comment-block' parser."
367 ;; Standard test.
368 (should
369 (org-test-with-temp-text "#+BEGIN_COMMENT\nText\n#+END_COMMENT"
370 (org-element-map
371 (org-element-parse-buffer) 'comment-block 'identity)))
372 ;; Ignore case.
373 (should
374 (org-test-with-temp-text "#+begin_comment\nText\n#+end_comment"
375 (org-element-map
376 (org-element-parse-buffer) 'comment-block 'identity)))
377 ;; Test folded block.
378 (org-test-with-temp-text "#+BEGIN_COMMENT\nText\n#+END_COMMENT"
379 (org-cycle)
380 (should
381 (org-element-property
382 :hiddenp
383 (org-element-map
384 (org-element-parse-buffer) 'comment-block 'identity nil t))))
385 ;; Ignore incomplete block.
386 (should-not
387 (org-test-with-temp-text "#+BEGIN_COMMENT"
388 (org-element-map
389 (org-element-parse-buffer) 'comment-block 'identity nil t))))
392 ;;;; Drawer
394 (ert-deftest test-org-element/drawer-parser ()
395 "Test `drawer' parser."
396 ;; Standard test.
397 (should
398 (let ((org-drawers '("TEST")))
399 (org-test-with-temp-text ":TEST:\nText\n:END:"
400 (org-element-map (org-element-parse-buffer) 'drawer 'identity))))
401 ;; Do not mix regular drawers and property drawers.
402 (should-not
403 (let ((org-drawers '("PROPERTIES")))
404 (org-test-with-temp-text ":PROPERTIES:\n:prop: value\n:END:"
405 (org-element-map
406 (org-element-parse-buffer) 'drawer 'identity nil t))))
407 ;; Ignore incomplete drawer.
408 (should-not
409 (let ((org-drawers '("TEST")))
410 (org-test-with-temp-text ":TEST:"
411 (org-element-map
412 (org-element-parse-buffer) 'drawer 'identity nil t)))))
415 ;;;; Dynamic Block
417 (ert-deftest test-org-element/dynamic-block-parser ()
418 "Test `dynamic-block' parser."
419 ;; Standard test.
420 (should
421 (org-test-with-temp-text
422 "#+BEGIN: myblock :param1 val1 :param2 val2\nText\n#+END:"
423 (org-element-map (org-element-parse-buffer) 'dynamic-block 'identity)))
424 ;; Folded view
425 (org-test-with-temp-text
426 "#+BEGIN: myblock :param1 val1 :param2 val2\nText\n#+END:"
427 (org-cycle)
428 (should
429 (org-element-property
430 :hiddenp
431 (org-element-map
432 (org-element-parse-buffer) 'dynamic-block 'identity nil t))))
433 ;; Ignore case.
434 (should
435 (org-test-with-temp-text
436 "#+begin: myblock :param1 val1 :param2 val2\nText\n#+end:"
437 (org-element-map (org-element-parse-buffer) 'dynamic-block 'identity)))
438 ;; Ignore incomplete block.
439 (should-not
440 (org-test-with-temp-text "#+BEGIN: myblock :param1 val1 :param2 val2"
441 (org-element-map
442 (org-element-parse-buffer) 'dynamic-block 'identity nil t))))
445 ;;;; Entity
447 (ert-deftest test-org-element/entity-parser ()
448 "Test `entity' parser."
449 ;; Without brackets.
450 (should
451 (org-test-with-temp-text "\\sin"
452 (org-element-map (org-element-parse-buffer) 'entity 'identity)))
453 ;; With brackets.
454 (should
455 (org-element-property
456 :use-brackets-p
457 (org-test-with-temp-text "\\alpha{}text"
458 (org-element-map (org-element-parse-buffer) 'entity 'identity nil t))))
459 ;; User-defined entity.
460 (should
461 (equal
462 (org-element-property
463 :name
464 (let ((org-entities-user
465 '(("test" "test" nil "test" "test" "test" "test"))))
466 (org-test-with-temp-text "\\test"
467 (org-element-map (org-element-parse-buffer) 'entity 'identity nil t))))
468 "test")))
471 ;;;; Example Block
473 (ert-deftest test-org-element/example-block-parser ()
474 "Test `example-block' parser."
475 ;; Standard test.
476 (should
477 (org-test-with-temp-text "#+BEGIN_EXAMPLE\nText\n#+END_EXAMPLE"
478 (org-element-map (org-element-parse-buffer) 'example-block 'identity)))
479 ;; Test folded block.
480 (org-test-with-temp-text "#+BEGIN_EXAMPLE\nText\n#+END_EXAMPLE"
481 (org-cycle)
482 (should
483 (org-element-property
484 :hiddenp
485 (org-element-map
486 (org-element-parse-buffer) 'example-block 'identity nil t))))
487 ;; Ignore incomplete block.
488 (should-not
489 (org-test-with-temp-text "#+BEGIN_EXAMPLE"
490 (org-element-map
491 (org-element-parse-buffer) 'example-block 'identity nil t)))
492 ;; Properly un-escape code.
493 (should
494 (equal "* Headline\n #+keyword\nText\n"
495 (org-test-with-temp-text
496 "#+BEGIN_EXAMPLE\n,* Headline\n ,#+keyword\nText\n#+END_EXAMPLE"
497 (org-element-property :value (org-element-at-point))))))
499 (ert-deftest test-org-element/block-switches ()
500 "Test `example-block' and `src-block' switches parsing."
501 (let ((org-coderef-label-format "(ref:%s)"))
502 ;; 1. Test "-i" switch.
503 (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp\n(+ 1 1)\n#+END_SRC"
504 (should-not
505 (org-element-property :preserve-indent (org-element-at-point))))
506 (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp -i\n(+ 1 1)\n#+END_SRC"
507 (should (org-element-property :preserve-indent (org-element-at-point))))
508 (org-test-with-temp-text "#+BEGIN_EXAMPLE\nText.\n#+END_EXAMPLE"
509 (should-not
510 (org-element-property :preserve-indent (org-element-at-point))))
511 (org-test-with-temp-text "#+BEGIN_EXAMPLE -i\nText.\n#+END_EXAMPLE"
512 (should (org-element-property :preserve-indent (org-element-at-point))))
513 ;; 2. "-n -r -k" combination should number lines, retain labels but
514 ;; not use them in coderefs.
515 (org-test-with-temp-text "#+BEGIN_EXAMPLE -n -r -k\nText.\n#+END_EXAMPLE"
516 (let ((element (org-element-at-point)))
517 (should (and (org-element-property :number-lines element)
518 (org-element-property :retain-labels element)
519 (not (org-element-property :use-labels element))))))
520 (org-test-with-temp-text
521 "#+BEGIN_SRC emacs-lisp -n -r -k\n(+ 1 1)\n#+END_SRC"
522 (let ((element (org-element-at-point)))
523 (should (and (org-element-property :number-lines element)
524 (org-element-property :retain-labels element)
525 (not (org-element-property :use-labels element))))))
526 ;; 3. "-n -r" combination should number-lines remove labels and not
527 ;; use them in coderefs.
528 (org-test-with-temp-text "#+BEGIN_EXAMPLE -n -r\nText.\n#+END_EXAMPLE"
529 (let ((element (org-element-at-point)))
530 (should (and (org-element-property :number-lines element)
531 (not (org-element-property :retain-labels element))
532 (not (org-element-property :use-labels element))))))
533 (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp -n -r\n(+ 1 1)\n#+END_SRC"
534 (let ((element (org-element-at-point)))
535 (should (and (org-element-property :number-lines element)
536 (not (org-element-property :retain-labels element))
537 (not (org-element-property :use-labels element))))))
538 ;; 4. "-n" or "+n" should number lines, retain labels and use them
539 ;; in coderefs.
540 (org-test-with-temp-text "#+BEGIN_EXAMPLE -n\nText.\n#+END_EXAMPLE"
541 (let ((element (org-element-at-point)))
542 (should (and (org-element-property :number-lines element)
543 (org-element-property :retain-labels element)
544 (org-element-property :use-labels element)))))
545 (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp -n\n(+ 1 1)\n#+END_SRC"
546 (let ((element (org-element-at-point)))
547 (should (and (org-element-property :number-lines element)
548 (org-element-property :retain-labels element)
549 (org-element-property :use-labels element)))))
550 (org-test-with-temp-text "#+BEGIN_EXAMPLE +n\nText.\n#+END_EXAMPLE"
551 (let ((element (org-element-at-point)))
552 (should (and (org-element-property :number-lines element)
553 (org-element-property :retain-labels element)
554 (org-element-property :use-labels element)))))
555 (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp +n\n(+ 1 1)\n#+END_SRC"
556 (let ((element (org-element-at-point)))
557 (should (and (org-element-property :number-lines element)
558 (org-element-property :retain-labels element)
559 (org-element-property :use-labels element)))))
560 ;; 5. No switch should not number lines, but retain labels and use
561 ;; them in coderefs.
562 (org-test-with-temp-text "#+BEGIN_EXAMPLE\nText.\n#+END_EXAMPLE"
563 (let ((element (org-element-at-point)))
564 (should (and (not (org-element-property :number-lines element))
565 (org-element-property :retain-labels element)
566 (org-element-property :use-labels element)))))
567 (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp\n(+ 1 1)\n#+END_SRC"
568 (let ((element (org-element-at-point)))
569 (should (and (not (org-element-property :number-lines element))
570 (org-element-property :retain-labels element)
571 (org-element-property :use-labels element)))))
572 ;; 6. "-r" switch only: do not number lines, remove labels, and
573 ;; don't use labels in coderefs.
574 (org-test-with-temp-text "#+BEGIN_EXAMPLE -r\nText.\n#+END_EXAMPLE"
575 (let ((element (org-element-at-point)))
576 (should (and (not (org-element-property :number-lines element))
577 (not (org-element-property :retain-labels element))
578 (not (org-element-property :use-labels element))))))
579 (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp -r\n(+ 1 1)\n#+END_SRC"
580 (let ((element (org-element-at-point)))
581 (should (and (not (org-element-property :number-lines element))
582 (not (org-element-property :retain-labels element))
583 (not (org-element-property :use-labels element))))))
584 ;; 7. Recognize coderefs with user-defined syntax.
585 (org-test-with-temp-text
586 "#+BEGIN_EXAMPLE -l \"[ref:%s]\"\nText [ref:text]\n#+END_EXAMPLE"
587 (let ((element (org-element-at-point)))
588 (should
589 (equal (org-element-property :label-fmt element) "[ref:%s]"))))
590 (org-test-with-temp-text
591 "#+BEGIN_SRC emacs-lisp -l \"[ref:%s]\"\n(+ 1 1) [ref:text]\n#+END_SRC"
592 (let ((element (org-element-at-point)))
593 (should
594 (equal (org-element-property :label-fmt element) "[ref:%s]"))))))
597 ;;;; Export Block
599 (ert-deftest test-org-element/export-block-parser ()
600 "Test `export-block' parser."
601 ;; Standard test.
602 (should
603 (org-test-with-temp-text "#+BEGIN_LATEX\nText\n#+END_LATEX"
604 (org-element-map
605 (let ((org-element-block-name-alist
606 '(("LATEX" . org-element-export-block-parser))))
607 (org-element-parse-buffer))
608 'export-block 'identity)))
609 ;; Test folded block.
610 (org-test-with-temp-text "#+BEGIN_LATEX\nText\n#+END_LATEX"
611 (org-cycle)
612 (should
613 (org-element-property
614 :hiddenp
615 (org-element-map
616 (let ((org-element-block-name-alist
617 '(("LATEX" . org-element-export-block-parser))))
618 (org-element-parse-buffer))
619 'export-block 'identity nil t))))
620 ;; Ignore case.
621 (should
622 (org-test-with-temp-text "#+begin_latex\nText\n#+end_latex"
623 (org-element-map
624 (let ((org-element-block-name-alist
625 '(("LATEX" . org-element-export-block-parser))))
626 (org-element-parse-buffer))
627 'export-block 'identity)))
628 ;; Ignore incomplete block.
629 (should-not
630 (org-test-with-temp-text "#+BEGIN_LATEX"
631 (org-element-map
632 (let ((org-element-block-name-alist
633 '(("LATEX" . org-element-export-block-parser))))
634 (org-element-parse-buffer))
635 'export-block 'identity nil t))))
638 ;;;; Export Snippet
640 (ert-deftest test-org-element/export-snippet-parser ()
641 "Test `export-snippet' parser."
642 (should
643 (equal
644 '("back-end" . "contents")
645 (org-test-with-temp-text "@@back-end:contents@@"
646 (org-element-map
647 (org-element-parse-buffer) 'export-snippet
648 (lambda (snippet) (cons (org-element-property :back-end snippet)
649 (org-element-property :value snippet)))
650 nil t)))))
653 ;;;; Fixed Width
655 (ert-deftest test-org-element/fixed-width ()
656 "Test fixed-width area parsing."
657 ;; Preserve indentation.
658 (should
659 (org-test-with-temp-text ": no blank\n: one blank"
660 (org-element-map (org-element-parse-buffer) 'fixed-width 'identity)))
661 ;; Fixed-width with empty lines.
662 (should
663 (org-test-with-temp-text ": first part\n:\n: \n: second part"
664 (org-element-map (org-element-parse-buffer) 'fixed-width 'identity)))
665 ;; Parse indented fixed-width markers.
666 (should
667 (org-test-with-temp-text "Text\n : no blank\n : one blank"
668 (org-element-map (org-element-parse-buffer) 'fixed-width 'identity)))
669 ;; Distinguish fixed-width areas within a list and outside of it.
670 (should
671 (= 2
672 (length
673 (org-test-with-temp-text "
674 - Item
675 : fixed-width inside
676 : fixed-width outside"
677 (org-element-map
678 (org-element-parse-buffer) 'fixed-width 'identity))))))
681 ;;;; Footnote Definition
683 (ert-deftest test-org-element/footnote-definition-parser ()
684 "Test `footnote-definition' parser."
685 (should
686 (org-test-with-temp-text "[fn:1] Definition"
687 (org-element-map
688 (org-element-parse-buffer) 'footnote-definition 'identity nil t)))
689 ;; Footnote with more contents
690 (should
691 (= 28
692 (org-element-property
693 :end
694 (org-test-with-temp-text "[fn:1] Definition\n| a | b |"
695 (org-element-map
696 (org-element-parse-buffer)
697 'footnote-definition 'identity nil t)))))
698 ;; Footnote starting with special syntax.
699 (should-not
700 (org-test-with-temp-text "[fn:1] - no item"
701 (org-element-map (org-element-parse-buffer) 'item 'identity))))
704 ;;;; Footnotes Reference.
706 (ert-deftest test-org-element/footnote-reference-parser ()
707 "Test `footnote-reference' parser."
708 ;; 1. Parse a standard reference.
709 (org-test-with-temp-text "Text[fn:label]"
710 (should
711 (org-element-map
712 (org-element-parse-buffer) 'footnote-reference 'identity)))
713 ;; 2. Parse a normalized reference.
714 (org-test-with-temp-text "Text[1]"
715 (should
716 (org-element-map
717 (org-element-parse-buffer) 'footnote-reference 'identity)))
718 ;; 3. Parse an inline reference.
719 (org-test-with-temp-text "Text[fn:test:def]"
720 (should
721 (org-element-map
722 (org-element-parse-buffer) 'footnote-reference 'identity)))
723 ;; 4. Parse an anonymous reference.
724 (org-test-with-temp-text "Text[fn::def]"
725 (should
726 (org-element-map
727 (org-element-parse-buffer) 'footnote-reference 'identity)))
728 ;; 5. Parse nested footnotes.
729 (org-test-with-temp-text "Text[fn::def [fn:label]]"
730 (should
731 (= 2
732 (length
733 (org-element-map
734 (org-element-parse-buffer) 'footnote-reference 'identity)))))
735 ;; 6. Parse adjacent footnotes.
736 (org-test-with-temp-text "Text[fn:label1][fn:label2]"
737 (should
738 (= 2
739 (length
740 (org-element-map
741 (org-element-parse-buffer) 'footnote-reference 'identity)))))
742 ;; 7. Only properly closed footnotes are recognized as such.
743 (org-test-with-temp-text "Text[fn:label"
744 (should-not
745 (org-element-map
746 (org-element-parse-buffer) 'footnote-reference 'identity))))
749 ;;;; Headline
751 (ert-deftest test-org-element/headline-quote-keyword ()
752 "Test QUOTE keyword recognition."
753 ;; Reference test.
754 (org-test-with-temp-text "* Headline"
755 (let ((org-quote-string "QUOTE"))
756 (should-not (org-element-property :quotedp (org-element-at-point)))))
757 ;; Standard position.
758 (org-test-with-temp-text "* QUOTE Headline"
759 (let* ((org-quote-string "QUOTE")
760 (headline (org-element-at-point)))
761 (should (org-element-property :quotedp headline))
762 ;; Test removal from raw value.
763 (should (equal (org-element-property :raw-value headline) "Headline"))))
764 ;; Case sensitivity.
765 (org-test-with-temp-text "* QUOTE Headline"
766 (let* ((org-quote-string "Quote")
767 (headline (org-element-at-point)))
768 (should-not (org-element-property :quotedp headline))
769 (should (equal (org-element-property :raw-value headline)
770 "QUOTE Headline"))))
771 ;; With another keyword.
772 (org-test-with-temp-text "* TODO QUOTE Headline"
773 (let* ((org-quote-string "QUOTE")
774 (org-todo-keywords '((sequence "TODO" "DONE")))
775 (headline (org-element-at-point)))
776 (should (org-element-property :quotedp headline))
777 (should (equal (org-element-property :raw-value headline) "Headline"))))
778 ;; With the keyword only.
779 (org-test-with-temp-text "* QUOTE"
780 (let* ((org-quote-string "QUOTE")
781 (headline (org-element-at-point)))
782 (should (org-element-property :quotedp headline))
783 (should (equal (org-element-property :raw-value headline) "")))))
785 (ert-deftest test-org-element/headline-comment-keyword ()
786 "Test COMMENT keyword recognition."
787 ;; Reference test.
788 (org-test-with-temp-text "* Headline"
789 (let ((org-comment-string "COMMENT"))
790 (should-not (org-element-property :commentedp (org-element-at-point)))))
791 ;; Standard position.
792 (org-test-with-temp-text "* COMMENT Headline"
793 (let ((org-comment-string "COMMENT")
794 (headline (org-element-at-point)))
795 (should (org-element-property :commentedp headline))
796 (should (equal (org-element-property :raw-value headline) "Headline"))))
797 ;; Case sensitivity.
798 (org-test-with-temp-text "* COMMENT Headline"
799 (let* ((org-comment-string "Comment")
800 (headline (org-element-at-point)))
801 (should-not (org-element-property :commentedp headline))
802 (should (equal (org-element-property :raw-value headline)
803 "COMMENT Headline"))))
804 ;; With another keyword.
805 (org-test-with-temp-text "* TODO COMMENT Headline"
806 (let* ((org-comment-string "COMMENT")
807 (org-todo-keywords '((sequence "TODO" "DONE")))
808 (headline (org-element-at-point)))
809 (should (org-element-property :commentedp headline))
810 (should (equal (org-element-property :raw-value headline) "Headline"))))
811 ;; With the keyword only.
812 (org-test-with-temp-text "* COMMENT"
813 (let* ((org-comment-string "COMMENT")
814 (headline (org-element-at-point)))
815 (should (org-element-property :commentedp headline))
816 (should (equal (org-element-property :raw-value headline) "")))))
818 (ert-deftest test-org-element/headline-archive-tag ()
819 "Test ARCHIVE tag recognition."
820 ;; Reference test.
821 (org-test-with-temp-text "* Headline"
822 (let ((org-archive-tag "ARCHIVE"))
823 (should-not (org-element-property :archivedp (org-element-at-point)))))
824 ;; Single tag.
825 (org-test-with-temp-text "* Headline :ARCHIVE:"
826 (let ((org-archive-tag "ARCHIVE"))
827 (let ((headline (org-element-at-point)))
828 (should (org-element-property :archivedp headline))
829 ;; Test tag removal.
830 (should-not (org-element-property :tags headline))))
831 (let ((org-archive-tag "Archive"))
832 (should-not (org-element-property :archivedp (org-element-at-point)))))
833 ;; Multiple tags.
834 (org-test-with-temp-text "* Headline :test:ARCHIVE:"
835 (let ((org-archive-tag "ARCHIVE"))
836 (let ((headline (org-element-at-point)))
837 (should (org-element-property :archivedp headline))
838 ;; Test tag removal.
839 (should (equal (org-element-property :tags headline) '("test")))))))
842 ;;;; Horizontal Rule
844 (ert-deftest test-org-element/horizontal-rule-parser ()
845 "Test `horizontal-rule' parser."
846 ;; Standard.
847 (should
848 (org-test-with-temp-text "-----"
849 (org-element-map (org-element-parse-buffer) 'horizontal-rule 'identity)))
850 ;; Indented.
851 (should
852 (org-test-with-temp-text " -----"
853 (org-element-map (org-element-parse-buffer) 'horizontal-rule 'identity)))
854 ;; Hyphen must be alone on the line.
855 (should-not
856 (org-test-with-temp-text "-----wrong"
857 (org-element-map (org-element-parse-buffer) 'horizontal-rule 'identity)))
858 ;; 4 hyphens is too small.
859 (should-not
860 (org-test-with-temp-text "----"
861 (org-element-map (org-element-parse-buffer) 'horizontal-rule 'identity))))
864 ;;;; Inline Babel Call
866 (ert-deftest test-org-element/inline-babel-call-parser ()
867 "Test `inline-babel-call' parser."
868 (should
869 (org-test-with-temp-text "call_test()"
870 (org-element-map
871 (org-element-parse-buffer) 'inline-babel-call 'identity))))
874 ;;;; Inline Src Block
876 (ert-deftest test-org-element/inline-src-block-parser ()
877 "Test `inline-src-block' parser."
878 (should
879 (org-test-with-temp-text "src_emacs-lisp{(+ 1 1)}"
880 (org-element-map (org-element-parse-buffer) 'inline-src-block 'identity)))
881 ;; Test parsing at the beginning of an item.
882 (should
883 (org-test-with-temp-text "- src_emacs-lisp{(+ 1 1)}"
884 (org-element-map (org-element-parse-buffer) 'inline-src-block 'identity))))
887 ;;;; Inlinetask
889 (ert-deftest test-org-element/inlinetask-parser ()
890 "Test `inlinetask' parser."
891 (when (featurep 'org-inlinetask)
892 (let ((org-inlinetask-min-level 15))
893 ;; 1. Regular inlinetask.
894 (should
895 (org-test-with-temp-text
896 "*************** Task\nTest\n*************** END"
897 (org-element-map (org-element-parse-buffer) 'inlinetask 'identity)))
898 ;; 2. Degenerate inlinetask.
899 (should
900 (org-test-with-temp-text "*************** Task"
901 (org-element-map (org-element-parse-buffer) 'inlinetask 'identity)))
902 ;; TODO keyword.
903 (should
904 (equal
905 "TODO"
906 (let ((org-todo-keywords '((sequence "TODO" "DONE"))))
907 (org-test-with-temp-text "*************** TODO Task"
908 (org-element-property
909 :todo-keyword
910 (org-element-map
911 (org-element-parse-buffer) 'inlinetask 'identity nil t))))))
912 ;; Planning info.
913 (should
914 (equal
915 "2012-03-29 thu."
916 (org-test-with-temp-text "
917 *************** Task
918 DEADLINE: <2012-03-29 thu.>"
919 (org-element-property
920 :deadline
921 (org-element-map
922 (org-element-parse-buffer) 'inlinetask 'identity nil t)))))
923 ;; Priority.
924 (should
925 (equal
927 (org-test-with-temp-text "
928 *************** [#A] Task"
929 (org-element-property
930 :priority
931 (org-element-map
932 (org-element-parse-buffer) 'inlinetask 'identity nil t)))))
933 ;; Tags.
934 (should
935 (equal
936 '("test")
937 (org-test-with-temp-text "
938 *************** Task :test:"
939 (org-element-property
940 :tags
941 (org-element-map
942 (org-element-parse-buffer) 'inlinetask 'identity nil t))))))))
945 ;;;; Italic
947 (ert-deftest test-org-element/italic-parser ()
948 "Test `italic' parser."
949 ;; Regular test.
950 (should
951 (let ((org-emph-re "\\([ ('\"{]\\|^\\)\\(\\([+*/_=~]\\)\\([^ \n,\"']\\|[^ \n,\"'].*?\\(?:\n.*?\\)\\{0,1\\}[^ \n,\"']\\)\\3\\)\\([- .,:!?;'\")}\\]\\|$\\)"))
952 (org-test-with-temp-text "/italic/"
953 (org-element-map (org-element-parse-buffer) 'italic 'identity nil t))))
954 ;; Multi-line markup.
955 (should
956 (equal
957 (org-element-contents
958 (let ((org-emph-re "\\([ ('\"{]\\|^\\)\\(\\([+*/_=~]\\)\\([^ \n,\"']\\|[^ \n,\"'].*?\\(?:\n.*?\\)\\{0,1\\}[^ \n,\"']\\)\\3\\)\\([- .,:!?;'\")}\\]\\|$\\)"))
959 (org-test-with-temp-text "/first line\nsecond line/"
960 (org-element-map (org-element-parse-buffer) 'italic 'identity nil t))))
961 '("first line\nsecond line"))))
964 ;;;; Item
966 (ert-deftest test-org-element/item-parser ()
967 "Test `item' parser."
968 ;; Standard test.
969 (should
970 (org-test-with-temp-text "- item"
971 (org-element-map (org-element-parse-buffer) 'item 'identity)))
972 ;; Counter.
973 (should
974 (= 6
975 (org-element-property
976 :counter
977 (org-test-with-temp-text "6. [@6] item"
978 (org-element-map (org-element-parse-buffer) 'item 'identity nil t)))))
979 ;; Tag
980 (should
981 (equal
982 '("tag")
983 (org-element-property
984 :tag
985 (org-test-with-temp-text "- tag :: description"
986 (org-element-map (org-element-parse-buffer) 'item 'identity nil t)))))
987 ;; No tags in ordered lists.
988 (should-not
989 (org-element-property
990 :tag
991 (org-test-with-temp-text "1. tag :: description"
992 (org-element-map (org-element-parse-buffer) 'item 'identity nil t))))
993 ;; Check-boxes
994 (should
995 (equal
996 '(trans on off)
997 (org-test-with-temp-text "
998 - [-] item 1
999 - [X] item 1.1
1000 - [ ] item 1.2"
1001 (org-element-map
1002 (org-element-parse-buffer) 'item
1003 (lambda (item) (org-element-property :checkbox item))))))
1004 ;; Folded state.
1005 (org-test-with-temp-text "* Headline
1006 - item
1008 paragraph below"
1009 (forward-line)
1010 (let ((org-cycle-include-plain-lists t)) (org-cycle))
1011 (should
1012 (org-element-property
1013 :hiddenp
1014 (org-element-map (org-element-parse-buffer) 'item 'identity nil t))))
1015 ;; Item starting with special syntax.
1016 (should
1017 (equal '(("- item"))
1018 (org-test-with-temp-text "- - item"
1019 (org-element-map
1020 (org-element-parse-buffer) 'paragraph 'org-element-contents)))))
1023 ;;;; Keyword
1025 (ert-deftest test-org-element/keyword-parser ()
1026 "Test `keyword' parser."
1027 ;; Standard test.
1028 (should
1029 (org-test-with-temp-text "#+KEYWORD: value"
1030 (org-element-map (org-element-parse-buffer) 'keyword 'identity)))
1031 ;; Keywords are case-insensitive.
1032 (should
1033 (org-test-with-temp-text "#+keyword: value"
1034 (org-element-map (org-element-parse-buffer) 'keyword 'identity)))
1035 ;; Affiliated keywords are not keywords.
1036 (should-not
1037 (org-test-with-temp-text "#+NAME: value
1038 Paragraph"
1039 (org-element-map (org-element-parse-buffer) 'keyword 'identity)))
1040 ;; Do not mix keywords with Babel calls and dynamic blocks.
1041 (should-not
1042 (org-test-with-temp-text "#+CALL: fun()"
1043 (org-element-map (org-element-parse-buffer) 'keyword 'identity)))
1044 (should-not
1045 (org-test-with-temp-text "#+BEGIN: my-fun\nBody\n#+END:"
1046 (org-element-map (org-element-parse-buffer) 'keyword 'identity))))
1049 ;;;; Latex Environment
1051 (ert-deftest test-org-element/latex-environment-parser ()
1052 "Test `latex-environment' parser."
1053 (should
1054 (org-test-with-temp-text "\\begin{equation}\ne^{i\\pi}+1=0\n\\end{equation}"
1055 (org-element-map
1056 (org-element-parse-buffer) 'latex-environment 'identity)))
1057 ;; Allow nested environments.
1058 (should
1059 (equal
1060 "\\begin{outer}
1061 \\begin{inner}
1062 e^{i\\pi}+1=0
1063 \\end{inner}
1064 \\end{outer}"
1065 (org-test-with-temp-text "
1066 \\begin{outer}
1067 \\begin{inner}
1068 e^{i\\pi}+1=0
1069 \\end{inner}
1070 \\end{outer}"
1071 (org-element-property
1072 :value
1073 (org-element-map
1074 (org-element-parse-buffer) 'latex-environment 'identity nil t))))))
1077 ;;;; Latex Fragment
1079 (ert-deftest test-org-element/latex-fragment-parser ()
1080 "Test `latex-fragment' parser."
1081 (let ((org-latex-regexps
1082 '(("begin" "^[ ]*\\(\\\\begin{\\([a-zA-Z0-9\\*]+\\)[^