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