org-element: Fix org-element-context on parsed keywords
[org-mode.git] / testing / lisp / test-org-element.el
blobd6298dbd42e59336b9f21c319b4eb99ba0ac8389
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)))))
212 (should
213 (equal
214 '((("l1")) (nil "s1"))
215 (org-test-with-temp-text "#+CAPTION[s1]:\n#+CAPTION: l1\nParagraph"
216 (org-element-property :caption (org-element-at-point))))))
219 ;;;; Babel Call
221 (ert-deftest test-org-element/babel-call-parser ()
222 "Test `babel-call' parsing."
223 ;; Standard test.
224 (should
225 (org-test-with-temp-text "#+CALL: test()"
226 (org-element-map (org-element-parse-buffer) 'babel-call 'identity)))
227 ;; Ignore case.
228 (should
229 (org-test-with-temp-text "#+call: test()"
230 (org-element-map (org-element-parse-buffer) 'babel-call 'identity))))
233 ;;;; Bold
235 (ert-deftest test-org-element/bold-parser ()
236 "Test `bold' parser."
237 ;; Standard test.
238 (should
239 (let ((org-emph-re "\\([ ('\"{]\\|^\\)\\(\\([+*/_=~]\\)\\([^ \n,\"']\\|[^ \n,\"'].*?\\(?:\n.*?\\)\\{0,1\\}[^ \n,\"']\\)\\3\\)\\([- .,:!?;'\")}\\]\\|$\\)"))
240 (org-test-with-temp-text "*bold*"
241 (org-element-map (org-element-parse-buffer) 'bold 'identity nil t))))
242 ;; Multi-line markup.
243 (should
244 (equal
245 (org-element-contents
246 (let ((org-emph-re "\\([ ('\"{]\\|^\\)\\(\\([+*/_=~]\\)\\([^ \n,\"']\\|[^ \n,\"'].*?\\(?:\n.*?\\)\\{0,1\\}[^ \n,\"']\\)\\3\\)\\([- .,:!?;'\")}\\]\\|$\\)"))
247 (org-test-with-temp-text "*first line\nsecond line*"
248 (org-element-map (org-element-parse-buffer) 'bold 'identity nil t))))
249 '("first line\nsecond line"))))
252 ;;;; Center Block
254 (ert-deftest test-org-element/center-block-parser ()
255 "Test `center-block' parser."
256 ;; Standard test.
257 (should
258 (org-test-with-temp-text "#+BEGIN_CENTER\nText\n#+END_CENTER"
259 (org-element-map (org-element-parse-buffer) 'center-block 'identity)))
260 ;; Ignore case.
261 (should
262 (org-test-with-temp-text "#+begin_center\nText\n#+end_center"
263 (org-element-map (org-element-parse-buffer) 'center-block 'identity)))
264 ;; Test folded block.
265 (org-test-with-temp-text "#+BEGIN_CENTER\nText\n#+END_CENTER"
266 (org-cycle)
267 (should
268 (org-element-property
269 :hiddenp
270 (org-element-map
271 (org-element-parse-buffer) 'center-block 'identity nil t))))
272 ;; Ignore incomplete block.
273 (should-not
274 (org-test-with-temp-text "#+BEGIN_CENTER"
275 (org-element-map
276 (org-element-parse-buffer) 'center-block 'identity nil t))))
279 ;;;; Clock
281 (ert-deftest test-org-element/clock-parser ()
282 "Test `clock' parser."
283 ;; Running clock.
284 (let* ((org-clock-string "CLOCK:")
285 (clock (org-test-with-temp-text "CLOCK: [2012-01-01 sun. 00:01]"
286 (org-element-at-point))))
287 (should (eq (org-element-property :status clock) 'running))
288 (should
289 (equal (org-element-property :raw-value
290 (org-element-property :value clock))
291 "[2012-01-01 sun. 00:01]"))
292 (should-not (org-element-property :duration clock)))
293 ;; Closed clock.
294 (let* ((org-clock-string "CLOCK:")
295 (clock
296 (org-test-with-temp-text
297 "CLOCK: [2012-01-01 sun. 00:01]--[2012-01-01 sun. 00:02] => 0:01"
298 (org-element-at-point))))
299 (should (eq (org-element-property :status clock) 'closed))
300 (should (equal (org-element-property :raw-value
301 (org-element-property :value clock))
302 "[2012-01-01 sun. 00:01]--[2012-01-01 sun. 00:02]"))
303 (should (equal (org-element-property :duration clock) "0:01"))))
306 ;;;; Code
308 (ert-deftest test-org-element/code-parser ()
309 "Test `code' parser."
310 ;; Regular test.
311 (should
312 (let ((org-emph-re "\\([ ('\"{]\\|^\\)\\(\\([+*/_=~]\\)\\([^ \n,\"']\\|[^ \n,\"'].*?\\(?:\n.*?\\)\\{0,1\\}[^ \n,\"']\\)\\3\\)\\([- .,:!?;'\")}\\]\\|$\\)"))
313 (org-test-with-temp-text "~code~"
314 (org-element-map (org-element-parse-buffer) 'code 'identity))))
315 ;; Multi-line markup.
316 (should
317 (equal
318 (org-element-property
319 :value
320 (let ((org-emph-re "\\([ ('\"{]\\|^\\)\\(\\([+*/_=~]\\)\\([^ \n,\"']\\|[^ \n,\"'].*?\\(?:\n.*?\\)\\{0,1\\}[^ \n,\"']\\)\\3\\)\\([- .,:!?;'\")}\\]\\|$\\)"))
321 (org-test-with-temp-text "~first line\nsecond line~"
322 (org-element-map
323 (org-element-parse-buffer) 'code 'identity nil t))))
324 "first line\nsecond line")))
327 ;;;; Comment
329 (ert-deftest test-org-element/comment-parser ()
330 "Test `comment' parser."
331 ;; Regular comment.
332 (should
333 (org-test-with-temp-text "# Comment"
334 (org-element-map (org-element-parse-buffer) 'comment 'identity)))
335 ;; Inline comment.
336 (should
337 (org-test-with-temp-text " # Comment"
338 (org-element-map (org-element-parse-buffer) 'comment 'identity)))
339 ;; Preserve indentation.
340 (should
341 (equal
342 (org-element-property
343 :value
344 (org-test-with-temp-text "# No blank\n# One blank"
345 (org-element-map (org-element-parse-buffer) 'comment 'identity nil t)))
346 "No blank\n One blank"))
347 ;; Comment with blank lines.
348 (should
349 (equal
350 (org-element-property
351 :value
352 (org-test-with-temp-text "# First part\n# \n#\n# Second part"
353 (org-element-map (org-element-parse-buffer) 'comment 'identity nil t)))
354 "First part\n\n\nSecond part"))
355 ;; Do not mix comments and keywords.
356 (should
357 (eq 1
358 (org-test-with-temp-text "#+keyword: value\n# comment\n#+keyword: value"
359 (length (org-element-map
360 (org-element-parse-buffer) 'comment 'identity)))))
361 (should
362 (equal "comment"
363 (org-test-with-temp-text "#+keyword: value\n# comment\n#+keyword: value"
364 (org-element-property
365 :value
366 (org-element-map
367 (org-element-parse-buffer) 'comment 'identity nil t))))))
370 ;;;; Comment Block
372 (ert-deftest test-org-element/comment-block-parser ()
373 "Test `comment-block' parser."
374 ;; Standard test.
375 (should
376 (org-test-with-temp-text "#+BEGIN_COMMENT\nText\n#+END_COMMENT"
377 (org-element-map
378 (org-element-parse-buffer) 'comment-block 'identity)))
379 ;; Ignore case.
380 (should
381 (org-test-with-temp-text "#+begin_comment\nText\n#+end_comment"
382 (org-element-map
383 (org-element-parse-buffer) 'comment-block 'identity)))
384 ;; Test folded block.
385 (org-test-with-temp-text "#+BEGIN_COMMENT\nText\n#+END_COMMENT"
386 (org-cycle)
387 (should
388 (org-element-property
389 :hiddenp
390 (org-element-map
391 (org-element-parse-buffer) 'comment-block 'identity nil t))))
392 ;; Ignore incomplete block.
393 (should-not
394 (org-test-with-temp-text "#+BEGIN_COMMENT"
395 (org-element-map
396 (org-element-parse-buffer) 'comment-block 'identity nil t))))
399 ;;;; Diary Sexp
401 (ert-deftest test-org-element/diary-sexp-parser ()
402 "Test `diary-sexp' parser."
403 ;; Standard test.
404 (should
405 (eq 'diary-sexp
406 (org-test-with-temp-text
407 "%%(org-anniversary 1956 5 14)(2) Arthur Dent is %d years old"
408 (org-element-type (org-element-at-point)))))
409 ;; Diary sexp must live at beginning of line
410 (should-not
411 (eq 'diary-sexp
412 (org-test-with-temp-text " %%(org-bbdb-anniversaries)"
413 (org-element-type (org-element-at-point))))))
416 ;;;; Drawer
418 (ert-deftest test-org-element/drawer-parser ()
419 "Test `drawer' parser."
420 ;; Standard test.
421 (should
422 (let ((org-drawers '("TEST")))
423 (org-test-with-temp-text ":TEST:\nText\n:END:"
424 (org-element-map (org-element-parse-buffer) 'drawer 'identity))))
425 ;; Do not mix regular drawers and property drawers.
426 (should-not
427 (let ((org-drawers '("PROPERTIES")))
428 (org-test-with-temp-text ":PROPERTIES:\n:prop: value\n:END:"
429 (org-element-map
430 (org-element-parse-buffer) 'drawer 'identity nil t))))
431 ;; Ignore incomplete drawer.
432 (should-not
433 (let ((org-drawers '("TEST")))
434 (org-test-with-temp-text ":TEST:"
435 (org-element-map
436 (org-element-parse-buffer) 'drawer 'identity nil t)))))
439 ;;;; Dynamic Block
441 (ert-deftest test-org-element/dynamic-block-parser ()
442 "Test `dynamic-block' parser."
443 ;; Standard test.
444 (should
445 (org-test-with-temp-text
446 "#+BEGIN: myblock :param1 val1 :param2 val2\nText\n#+END:"
447 (org-element-map (org-element-parse-buffer) 'dynamic-block 'identity)))
448 ;; Folded view
449 (org-test-with-temp-text
450 "#+BEGIN: myblock :param1 val1 :param2 val2\nText\n#+END:"
451 (org-cycle)
452 (should
453 (org-element-property
454 :hiddenp
455 (org-element-map
456 (org-element-parse-buffer) 'dynamic-block 'identity nil t))))
457 ;; Ignore case.
458 (should
459 (org-test-with-temp-text
460 "#+begin: myblock :param1 val1 :param2 val2\nText\n#+end:"
461 (org-element-map (org-element-parse-buffer) 'dynamic-block 'identity)))
462 ;; Ignore incomplete block.
463 (should-not
464 (org-test-with-temp-text "#+BEGIN: myblock :param1 val1 :param2 val2"
465 (org-element-map
466 (org-element-parse-buffer) 'dynamic-block 'identity nil t))))
469 ;;;; Entity
471 (ert-deftest test-org-element/entity-parser ()
472 "Test `entity' parser."
473 ;; Without brackets.
474 (should
475 (org-test-with-temp-text "\\sin"
476 (org-element-map (org-element-parse-buffer) 'entity 'identity)))
477 ;; With brackets.
478 (should
479 (org-element-property
480 :use-brackets-p
481 (org-test-with-temp-text "\\alpha{}text"
482 (org-element-map (org-element-parse-buffer) 'entity 'identity nil t))))
483 ;; User-defined entity.
484 (should
485 (equal
486 (org-element-property
487 :name
488 (let ((org-entities-user
489 '(("test" "test" nil "test" "test" "test" "test"))))
490 (org-test-with-temp-text "\\test"
491 (org-element-map (org-element-parse-buffer) 'entity 'identity nil t))))
492 "test")))
495 ;;;; Example Block
497 (ert-deftest test-org-element/example-block-parser ()
498 "Test `example-block' parser."
499 ;; Standard test.
500 (should
501 (org-test-with-temp-text "#+BEGIN_EXAMPLE\nText\n#+END_EXAMPLE"
502 (org-element-map (org-element-parse-buffer) 'example-block 'identity)))
503 ;; Test folded block.
504 (org-test-with-temp-text "#+BEGIN_EXAMPLE\nText\n#+END_EXAMPLE"
505 (org-cycle)
506 (should
507 (org-element-property
508 :hiddenp
509 (org-element-map
510 (org-element-parse-buffer) 'example-block 'identity nil t))))
511 ;; Ignore incomplete block.
512 (should-not
513 (org-test-with-temp-text "#+BEGIN_EXAMPLE"
514 (org-element-map
515 (org-element-parse-buffer) 'example-block 'identity nil t)))
516 ;; Properly un-escape code.
517 (should
518 (equal "* Headline\n #+keyword\nText\n"
519 (org-test-with-temp-text
520 "#+BEGIN_EXAMPLE\n,* Headline\n ,#+keyword\nText\n#+END_EXAMPLE"
521 (org-element-property :value (org-element-at-point))))))
523 (ert-deftest test-org-element/block-switches ()
524 "Test `example-block' and `src-block' switches parsing."
525 (let ((org-coderef-label-format "(ref:%s)"))
526 ;; 1. Test "-i" switch.
527 (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp\n(+ 1 1)\n#+END_SRC"
528 (should-not
529 (org-element-property :preserve-indent (org-element-at-point))))
530 (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp -i\n(+ 1 1)\n#+END_SRC"
531 (should (org-element-property :preserve-indent (org-element-at-point))))
532 (org-test-with-temp-text "#+BEGIN_EXAMPLE\nText.\n#+END_EXAMPLE"
533 (should-not
534 (org-element-property :preserve-indent (org-element-at-point))))
535 (org-test-with-temp-text "#+BEGIN_EXAMPLE -i\nText.\n#+END_EXAMPLE"
536 (should (org-element-property :preserve-indent (org-element-at-point))))
537 ;; 2. "-n -r -k" combination should number lines, retain labels but
538 ;; not use them in coderefs.
539 (org-test-with-temp-text "#+BEGIN_EXAMPLE -n -r -k\nText.\n#+END_EXAMPLE"
540 (let ((element (org-element-at-point)))
541 (should (and (org-element-property :number-lines element)
542 (org-element-property :retain-labels element)
543 (not (org-element-property :use-labels element))))))
544 (org-test-with-temp-text
545 "#+BEGIN_SRC emacs-lisp -n -r -k\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 (not (org-element-property :use-labels element))))))
550 ;; 3. "-n -r" combination should number-lines remove labels and not
551 ;; use them in coderefs.
552 (org-test-with-temp-text "#+BEGIN_EXAMPLE -n -r\nText.\n#+END_EXAMPLE"
553 (let ((element (org-element-at-point)))
554 (should (and (org-element-property :number-lines element)
555 (not (org-element-property :retain-labels element))
556 (not (org-element-property :use-labels element))))))
557 (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp -n -r\n(+ 1 1)\n#+END_SRC"
558 (let ((element (org-element-at-point)))
559 (should (and (org-element-property :number-lines element)
560 (not (org-element-property :retain-labels element))
561 (not (org-element-property :use-labels element))))))
562 ;; 4. "-n" or "+n" should number lines, retain labels and use them
563 ;; in coderefs.
564 (org-test-with-temp-text "#+BEGIN_EXAMPLE -n\nText.\n#+END_EXAMPLE"
565 (let ((element (org-element-at-point)))
566 (should (and (org-element-property :number-lines element)
567 (org-element-property :retain-labels element)
568 (org-element-property :use-labels element)))))
569 (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp -n\n(+ 1 1)\n#+END_SRC"
570 (let ((element (org-element-at-point)))
571 (should (and (org-element-property :number-lines element)
572 (org-element-property :retain-labels element)
573 (org-element-property :use-labels element)))))
574 (org-test-with-temp-text "#+BEGIN_EXAMPLE +n\nText.\n#+END_EXAMPLE"
575 (let ((element (org-element-at-point)))
576 (should (and (org-element-property :number-lines element)
577 (org-element-property :retain-labels element)
578 (org-element-property :use-labels element)))))
579 (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp +n\n(+ 1 1)\n#+END_SRC"
580 (let ((element (org-element-at-point)))
581 (should (and (org-element-property :number-lines element)
582 (org-element-property :retain-labels element)
583 (org-element-property :use-labels element)))))
584 ;; 5. No switch should not number lines, but retain labels and use
585 ;; them in coderefs.
586 (org-test-with-temp-text "#+BEGIN_EXAMPLE\nText.\n#+END_EXAMPLE"
587 (let ((element (org-element-at-point)))
588 (should (and (not (org-element-property :number-lines element))
589 (org-element-property :retain-labels element)
590 (org-element-property :use-labels element)))))
591 (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp\n(+ 1 1)\n#+END_SRC"
592 (let ((element (org-element-at-point)))
593 (should (and (not (org-element-property :number-lines element))
594 (org-element-property :retain-labels element)
595 (org-element-property :use-labels element)))))
596 ;; 6. "-r" switch only: do not number lines, remove labels, and
597 ;; don't use labels in coderefs.
598 (org-test-with-temp-text "#+BEGIN_EXAMPLE -r\nText.\n#+END_EXAMPLE"
599 (let ((element (org-element-at-point)))
600 (should (and (not (org-element-property :number-lines element))
601 (not (org-element-property :retain-labels element))
602 (not (org-element-property :use-labels element))))))
603 (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp -r\n(+ 1 1)\n#+END_SRC"
604 (let ((element (org-element-at-point)))
605 (should (and (not (org-element-property :number-lines element))
606 (not (org-element-property :retain-labels element))
607 (not (org-element-property :use-labels element))))))
608 ;; 7. Recognize coderefs with user-defined syntax.
609 (org-test-with-temp-text
610 "#+BEGIN_EXAMPLE -l \"[ref:%s]\"\nText [ref:text]\n#+END_EXAMPLE"
611 (let ((element (org-element-at-point)))
612 (should
613 (equal (org-element-property :label-fmt element) "[ref:%s]"))))
614 (org-test-with-temp-text
615 "#+BEGIN_SRC emacs-lisp -l \"[ref:%s]\"\n(+ 1 1) [ref:text]\n#+END_SRC"
616 (let ((element (org-element-at-point)))
617 (should
618 (equal (org-element-property :label-fmt element) "[ref:%s]"))))))
621 ;;;; Export Block
623 (ert-deftest test-org-element/export-block-parser ()
624 "Test `export-block' parser."
625 ;; Standard test.
626 (should
627 (org-test-with-temp-text "#+BEGIN_LATEX\nText\n#+END_LATEX"
628 (org-element-map
629 (let ((org-element-block-name-alist
630 '(("LATEX" . org-element-export-block-parser))))
631 (org-element-parse-buffer))
632 'export-block 'identity)))
633 ;; Test folded block.
634 (org-test-with-temp-text "#+BEGIN_LATEX\nText\n#+END_LATEX"
635 (org-cycle)
636 (should
637 (org-element-property
638 :hiddenp
639 (org-element-map
640 (let ((org-element-block-name-alist
641 '(("LATEX" . org-element-export-block-parser))))
642 (org-element-parse-buffer))
643 'export-block 'identity nil t))))
644 ;; Ignore case.
645 (should
646 (org-test-with-temp-text "#+begin_latex\nText\n#+end_latex"
647 (org-element-map
648 (let ((org-element-block-name-alist
649 '(("LATEX" . org-element-export-block-parser))))
650 (org-element-parse-buffer))
651 'export-block 'identity)))
652 ;; Ignore incomplete block.
653 (should-not
654 (org-test-with-temp-text "#+BEGIN_LATEX"
655 (org-element-map
656 (let ((org-element-block-name-alist
657 '(("LATEX" . org-element-export-block-parser))))
658 (org-element-parse-buffer))
659 'export-block 'identity nil t))))
662 ;;;; Export Snippet
664 (ert-deftest test-org-element/export-snippet-parser ()
665 "Test `export-snippet' parser."
666 (should
667 (equal
668 '("back-end" . "contents")
669 (org-test-with-temp-text "@@back-end:contents@@"
670 (org-element-map
671 (org-element-parse-buffer) 'export-snippet
672 (lambda (snippet) (cons (org-element-property :back-end snippet)
673 (org-element-property :value snippet)))
674 nil t)))))
677 ;;;; Fixed Width
679 (ert-deftest test-org-element/fixed-width ()
680 "Test fixed-width area parsing."
681 ;; Preserve indentation.
682 (should
683 (org-test-with-temp-text ": no blank\n: one blank"
684 (org-element-map (org-element-parse-buffer) 'fixed-width 'identity)))
685 ;; Fixed-width with empty lines.
686 (should
687 (org-test-with-temp-text ": first part\n:\n: \n: second part"
688 (org-element-map (org-element-parse-buffer) 'fixed-width 'identity)))
689 ;; Parse indented fixed-width markers.
690 (should
691 (org-test-with-temp-text "Text\n : no blank\n : one blank"
692 (org-element-map (org-element-parse-buffer) 'fixed-width 'identity)))
693 ;; Distinguish fixed-width areas within a list and outside of it.
694 (should
695 (= 2
696 (length
697 (org-test-with-temp-text "
698 - Item
699 : fixed-width inside
700 : fixed-width outside"
701 (org-element-map
702 (org-element-parse-buffer) 'fixed-width 'identity))))))
705 ;;;; Footnote Definition
707 (ert-deftest test-org-element/footnote-definition-parser ()
708 "Test `footnote-definition' parser."
709 (should
710 (org-test-with-temp-text "[fn:1] Definition"
711 (org-element-map
712 (org-element-parse-buffer) 'footnote-definition 'identity nil t)))
713 ;; Footnote with more contents
714 (should
715 (= 28
716 (org-element-property
717 :end
718 (org-test-with-temp-text "[fn:1] Definition\n| a | b |"
719 (org-element-map
720 (org-element-parse-buffer)
721 'footnote-definition 'identity nil t)))))
722 ;; Footnote starting with special syntax.
723 (should-not
724 (org-test-with-temp-text "[fn:1] - no item"
725 (org-element-map (org-element-parse-buffer) 'item 'identity))))
728 ;;;; Footnotes Reference.
730 (ert-deftest test-org-element/footnote-reference-parser ()
731 "Test `footnote-reference' parser."
732 ;; 1. Parse a standard reference.
733 (org-test-with-temp-text "Text[fn:label]"
734 (should
735 (org-element-map
736 (org-element-parse-buffer) 'footnote-reference 'identity)))
737 ;; 2. Parse a normalized reference.
738 (org-test-with-temp-text "Text[1]"
739 (should
740 (org-element-map
741 (org-element-parse-buffer) 'footnote-reference 'identity)))
742 ;; 3. Parse an inline reference.
743 (org-test-with-temp-text "Text[fn:test:def]"
744 (should
745 (org-element-map
746 (org-element-parse-buffer) 'footnote-reference 'identity)))
747 ;; 4. Parse an anonymous reference.
748 (org-test-with-temp-text "Text[fn::def]"
749 (should
750 (org-element-map
751 (org-element-parse-buffer) 'footnote-reference 'identity)))
752 ;; 5. Parse nested footnotes.
753 (org-test-with-temp-text "Text[fn::def [fn:label]]"
754 (should
755 (= 2
756 (length
757 (org-element-map
758 (org-element-parse-buffer) 'footnote-reference 'identity)))))
759 ;; 6. Parse adjacent footnotes.
760 (org-test-with-temp-text "Text[fn:label1][fn:label2]"
761 (should
762 (= 2
763 (length
764 (org-element-map
765 (org-element-parse-buffer) 'footnote-reference 'identity)))))
766 ;; 7. Only properly closed footnotes are recognized as such.
767 (org-test-with-temp-text "Text[fn:label"
768 (should-not
769 (org-element-map
770 (org-element-parse-buffer) 'footnote-reference 'identity))))
773 ;;;; Headline
775 (ert-deftest test-org-element/headline-quote-keyword ()
776 "Test QUOTE keyword recognition."
777 ;; Reference test.
778 (org-test-with-temp-text "* Headline"
779 (let ((org-quote-string "QUOTE"))
780 (should-not (org-element-property :quotedp (org-element-at-point)))))
781 ;; Standard position.
782 (org-test-with-temp-text "* QUOTE Headline"
783 (let* ((org-quote-string "QUOTE")
784 (headline (org-element-at-point)))
785 (should (org-element-property :quotedp headline))
786 ;; Test removal from raw value.
787 (should (equal (org-element-property :raw-value headline) "Headline"))))
788 ;; Case sensitivity.
789 (org-test-with-temp-text "* QUOTE Headline"
790 (let* ((org-quote-string "Quote")
791 (headline (org-element-at-point)))
792 (should-not (org-element-property :quotedp headline))
793 (should (equal (org-element-property :raw-value headline)
794 "QUOTE Headline"))))
795 ;; With another keyword.
796 (org-test-with-temp-text "* TODO QUOTE Headline"
797 (let* ((org-quote-string "QUOTE")
798 (org-todo-keywords '((sequence "TODO" "DONE")))
799 (headline (org-element-at-point)))
800 (should (org-element-property :quotedp headline))
801 (should (equal (org-element-property :raw-value headline) "Headline"))))
802 ;; With the keyword only.
803 (org-test-with-temp-text "* QUOTE"
804 (let* ((org-quote-string "QUOTE")
805 (headline (org-element-at-point)))
806 (should (org-element-property :quotedp headline))
807 (should (equal (org-element-property :raw-value headline) "")))))
809 (ert-deftest test-org-element/headline-comment-keyword ()
810 "Test COMMENT keyword recognition."
811 ;; Reference test.
812 (org-test-with-temp-text "* Headline"
813 (let ((org-comment-string "COMMENT"))
814 (should-not (org-element-property :commentedp (org-element-at-point)))))
815 ;; Standard position.
816 (org-test-with-temp-text "* COMMENT Headline"
817 (let ((org-comment-string "COMMENT")
818 (headline (org-element-at-point)))
819 (should (org-element-property :commentedp headline))
820 (should (equal (org-element-property :raw-value headline) "Headline"))))
821 ;; Case sensitivity.
822 (org-test-with-temp-text "* COMMENT Headline"
823 (let* ((org-comment-string "Comment")
824 (headline (org-element-at-point)))
825 (should-not (org-element-property :commentedp headline))
826 (should (equal (org-element-property :raw-value headline)
827 "COMMENT Headline"))))
828 ;; With another keyword.
829 (org-test-with-temp-text "* TODO COMMENT Headline"
830 (let* ((org-comment-string "COMMENT")
831 (org-todo-keywords '((sequence "TODO" "DONE")))
832 (headline (org-element-at-point)))
833 (should (org-element-property :commentedp headline))
834 (should (equal (org-element-property :raw-value headline) "Headline"))))
835 ;; With the keyword only.
836 (org-test-with-temp-text "* COMMENT"
837 (let* ((org-comment-string "COMMENT")
838 (headline (org-element-at-point)))
839 (should (org-element-property :commentedp headline))
840 (should (equal (org-element-property :raw-value headline) "")))))
842 (ert-deftest test-org-element/headline-archive-tag ()
843 "Test ARCHIVE tag recognition."
844 ;; Reference test.
845 (org-test-with-temp-text "* Headline"
846 (let ((org-archive-tag "ARCHIVE"))
847 (should-not (org-element-property :archivedp (org-element-at-point)))))
848 ;; Single tag.
849 (org-test-with-temp-text "* Headline :ARCHIVE:"
850 (let ((org-archive-tag "ARCHIVE"))
851 (let ((headline (org-element-at-point)))
852 (should (org-element-property :archivedp headline))
853 ;; Test tag removal.
854 (should-not (org-element-property :tags headline))))
855 (let ((org-archive-tag "Archive"))
856 (should-not (org-element-property :archivedp (org-element-at-point)))))
857 ;; Multiple tags.
858 (org-test-with-temp-text "* Headline :test:ARCHIVE:"
859 (let ((org-archive-tag "ARCHIVE"))
860 (let ((headline (org-element-at-point)))
861 (should (org-element-property :archivedp headline))
862 ;; Test tag removal.
863 (should (equal (org-element-property :tags headline) '("test")))))))
866 ;;;; Horizontal Rule
868 (ert-deftest test-org-element/horizontal-rule-parser ()
869 "Test `horizontal-rule' parser."
870 ;; Standard.
871 (should
872 (org-test-with-temp-text "-----"
873 (org-element-map (org-element-parse-buffer) 'horizontal-rule 'identity)))
874 ;; Indented.
875 (should
876 (org-test-with-temp-text " -----"
877 (org-element-map (org-element-parse-buffer) 'horizontal-rule 'identity)))
878 ;; Hyphen must be alone on the line.
879 (should-not
880 (org-test-with-temp-text "-----wrong"
881 (org-element-map (org-element-parse-buffer) 'horizontal-rule 'identity)))
882 ;; 4 hyphens is too small.
883 (should-not
884 (org-test-with-temp-text "----"
885 (org-element-map (org-element-parse-buffer) 'horizontal-rule 'identity))))
888 ;;;; Inline Babel Call
890 (ert-deftest test-org-element/inline-babel-call-parser ()
891 "Test `inline-babel-call' parser."
892 (should
893 (org-test-with-temp-text "call_test()"
894 (org-element-map
895 (org-element-parse-buffer) 'inline-babel-call 'identity))))
898 ;;;; Inline Src Block
900 (ert-deftest test-org-element/inline-src-block-parser ()
901 "Test `inline-src-block' parser."
902 (should
903 (org-test-with-temp-text "src_emacs-lisp{(+ 1 1)}"
904 (org-element-map (org-element-parse-buffer) 'inline-src-block 'identity)))
905 ;; Test parsing at the beginning of an item.
906 (should
907 (org-test-with-temp-text "- src_emacs-lisp{(+ 1 1)}"
908 (org-element-map (org-element-parse-buffer) 'inline-src-block 'identity))))
911 ;;;; Inlinetask
913 (ert-deftest test-org-element/inlinetask-parser ()
914 "Test `inlinetask' parser."
915 (when (featurep 'org-inlinetask)
916 (let ((org-inlinetask-min-level 15))
917 ;; 1. Regular inlinetask.
918 (should
919 (org-test-with-temp-text
920 "*************** Task\nTest\n*************** END"
921 (org-element-map (org-element-parse-buffer) 'inlinetask 'identity)))
922 ;; 2. Degenerate inlinetask.
923 (should
924 (org-test-with-temp-text "*************** Task"
925 (org-element-map (org-element-parse-buffer) 'inlinetask 'identity)))
926 ;; TODO keyword.
927 (should
928 (equal
929 "TODO"
930 (let ((org-todo-keywords '((sequence "TODO" "DONE"))))
931 (org-test-with-temp-text "*************** TODO Task"
932 (org-element-property
933 :todo-keyword
934 (org-element-map
935 (org-element-parse-buffer) 'inlinetask 'identity nil t))))))
936 ;; Planning info.
937 (should
938 (equal
939 "2012-03-29 thu."
940 (org-test-with-temp-text "
941 *************** Task
942 DEADLINE: <2012-03-29 thu.>"
943 (org-element-property
944 :deadline
945 (org-element-map
946 (org-element-parse-buffer) 'inlinetask 'identity nil t)))))
947 ;; Priority.
948 (should
949 (equal
951 (org-test-with-temp-text "
952 *************** [#A] Task"
953 (org-element-property
954 :priority
955 (org-element-map
956 (org-element-parse-buffer) 'inlinetask 'identity nil t)))))
957 ;; Tags.
958 (should
959 (equal
960 '("test")
961 (org-test-with-temp-text "
962 *************** Task :test:"
963 (org-element-property
964 :tags
965 (org-element-map
966 (org-element-parse-buffer) 'inlinetask 'identity nil t))))))))
969 ;;;; Italic
971 (ert-deftest test-org-element/italic-parser ()
972 "Test `italic' parser."
973 ;; Regular test.
974 (should
975 (let ((org-emph-re "\\([ ('\"{]\\|^\\)\\(\\([+*/_=~]\\)\\([^ \n,\"']\\|[^ \n,\"'].*?\\(?:\n.*?\\)\\{0,1\\}[^ \n,\"']\\)\\3\\)\\([- .,:!?;'\")}\\]\\|$\\)"))
976 (org-test-with-temp-text "/italic/"
977 (org-element-map (org-element-parse-buffer) 'italic 'identity nil t))))
978 ;; Multi-line markup.
979 (should
980 (equal
981 (org-element-contents
982 (let ((org-emph-re "\\([ ('\"{]\\|^\\)\\(\\([+*/_=~]\\)\\([^ \n,\"']\\|[^ \n,\"'].*?\\(?:\n.*?\\)\\{0,1\\}[^ \n,\"']\\)\\3\\)\\([- .,:!?;'\")}\\]\\|$\\)"))
983 (org-test-with-temp-text "/first line\nsecond line/"
984 (org-element-map (org-element-parse-buffer) 'italic 'identity nil t))))
985 '("first line\nsecond line"))))
988 ;;;; Item
990 (ert-deftest test-org-element/item-parser ()
991 "Test `item' parser."
992 ;; Standard test.
993 (should
994 (org-test-with-temp-text "- item"
995 (org-element-map (org-element-parse-buffer) 'item 'identity)))
996 ;; Counter.
997 (should
998 (= 6
999 (org-element-property
1000 :counter
1001 (org-test-with-temp-text "6. [@6] item"
1002 (org-element-map (org-element-parse-buffer) 'item 'identity nil t)))))
1003 ;; Tag
1004 (should
1005 (equal
1006 '("tag")
1007 (org-element-property
1008 :tag
1009 (org-test-with-temp-text "- tag :: description"
1010 (org-element-map (org-element-parse-buffer) 'item 'identity nil t)))))
1011 ;; No tags in ordered lists.
1012 (should-not
1013 (org-element-property
1014 :tag
1015 (org-test-with-temp-text "1. tag :: description"
1016 (org-element-map (org-element-parse-buffer) 'item 'identity nil t))))
1017 ;; Check-boxes
1018 (should
1019 (equal
1020 '(trans on off)
1021 (org-test-with-temp-text "
1022 - [-] item 1
1023 - [X] item 1.1
1024 - [ ] item 1.2"
1025 (org-element-map
1026 (org-element-parse-buffer) 'item
1027 (lambda (item) (org-element-property :checkbox item))))))
1028 ;; Folded state.
1029 (org-test-with-temp-text "* Headline
1030 - item
1032 paragraph below"
1033 (forward-line)
1034 (let ((org-cycle-include-plain-lists t)) (org-cycle))
1035 (should
1036 (org-element-property
1037 :hiddenp
1038 (org-element-map (org-element-parse-buffer) 'item 'identity nil t))))
1039 ;; Item starting with special syntax.
1040 (should
1041 (equal '(("- item"))
1042 (org-test-with-temp-text "- - item"
1043 (org-element-map
1044 (org-element-parse-buffer) 'paragraph 'org-element-contents)))))
1047 ;;;; Keyword
1049 (ert-deftest test-org-element/keyword-parser ()
1050 "Test `keyword' parser."
1051 ;; Standard test.
1052 (should
1053 (org-test-with-temp-text "#+KEYWORD: value"
1054 (org-element-map (org-element-parse-buffer) 'keyword 'identity)))
1055 ;; Keywords are case-insensitive.
1056 (should
1057 (org-test-with-temp-text "#+keyword: value"
1058 (org-element-map (org-element-parse-buffer) 'keyword 'identity)))
1059 ;; Affiliated keywords are not keywords.
1060 (should-not
1061 (org-test-with-temp-text "#+NAME: value
1062 Paragraph"
1063 (org-element-map (org-element-parse-buffer) 'keyword 'identity)))
1064 ;; Do not mix keywords with Babel calls and dynamic blocks.
1065 (should-not
1066 (org-test-with-temp-text "#+CALL: fun()"
1067 (org-element-map (org-element-parse-buffer) 'keyword 'identity)))
1068 (should-not
1069 (org-test-with-temp-text "#+BEGIN: my-fun\nBody\n#+END:"
1070 (org-element-map (org-element-parse-buffer) 'keyword 'identity))))
1073 ;;;; Latex Environment
1075 (ert-deftest test-org-element/latex-environment-parser ()
1076 "Test `latex-environment' parser."
1077 (should
1078 (org-test-with-temp-text "\\begin{equation}\ne^{i\\pi}+1=0\n\\end{equation}"
1079 (org-element-map
1080 (org-element-parse-buffer) 'latex-environment 'identity)))
1081 ;; Allow nested environments.
1082 (should
1083 (equal
1084 "\\begin{outer}
1085 \\begin{inner}
1086 e^{i\\pi}+1=0
1087 \\end{inner}
1088 \\end{outer}"
1089 (org-test-with-temp-text "
1090 \\begin{outer}
1091 \\begin{inner}
1092 e^{i\\pi}+1=0
1093 \\end{inner}
1094 \\end{outer}"
1095 (org-element-property
1096 :value
1097 (org-element-map
1098 (org-element-parse-buffer) 'latex-environment 'identity nil t))))))
1101 ;;;; Latex Fragment
1103 (ert-deftest test-org-element/latex-fragment-parser ()
1104 "Test `latex-fragment' parser."
1105 (let ((org-latex-regexps
1106 '(("begin" "^[ ]*\\(\\\\begin{\\([a-zA-Z0-9\\*]+\\)[^