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