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