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/>.
24 (unless (featurep 'org-element
)
25 (signal 'missing-test-dependency
"org-element"))
35 (ert-deftest test-org-element
/headline-quote-keyword
()
36 "Test QUOTE keyword recognition."
38 (org-test-with-temp-text "* Headline"
39 (let ((org-quote-string "QUOTE"))
40 (should-not (org-element-property :quotedp
(org-element-at-point)))))
42 (org-test-with-temp-text "* QUOTE Headline"
43 (let ((org-quote-string "QUOTE"))
44 (let ((headline (org-element-at-point)))
45 (should (org-element-property :quotedp headline
))
46 ;; Test removal from raw value.
47 (should (equal (org-element-property :raw-value headline
) "Headline"))))
49 (let ((org-quote-string "Quote"))
50 (should-not (org-element-property :quotedp
(org-element-at-point)))))
51 ;; With another keyword.
52 (org-test-with-temp-text "* TODO QUOTE Headline"
53 (let ((org-quote-string "QUOTE")
54 (org-todo-keywords '((sequence "TODO" "DONE"))))
55 (should (org-element-property :quotedp
(org-element-at-point))))))
57 (ert-deftest test-org-element
/headline-comment-keyword
()
58 "Test COMMENT keyword recognition."
60 (org-test-with-temp-text "* Headline"
61 (let ((org-comment-string "COMMENT"))
62 (should-not (org-element-property :commentedp
(org-element-at-point)))))
64 (org-test-with-temp-text "* COMMENT Headline"
65 (let ((org-comment-string "COMMENT"))
66 (let ((headline (org-element-at-point)))
67 (should (org-element-property :commentedp headline
))
68 ;; Test removal from raw value.
69 (should (equal (org-element-property :raw-value headline
) "Headline"))))
71 (let ((org-comment-string "Comment"))
72 (should-not (org-element-property :commentedp
(org-element-at-point)))))
73 ;; With another keyword.
74 (org-test-with-temp-text "* TODO COMMENT Headline"
75 (let ((org-comment-string "COMMENT")
76 (org-todo-keywords '((sequence "TODO" "DONE"))))
77 (should (org-element-property :commentedp
(org-element-at-point))))))
79 (ert-deftest test-org-element
/headline-archive-tag
()
80 "Test ARCHIVE tag recognition."
82 (org-test-with-temp-text "* Headline"
83 (let ((org-archive-tag "ARCHIVE"))
84 (should-not (org-element-property :archivedp
(org-element-at-point)))))
86 (org-test-with-temp-text "* Headline :ARCHIVE:"
87 (let ((org-archive-tag "ARCHIVE"))
88 (let ((headline (org-element-at-point)))
89 (should (org-element-property :archivedp headline
))
91 (should-not (org-element-property :tags headline
))))
92 (let ((org-archive-tag "Archive"))
93 (should-not (org-element-property :archivedp
(org-element-at-point)))))
95 (org-test-with-temp-text "* Headline :test:ARCHIVE:"
96 (let ((org-archive-tag "ARCHIVE"))
97 (let ((headline (org-element-at-point)))
98 (should (org-element-property :archivedp headline
))
100 (should (equal (org-element-property :tags headline
) ":test:"))))))
104 ;;;; Example-blocks and Src-blocks
106 (ert-deftest test-org-element
/block-switches
()
107 "Test `example-block' and `src-block' switches parsing."
108 (let ((org-coderef-label-format "(ref:%s)"))
109 ;; 1. Test "-i" switch.
110 (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp\n(+ 1 1)\n#+END_SRC"
111 (let ((element (org-element-current-element)))
112 (should-not (org-element-property :preserve-indent element
))))
113 (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp -i\n(+ 1 1)\n#+END_SRC"
114 (let ((element (org-element-current-element)))
115 (should (org-element-property :preserve-indent element
))))
116 (org-test-with-temp-text "#+BEGIN_EXAMPLE\nText.\n#+END_EXAMPLE"
117 (let ((element (org-element-current-element)))
118 (should-not (org-element-property :preserve-indent element
))))
119 (org-test-with-temp-text "#+BEGIN_EXAMPLE -i\nText.\n#+END_EXAMPLE"
120 (let ((element (org-element-current-element)))
121 (should (org-element-property :preserve-indent element
))))
122 ;; 2. "-n -r -k" combination should number lines, retain labels but
123 ;; not use them in coderefs.
124 (org-test-with-temp-text "#+BEGIN_EXAMPLE -n -r -k\nText.\N#+END_EXAMPLE"
125 (let ((element (org-element-current-element)))
126 (should (and (org-element-property :number-lines element
)
127 (org-element-property :retain-labels element
)
128 (not (org-element-property :use-labels element
))))))
129 (org-test-with-temp-text
130 "#+BEGIN_SRC emacs-lisp -n -r -k\n(+ 1 1)\n#+END_SRC"
131 (let ((element (org-element-current-element)))
132 (should (and (org-element-property :number-lines element
)
133 (org-element-property :retain-labels element
)
134 (not (org-element-property :use-labels element
))))))
135 ;; 3. "-n -r" combination should number-lines remove labels and not
136 ;; use them in coderefs.
137 (org-test-with-temp-text "#+BEGIN_EXAMPLE -n -r\nText.\n#+END_EXAMPLE"
138 (let ((element (org-element-current-element)))
139 (should (and (org-element-property :number-lines element
)
140 (not (org-element-property :retain-labels element
))
141 (not (org-element-property :use-labels element
))))))
142 (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp -n -r\n(+ 1 1)\n#+END_SRC"
143 (let ((element (org-element-current-element)))
144 (should (and (org-element-property :number-lines element
)
145 (not (org-element-property :retain-labels element
))
146 (not (org-element-property :use-labels element
))))))
147 ;; 4. "-n" or "+n" should number lines, retain labels and use them
149 (org-test-with-temp-text "#+BEGIN_EXAMPLE -n\nText.\n#+END_EXAMPLE"
150 (let ((element (org-element-current-element)))
151 (should (and (org-element-property :number-lines element
)
152 (org-element-property :retain-labels element
)
153 (org-element-property :use-labels element
)))))
154 (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp -n\n(+ 1 1)\n#+END_SRC"
155 (let ((element (org-element-current-element)))
156 (should (and (org-element-property :number-lines element
)
157 (org-element-property :retain-labels element
)
158 (org-element-property :use-labels element
)))))
159 (org-test-with-temp-text "#+BEGIN_EXAMPLE +n\nText.\n#+END_EXAMPLE"
160 (let ((element (org-element-current-element)))
161 (should (and (org-element-property :number-lines element
)
162 (org-element-property :retain-labels element
)
163 (org-element-property :use-labels element
)))))
164 (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp +n\n(+ 1 1)\n#+END_SRC"
165 (let ((element (org-element-current-element)))
166 (should (and (org-element-property :number-lines element
)
167 (org-element-property :retain-labels element
)
168 (org-element-property :use-labels element
)))))
169 ;; 5. No switch should not number lines, but retain labels and use
171 (org-test-with-temp-text "#+BEGIN_EXAMPLE\nText.\n#+END_EXAMPLE"
172 (let ((element (org-element-current-element)))
173 (should (and (not (org-element-property :number-lines element
))
174 (org-element-property :retain-labels element
)
175 (org-element-property :use-labels element
)))))
176 (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp\n(+ 1 1)\n#+END_SRC"
177 (let ((element (org-element-current-element)))
178 (should (and (not (org-element-property :number-lines element
))
179 (org-element-property :retain-labels element
)
180 (org-element-property :use-labels element
)))))
181 ;; 6. "-r" switch only: do not number lines, remove labels, and
182 ;; don't use labels in coderefs.
183 (org-test-with-temp-text "#+BEGIN_EXAMPLE -r\nText.\n#+END_EXAMPLE"
184 (let ((element (org-element-current-element)))
185 (should (and (not (org-element-property :number-lines element
))
186 (not (org-element-property :retain-labels element
))
187 (not (org-element-property :use-labels element
))))))
188 (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp -r\n(+ 1 1)\n#+END_SRC"
189 (let ((element (org-element-current-element)))
190 (should (and (not (org-element-property :number-lines element
))
191 (not (org-element-property :retain-labels element
))
192 (not (org-element-property :use-labels element
))))))
193 ;; 7. Recognize coderefs with user-defined syntax.
194 (org-test-with-temp-text
195 "#+BEGIN_EXAMPLE -l \"[ref:%s]\"\nText [ref:text]\n#+END_EXAMPLE"
196 (let ((element (org-element-current-element)))
198 (equal (org-element-property :label-fmt element
) "[ref:%s]"))))
199 (org-test-with-temp-text
200 "#+BEGIN_SRC emacs-lisp -l \"[ref:%s]\"\n(+ 1 1) [ref:text]\n#+END_SRC"
201 (let ((element (org-element-current-element)))
203 (equal (org-element-property :label-fmt element
) "[ref:%s]"))))))
207 ;;;; Footnotes references and definitions
209 (ert-deftest test-org-element
/footnote-reference
()
210 "Test footnote-reference parsing."
211 ;; 1. Parse a standard reference.
212 (org-test-with-temp-text "[fn:label]"
213 (should (equal (org-element-footnote-reference-parser)
215 (:label
"fn:label" :type standard
:inline-definition nil
216 :begin
1 :end
11 :post-blank
0)))))
217 ;; 2. Parse a normalized reference.
218 (org-test-with-temp-text "[1]"
219 (should (equal (org-element-footnote-reference-parser)
221 (:label
"1" :type standard
:inline-definition nil
222 :begin
1 :end
4 :post-blank
0)))))
223 ;; 3. Parse an inline reference.
224 (org-test-with-temp-text "[fn:test:def]"
225 (should (equal (org-element-footnote-reference-parser)
227 (:label
"fn:test" :type inline
:inline-definition
("def")
228 :begin
1 :end
14 :post-blank
0)))))
229 ;; 4. Parse an anonymous reference.
230 (org-test-with-temp-text "[fn::def]"
231 (should (equal (org-element-footnote-reference-parser)
233 (:label nil
:type inline
:inline-definition
("def")
234 :begin
1 :end
10 :post-blank
0)))))
235 ;; 5. Parse nested footnotes.
236 (org-test-with-temp-text "[fn::def [fn:label]]"
239 (org-element-footnote-reference-parser)
241 (:label nil
:type inline
245 (:label
"fn:label" :type standard
:inline-definition nil
246 :begin
5 :end
15 :post-blank
0)))
247 :begin
1 :end
21 :post-blank
0)))))
248 ;; 6. Parse adjacent footnotes.
249 (org-test-with-temp-text "[fn:label1][fn:label2]"
252 (org-element-footnote-reference-parser)
254 (:label
"fn:label1" :type standard
:inline-definition nil
:begin
1
255 :end
12 :post-blank
0)))))
256 ;; 7. Only properly closed footnotes are recognized as such.
257 (org-test-with-temp-text "Text [fn:label"
260 (org-element-parse-buffer) 'footnote-reference
'identity
))))
266 (ert-deftest test-org-element
/granularity
()
267 "Test granularity impact on buffer parsing."
268 (org-test-with-temp-text "
275 ;; 1.1. Granularity set to `headline' should parse every headline
276 ;; in buffer, and only them.
277 (let ((tree (org-element-parse-buffer 'headline
)))
278 (should (= 2 (length (org-element-map tree
'headline
'identity
))))
279 (should-not (org-element-map tree
'paragraph
'identity
)))
280 ;; 1.2. Granularity set to `greater-element' should not enter
281 ;; greater elements excepted headlines and sections.
282 (let ((tree (org-element-parse-buffer 'greater-element
)))
283 (should (= 1 (length (org-element-map tree
'center-block
'identity
))))
284 (should (= 1 (length (org-element-map tree
'paragraph
'identity
))))
285 (should-not (org-element-map tree
'entity
'identity
)))
286 ;; 1.3. Granularity set to `element' should enter every
288 (let ((tree (org-element-parse-buffer 'element
)))
289 (should (= 2 (length (org-element-map tree
'paragraph
'identity
))))
290 (should-not (org-element-map tree
'entity
'identity
)))
291 ;; 1.4. Granularity set to `object' can see everything.
292 (let ((tree (org-element-parse-buffer 'object
)))
293 (should (= 1 (length (org-element-map tree
'entity
'identity
)))))))
295 (ert-deftest test-org-element
/secondary-string-parsing
()
296 "Test if granularity correctly toggles secondary strings parsing."
297 ;; 1. With a granularity bigger than `object', no secondary string
300 ;; 1.1. Test with `headline' type.
301 (org-test-with-temp-text "* Headline"
303 (org-element-map (org-element-parse-buffer 'headline
) 'headline
307 (should (stringp (org-element-property :title headline
)))))
308 ;; 1.2. Test with `item' type.
309 (org-test-with-temp-text "* Headline\n- tag :: item"
310 (let ((item (org-element-map (org-element-parse-buffer 'element
)
315 (should (stringp (org-element-property :tag item
)))))
316 ;; 1.3. Test with `verse-block' type.
317 (org-test-with-temp-text "#+BEGIN_VERSE\nTest\n#+END_VERSE"
318 (let ((verse-block (org-element-map (org-element-parse-buffer 'element
)
323 (should (stringp (org-element-property :value verse-block
)))))
324 ;; 1.4. Test with `inlinetask' type, if avalaible.
325 (when (featurep 'org-inlinetask
)
326 (let ((org-inlinetask-min-level 15))
327 (org-test-with-temp-text "*************** Inlinetask"
328 (let ((inlinetask (org-element-map (org-element-parse-buffer 'element
)
333 (should (stringp (org-element-property :title inlinetask
)))))))
334 ;; 2. With a default granularity, secondary strings should be
336 (org-test-with-temp-text "* Headline"
338 (org-element-map (org-element-parse-buffer) 'headline
342 (should (listp (org-element-property :title headline
)))))
343 ;; 3. `org-element-at-point' should never parse a secondary string.
344 (org-test-with-temp-text "* Headline"
345 (should (stringp (org-element-property :title
(org-element-at-point))))))
349 ;;; Navigation tools.
351 (ert-deftest test-org-element
/forward-element
()
352 "Test `org-element-forward' specifications."
353 ;; 1. At EOB: should error.
354 (org-test-with-temp-text "Some text\n"
355 (goto-char (point-max))
356 (should-error (org-element-forward)))
357 ;; 2. Standard move: expected to ignore blank lines.
358 (org-test-with-temp-text "First paragraph.\n\n\nSecond paragraph."
359 (org-element-forward)
360 (should (looking-at "Second paragraph.")))
361 ;; 3. Headline tests.
362 (org-test-with-temp-text "
367 ;; 3.1. At an headline beginning: move to next headline at the
370 (org-element-forward)
371 (should (looking-at "** Head 1.2"))
372 ;; 3.2. At an headline beginning: move to parent headline if no
373 ;; headline at the same level.
375 (org-element-forward)
376 (should (looking-at "** Head 1.2")))
377 ;; 4. Greater element tests.
378 (org-test-with-temp-text
379 "#+BEGIN_CENTER\nInside.\n#+END_CENTER\n\nOutside."
380 ;; 4.1. At a greater element: expected to skip contents.
381 (org-element-forward)
382 (should (looking-at "Outside."))
383 ;; 4.2. At the end of greater element contents: expected to skip
384 ;; to the end of the greater element.
386 (org-element-forward)
387 (should (looking-at "Outside.")))
389 (org-test-with-temp-text "
403 ;; 5.1. At list top point: expected to move to the element after
406 (org-element-forward)
407 (should (looking-at "Outside."))
408 ;; 5.2. Special case: at the first line of a sub-list, but not at
409 ;; beginning of line, move to next item.
412 (org-element-forward)
413 (should (looking-at "- item2"))
416 (org-element-forward)
417 (should (looking-at " - sub2"))
418 ;; 5.3 At sub-list beginning: expected to move after the sub-list.
420 (org-element-forward)
421 (should (looking-at " Inner paragraph."))
422 ;; 5.4. At sub-list end: expected to move outside the sub-list.
424 (org-element-forward)
425 (should (looking-at " Inner paragraph."))
426 ;; 5.5. At an item: expected to move to next item, if any.
428 (org-element-forward)
429 (should (looking-at " - sub3"))))
431 (ert-deftest test-org-element
/backward-element
()
432 "Test `org-element-backward' specifications."
433 ;; 1. At BOB (modulo some white spaces): should error.
434 (org-test-with-temp-text " \nParagraph."
435 (org-skip-whitespace)
436 (should-error (org-element-backward)))
437 ;; 2. Not at the beginning of an element: move at its beginning.
438 (org-test-with-temp-text "Paragraph1.\n\nParagraph2."
441 (org-element-backward)
442 (should (looking-at "Paragraph2.")))
443 ;; 3. Headline tests.
444 (org-test-with-temp-text "
449 ;; 3.1. At an headline beginning: move to previous headline at the
452 (org-element-backward)
453 (should (looking-at "** Head 1.1"))
454 ;; 3.2. At an headline beginning: move to parent headline if no
455 ;; headline at the same level.
457 (org-element-backward)
458 (should (looking-at "* Head 1"))
459 ;; 3.3. At the first top-level headline: should error.
461 (should-error (org-element-backward)))
462 ;; 4. At beginning of first element inside a greater element:
463 ;; expected to move to greater element's beginning.
464 (org-test-with-temp-text "Before.\n#+BEGIN_CENTER\nInside.\n#+END_CENTER."
466 (org-element-backward)
467 (should (looking-at "#\\+BEGIN_CENTER")))
469 (org-test-with-temp-text "
484 ;; 5.1. At beginning of sub-list: expected to move to the
485 ;; paragraph before it.
487 (org-element-backward)
488 (should (looking-at "item1"))
489 ;; 5.2. At an item in a list: expected to move at previous item.
491 (org-element-backward)
492 (should (looking-at " - sub2"))
494 (org-element-backward)
495 (should (looking-at "- item1"))
496 ;; 5.3. At end of list/sub-list: expected to move to list/sub-list
499 (org-element-backward)
500 (should (looking-at " - sub1"))
502 (org-element-backward)
503 (should (looking-at "- item1"))
504 ;; 5.4. At blank-lines before list end: expected to move to top
507 (org-element-backward)
508 (should (looking-at "- item1"))))
510 (ert-deftest test-org-element
/up-element
()
511 "Test `org-element-up' specifications."
512 ;; 1. At BOB or with no surrounding element: should error.
513 (org-test-with-temp-text "Paragraph."
514 (should-error (org-element-up)))
515 (org-test-with-temp-text "* Head1\n* Head2"
517 (should-error (org-element-up)))
518 (org-test-with-temp-text "Paragraph1.\n\nParagraph2."
520 (should-error (org-element-up)))
521 ;; 2. At an headline: move to parent headline.
522 (org-test-with-temp-text "* Head1\n** Sub-Head1\n** Sub-Head2"
525 (should (looking-at "\\* Head1")))
526 ;; 3. Inside a greater element: move to greater element beginning.
527 (org-test-with-temp-text
528 "Before.\n#+BEGIN_CENTER\nParagraph1\nParagraph2\n#+END_CENTER\n"
531 (should (looking-at "#\\+BEGIN_CENTER")))
533 (org-test-with-temp-text "* Top
540 Paragraph within sub2.
543 ;; 4.1. Within an item: move to the item beginning.
546 (should (looking-at " - sub2"))
547 ;; 4.2. At an item in a sub-list: move to parent item.
550 (should (looking-at "- item1"))
551 ;; 4.3. At an item in top list: move to beginning of whole list.
554 (should (looking-at "- item1"))
555 ;; 4.4. Special case. At very top point: should move to parent of
559 (should (looking-at "\\* Top"))))
561 (ert-deftest test-org-element
/down-element
()
562 "Test `org-element-down' specifications."
563 ;; 1. Error when the element hasn't got a recursive type.
564 (org-test-with-temp-text "Paragraph."
565 (should-error (org-element-down)))
566 ;; 2. When at a plain-list, move to first item.
567 (org-test-with-temp-text "- Item 1\n - Item 1.1\n - Item 2.2"
570 (should (looking-at " - Item 1.1")))
571 ;; 3. Otherwise, move inside the greater element.
572 (org-test-with-temp-text "#+BEGIN_CENTER\nParagraph.\n#+END_CENTER"
574 (should (looking-at "Paragraph"))))
576 (ert-deftest test-org-element
/drag-backward
()
577 "Test `org-element-drag-backward' specifications."
578 ;; 1. Error when trying to move first element of buffer.
579 (org-test-with-temp-text "Paragraph 1.\n\nParagraph 2."
580 (should-error (org-element-drag-backward)))
581 ;; 2. Error when trying to swap nested elements.
582 (org-test-with-temp-text "#+BEGIN_CENTER\nTest.\n#+END_CENTER"
584 (should-error (org-element-drag-backward)))
585 ;; 3. Error when trying to swap an headline element and
586 ;; a non-headline element.
587 (org-test-with-temp-text "Test.\n* Head 1"
589 (should-error (org-element-drag-backward)))
590 ;; 4. Otherwise, swap elements, preserving column and blank lines
592 (org-test-with-temp-text "Para1\n\n\nParagraph 2\n\nPara3"
593 (search-forward "graph")
594 (org-element-drag-backward)
595 (should (equal (buffer-string) "Paragraph 2\n\n\nPara1\n\nPara3"))
596 (should (looking-at " 2"))))
598 (ert-deftest test-org-element
/drag-forward
()
599 "Test `org-element-drag-forward' specifications."
600 ;; 1. Error when trying to move first element of buffer.
601 (org-test-with-temp-text "Paragraph 1.\n\nParagraph 2."
603 (should-error (org-element-drag-forward)))
604 ;; 2. Error when trying to swap nested elements.
605 (org-test-with-temp-text "#+BEGIN_CENTER\nTest.\n#+END_CENTER"
607 (should-error (org-element-drag-forward)))
608 ;; 3. Error when trying to swap a non-headline element and an
610 (org-test-with-temp-text "Test.\n* Head 1"
611 (should-error (org-element-drag-forward)))
612 ;; 4. Otherwise, swap elements, preserving column and blank lines
614 (org-test-with-temp-text "Paragraph 1\n\n\nPara2\n\nPara3"
615 (search-forward "graph")
616 (org-element-drag-forward)
617 (should (equal (buffer-string) "Para2\n\n\nParagraph 1\n\nPara3"))
618 (should (looking-at " 1"))))
621 (provide 'test-org-element
)
622 ;;; test-org-element.el ends here