1 ;;; test-org-export.el --- Tests for org-export.el
3 ;; Copyright (C) 2012 Nicolas Goaziou
5 ;; Author: Nicolas Goaziou <n.goaziou at gmail dot com>
7 ;; Released under the GNU General Public License version 3
8 ;; see: http://www.gnu.org/licenses/gpl-3.0.html
16 (unless (featurep 'org-export
)
17 (signal 'missing-test-dependency
"org-export"))
23 (defmacro org-test-with-backend
(backend &rest body
)
24 "Execute body with an export back-end defined.
26 BACKEND is the name, as a string, of the back-end. BODY is the
27 body to execute. The defined back-end simply returns parsed data
29 (declare (debug (form body
)) (indent 1))
30 `(flet ,(let (transcoders)
31 (dolist (type (append org-element-all-elements
32 org-element-all-objects
)
34 (push `(,(intern (format "org-%s-%s" backend type
))
36 (,(intern (format "org-element-%s-interpreter" type
))
41 (defmacro org-test-with-parsed-data
(data &rest body
)
42 "Execute body with parsed data available.
44 DATA is a string containing the data to be parsed. BODY is the
45 body to execute. Parse tree is available under the `tree'
46 variable, and communication channel under `info'.
48 This function calls `org-export-collect-tree-properties'. As
49 such, `:ignore-list' (for `org-element-map') and
50 `:parse-tree' (for `org-export-get-genealogy') properties are
51 already filled in `info'."
52 (declare (debug (form body
)) (indent 1))
53 `(org-test-with-temp-text ,data
54 (let* ((tree (org-element-parse-buffer))
55 (info (org-export-collect-tree-properties tree nil
)))
58 (ert-deftest test-org-export
/parse-option-keyword
()
59 "Test reading all standard #+OPTIONS: items."
62 (org-export-parse-option-keyword
63 "H:1 num:t \\n:t timestamp:t arch:t author:t creator:t d:t email:t
64 *:t e:t ::t f:t pri:t -:t ^:t toc:t |:t tags:t tasks:t <:t todo:t")
66 1 :preserve-breaks t
:section-numbers t
:time-stamp-file t
67 :with-archived-trees t
:with-author t
:with-creator t
:with-drawers t
68 :with-email t
:with-emphasize t
:with-entities t
:with-fixed-width t
69 :with-footnotes t
:with-priority t
:with-special-strings t
70 :with-sub-superscript t
:with-toc t
:with-tables t
:with-tags t
71 :with-tasks t
:with-timestamps t
:with-todo-keywords t
)))
72 ;; Test some special values.
75 (org-export-parse-option-keyword
76 "arch:headline creator:comment d:(\"TEST\")
77 ^:{} toc:1 tags:not-in-toc tasks:todo num:2 <:active")
80 :with-archived-trees headline
:with-creator comment
81 :with-drawers
("TEST") :with-sub-superscript
{} :with-toc
1
82 :with-tags not-in-toc
:with-tasks todo
:with-timestamps active
))))
84 (ert-deftest test-org-export
/get-inbuffer-options
()
85 "Test reading all standard export keywords."
88 (org-test-with-temp-text "#+AUTHOR: Me, Myself and I
91 #+DESCRIPTION: Testing
92 #+DESCRIPTION: with two lines
93 #+EMAIL: some@email.org
94 #+EXPORT_EXCLUDE_TAGS: noexport invisible
97 #+EXPORT_SELECT_TAGS: export
100 (org-export-get-inbuffer-options))
102 ("Me, Myself and I") :creator
"Idem" :date
"Today"
103 :description
"Testing\nwith two lines" :email
"some@email.org"
104 :exclude-tags
("noexport" "invisible") :keywords
"test" :language
"en"
105 :select-tags
("export") :title
("Some title with spaces")))))
107 (ert-deftest test-org-export
/define-macro
()
108 "Try defining various Org macro using in-buffer #+MACRO: keyword."
110 (should (equal (org-test-with-temp-text "#+MACRO: one 1"
111 (org-export-get-inbuffer-options))
112 '(:macro-one
("1"))))
114 (should (equal (org-test-with-temp-text "#+MACRO: two (eval (+ 1 1))"
115 (org-export-get-inbuffer-options))
116 '(:macro-two
"(eval (+ 1 1))")))
118 (should-not (org-test-with-temp-text "#+MACRO: three"
119 (org-export-get-inbuffer-options)))
120 ;; Macro with newline character.
121 (should (equal (org-test-with-temp-text "#+MACRO: four a\\nb"
122 (org-export-get-inbuffer-options))
123 '(:macro-four
("a\nb"))))
124 ;; Macro with protected newline character.
125 (should (equal (org-test-with-temp-text "#+MACRO: five a\\\\nb"
126 (org-export-get-inbuffer-options))
127 '(:macro-five
("a\\nb"))))
129 (org-test-with-temp-text "#+MACRO: six 6\n#+MACRO: seven 1 + {{{six}}}"
132 (org-export-get-inbuffer-options)
136 ("1 + " (macro (:key
"six" :value
"{{{six}}}" :args nil
:begin
5 :end
14
137 :post-blank
0))))))))
139 (ert-deftest test-org-export
/handle-options
()
140 "Test if export options have an impact on output."
141 ;; Test exclude tags.
142 (org-test-with-temp-text "* Head1 :noexport:"
143 (org-test-with-backend "test"
145 (equal (org-export-as 'test nil nil nil
'(:exclude-tags
("noexport")))
147 ;; Test include tags.
148 (org-test-with-temp-text "
150 ** Sub-Head1.1 :export:
153 (org-test-with-backend "test"
156 "\\* Head1\n\\*\\* Sub-Head1.1[ \t]+:export:\n\\*\\*\\* Sub-Head1.1.1\n"
157 (org-export-as 'test nil nil nil
'(:select-tags
("export")))))))
158 ;; Test mixing include tags and exclude tags.
159 (org-test-with-temp-text "
161 ** Sub-Head1 :noexport:
164 ** Sub-Head1 :export:"
165 (org-test-with-backend "test"
168 "\\* Head1[ \t]+:export:\n\\*\\* Sub-Head2\n"
171 '(:select-tags
("export") :exclude-tags
("noexport")))))))
173 (let ((org-todo-keywords '((sequence "TODO" "DONE"))))
174 (org-test-with-temp-text "* TODO Head1"
175 (org-test-with-backend "test"
176 (should (equal (org-export-as 'test nil nil nil
'(:with-tasks nil
))
178 (let ((org-todo-keywords '((sequence "TODO" "DONE"))))
179 (org-test-with-temp-text "* TODO Head1"
180 (org-test-with-backend "test"
181 (should (equal (org-export-as 'test nil nil nil
'(:with-tasks t
))
182 "* TODO Head1\n")))))
184 (org-test-with-temp-text "* Head1 :archive:"
185 (let ((org-archive-tag "archive"))
186 (org-test-with-backend "test"
188 (equal (org-export-as 'test nil nil nil
'(:with-archived-trees nil
))
190 (org-test-with-temp-text "* Head1 :archive:\nbody\n** Sub-head 2"
191 (let ((org-archive-tag "archive"))
192 (org-test-with-backend "test"
195 "\\* Head1[ \t]+:archive:"
196 (org-export-as 'test nil nil nil
197 '(:with-archived-trees headline
)))))))
198 (org-test-with-temp-text "* Head1 :archive:"
199 (let ((org-archive-tag "archive"))
200 (org-test-with-backend "test"
203 "\\`\\* Head1[ \t]+:archive:\n\\'"
204 (org-export-as 'test nil nil nil
'(:with-archived-trees t
)))))))
206 (let ((org-drawers '("TEST")))
207 (org-test-with-temp-text ":TEST:\ncontents\n:END:"
208 (org-test-with-backend "test"
209 (should (equal (org-export-as 'test nil nil nil
'(:with-drawers nil
))
211 (should (equal (org-export-as 'test nil nil nil
'(:with-drawers t
))
212 ":TEST:\ncontents\n:END:\n")))))
213 (let ((org-drawers '("FOO" "BAR")))
214 (org-test-with-temp-text ":FOO:\nkeep\n:END:\n:BAR:\nremove\n:END:"
215 (org-test-with-backend "test"
217 (equal (org-export-as 'test nil nil nil
'(:with-drawers
("FOO")))
218 ":FOO:\nkeep\n:END:\n")))))
220 (org-test-with-temp-text "[2012-04-29 sun. 10:45]<2012-04-29 sun. 10:45>"
221 (org-test-with-backend "test"
223 (equal (org-export-as 'test nil nil nil
'(:with-timestamps t
))
224 "[2012-04-29 sun. 10:45]<2012-04-29 sun. 10:45>\n"))
226 (equal (org-export-as 'test nil nil nil
'(:with-timestamps nil
)) ""))
228 (equal (org-export-as 'test nil nil nil
'(:with-timestamps active
))
229 "<2012-04-29 sun. 10:45>\n"))
231 (equal (org-export-as 'test nil nil nil
'(:with-timestamps inactive
))
232 "[2012-04-29 sun. 10:45]\n"))))
234 (let ((org-clock-string "CLOCK:"))
235 (org-test-with-temp-text "CLOCK: [2012-04-29 sun. 10:45]"
236 (org-test-with-backend "test"
238 (equal (org-export-as 'test nil nil nil
'(:with-clocks t
))
239 "CLOCK: [2012-04-29 sun. 10:45]\n"))
241 (equal (org-export-as 'test nil nil nil
'(:with-clocks nil
)) "")))))
243 (let ((org-closed-string "CLOSED:"))
244 (org-test-with-temp-text "CLOSED: [2012-04-29 sun. 10:45]"
245 (org-test-with-backend "test"
247 (equal (org-export-as 'test nil nil nil
'(:with-plannings t
))
248 "CLOSED: [2012-04-29 sun. 10:45]\n"))
250 (equal (org-export-as 'test nil nil nil
'(:with-plannings nil
))
253 (ert-deftest test-org-export
/comment-tree
()
254 "Test if export process ignores commented trees."
255 (let ((org-comment-string "COMMENT"))
256 (org-test-with-temp-text "* COMMENT Head1"
257 (org-test-with-backend "test"
258 (should (equal (org-export-as 'test
) ""))))))
260 (ert-deftest test-org-export
/export-scope
()
261 "Test all export scopes."
262 (org-test-with-temp-text "
267 (org-test-with-backend "test"
270 (should (equal (org-export-as 'test
'subtree
) "text\n*** Head3\n"))
272 (goto-char (point-min))
275 (should (equal (org-export-as 'test nil
'visible
) "* Head1\n"))
277 (flet ((org-test-template (body info
) (format "BEGIN\n%sEND" body
)))
278 (should (equal (org-export-as 'test nil nil
'body-only
)
279 "* Head1\n** Head2\ntext\n*** Head3\n"))
280 (should (equal (org-export-as 'test
)
281 "BEGIN\n* Head1\n** Head2\ntext\n*** Head3\nEND")))
283 (goto-char (point-min))
285 (transient-mark-mode 1)
286 (push-mark (point) t t
)
287 (goto-char (point-at-eol))
288 (should (equal (org-export-as 'test
) "text\n"))))
289 ;; Subtree with a code block calling another block outside.
290 (org-test-with-temp-text "
292 #+BEGIN_SRC emacs-lisp :noweb yes :exports results
297 #+BEGIN_SRC emacs-lisp
300 (org-test-with-backend "test"
302 (should (equal (org-export-as 'test
'subtree
) ": 3\n")))))
304 (ert-deftest test-org-export
/export-snippet
()
305 "Test export snippets transcoding."
306 (org-test-with-temp-text "<test@A><t@B>"
307 (org-test-with-backend "test"
308 (flet ((org-test-export-snippet
309 (snippet contents info
)
310 (when (eq (org-export-snippet-backend snippet
) 'test
)
311 (org-element-property :value snippet
))))
312 (let ((org-export-snippet-translation-alist nil
))
313 (should (equal (org-export-as 'test
) "A\n")))
314 (let ((org-export-snippet-translation-alist '(("t" .
"test"))))
315 (should (equal (org-export-as 'test
) "AB\n")))))))
317 (ert-deftest test-org-export
/expand-include
()
318 "Test file inclusion in an Org buffer."
319 ;; Full insertion with recursive inclusion.
320 (org-test-with-temp-text
321 (format "#+INCLUDE: \"%s/examples/include.org\"" org-test-dir
)
322 (org-export-expand-include-keyword)
323 (should (equal (buffer-string)
324 "Small Org file with an include keyword.
326 #+BEGIN_SRC emacs-lisp :exports results\n(+ 2 1)\n#+END_SRC
332 ;; Localized insertion.
333 (org-test-with-temp-text
334 (format "#+INCLUDE: \"%s/examples/include.org\" :lines \"1-2\""
336 (org-export-expand-include-keyword)
337 (should (equal (buffer-string)
338 "Small Org file with an include keyword.\n")))
339 ;; Insertion with constraints on headlines level.
340 (org-test-with-temp-text
342 "* Top heading\n#+INCLUDE: \"%s/examples/include.org\" :lines \"9-\""
344 (org-export-expand-include-keyword)
345 (should (equal (buffer-string) "* Top heading\n** Heading\nbody\n")))
346 ;; Inclusion within an example block.
347 (org-test-with-temp-text
348 (format "#+INCLUDE: \"%s/examples/include.org\" :lines \"1-2\" example"
350 (org-export-expand-include-keyword)
354 "#+BEGIN_EXAMPLE\nSmall Org file with an include keyword.\n#+END_EXAMPLE\n")))
355 ;; Inclusion within a src-block.
356 (org-test-with-temp-text
358 "#+INCLUDE: \"%s/examples/include.org\" :lines \"4-5\" src emacs-lisp"
360 (org-export-expand-include-keyword)
361 (should (equal (buffer-string)
362 "#+BEGIN_SRC emacs-lisp\n(+ 2 1)\n#+END_SRC\n"))))
364 (ert-deftest test-org-export
/user-ignore-list
()
365 "Test if `:ignore-list' accepts user input."
366 (org-test-with-backend "test"
367 (flet ((skip-note-head
369 ;; Ignore headlines with the word "note" in their title.
373 (when (string-match "\\<note\\>"
374 (org-element-property :raw-value headline
))
375 (org-export-ignore-element headline info
)))
378 ;; Install function in parse tree filters.
379 (let ((org-export-filter-parse-tree-functions '(skip-note-head)))
380 (org-test-with-temp-text "* Head1\n* Head2 (note)\n"
381 (should (equal (org-export-as 'test
) "* Head1\n")))))))
383 (ert-deftest test-org-export
/before-parsing-hook
()
384 "Test `org-export-before-parsing-hook'."
385 (org-test-with-backend "test"
386 (org-test-with-temp-text "* Headline 1\nBody 1\n* Headline 2\nBody 2"
387 (let ((org-export-before-parsing-hook
391 (delete-region (point) (progn (forward-line) (point)))))))))
392 (should (equal (org-export-as 'test
) "Body 1\nBody 2\n"))))))
398 (ert-deftest test-org-export
/footnotes
()
399 "Test footnotes specifications."
400 (let ((org-footnote-section nil
))
401 ;; 1. Read every type of footnote.
402 (org-test-with-temp-text
403 "Text[fn:1] [1] [fn:label:C] [fn::D]\n\n[fn:1] A\n\n[1] B"
404 (let* ((tree (org-element-parse-buffer))
405 (info (org-export-store-footnote-definitions
406 `(:parse-tree
,tree
:with-footnotes t
))))
409 '((1 .
"A") (2 .
"B") (3 .
"C") (4 .
"D"))
411 tree
'footnote-reference
413 (let ((def (org-export-get-footnote-definition ref info
)))
414 (cons (org-export-get-footnote-number ref info
)
415 (if (eq (org-element-property :type ref
) 'inline
) (car def
)
416 (car (org-element-contents
417 (car (org-element-contents def
))))))))
419 ;; 2. Test nested footnotes order.
420 (org-test-with-temp-text
421 "Text[fn:1:A[fn:2]] [fn:3].\n\n[fn:2] B [fn:3] [fn::D].\n\n[fn:3] C."
422 (let* ((tree (org-element-parse-buffer))
423 (info (org-export-store-footnote-definitions
424 `(:parse-tree
,tree
:with-footnotes t
))))
427 '((1 .
"fn:1") (2 .
"fn:2") (3 .
"fn:3") (4))
429 tree
'footnote-reference
431 (when (org-export-footnote-first-reference-p ref info
)
432 (cons (org-export-get-footnote-number ref info
)
433 (org-element-property :label ref
))))
435 ;; 3. Test nested footnote in invisible definitions.
436 (org-test-with-temp-text "Text[1]\n\n[1] B [2]\n\n[2] C."
438 (narrow-to-region (point) (point-at-eol))
439 (let* ((tree (org-element-parse-buffer))
440 (info (org-export-store-footnote-definitions
441 `(:parse-tree
,tree
:with-footnotes t
))))
442 ;; Both footnotes should be seen.
444 (= (length (org-export-collect-footnote-definitions tree info
)) 2))))
445 ;; 4. Test footnotes definitions collection.
446 (org-test-with-temp-text "Text[fn:1:A[fn:2]] [fn:3].
448 \[fn:2] B [fn:3] [fn::D].
451 (let* ((tree (org-element-parse-buffer))
452 (info (org-export-store-footnote-definitions
453 `(:parse-tree
,tree
:with-footnotes t
))))
454 (should (= (length (org-export-collect-footnote-definitions tree info
))
456 ;; 5. Test export of footnotes defined outside parsing scope.
457 (org-test-with-temp-text "[fn:1] Out of scope
460 (org-test-with-backend "test"
461 (flet ((org-test-footnote-reference
462 (fn-ref contents info
)
463 (org-element-interpret-data
464 (org-export-get-footnote-definition fn-ref info
))))
466 (should (equal "ParagraphOut of scope\n"
467 (org-export-as 'test
'subtree
))))))))
473 (ert-deftest test-org-export
/fuzzy-links
()
474 "Test fuzzy link export specifications."
475 ;; 1. Links to invisible (keyword) targets should be ignored.
476 (org-test-with-parsed-data
477 "Paragraph.\n#+TARGET: Test\n[[Test]]"
482 (org-export-get-ordinal
483 (org-export-resolve-fuzzy-link link info
) info
)) info
)))
484 ;; 2. Link to an headline should return headline's number.
485 (org-test-with-parsed-data
486 "Paragraph.\n* Head1\n* Head2\n* Head3\n[[Head2]]"
488 ;; Note: Headline's number is in fact a list of numbers.
493 (org-export-get-ordinal
494 (org-export-resolve-fuzzy-link link info
) info
)) info t
))))
495 ;; 3. Link to a target in an item should return item's number.
496 (org-test-with-parsed-data
497 "- Item1\n - Item11\n - <<test>>Item12\n- Item2\n\n\n[[test]]"
499 ;; Note: Item's number is in fact a list of numbers.
504 (org-export-get-ordinal
505 (org-export-resolve-fuzzy-link link info
) info
)) info t
))))
506 ;; 4. Link to a target in a footnote should return footnote's
508 (org-test-with-parsed-data "
509 Paragraph[1][2][fn:lbl3:C<<target>>][[test]][[target]]\n[1] A\n\n[2] <<test>>B"
515 (org-export-get-ordinal
516 (org-export-resolve-fuzzy-link link info
) info
)) info
))))
517 ;; 5. Link to a named element should return sequence number of that
519 (org-test-with-parsed-data
520 "#+NAME: tbl1\n|1|2|\n#+NAME: tbl2\n|3|4|\n#+NAME: tbl3\n|5|6|\n[[tbl2]]"
526 (org-export-get-ordinal
527 (org-export-resolve-fuzzy-link link info
) info
)) info t
))))
528 ;; 6. Link to a target not within an item, a table, a footnote
529 ;; reference or definition should return section number.
530 (org-test-with-parsed-data
531 "* Head1\n* Head2\nParagraph<<target>>\n* Head3\n[[target]]"
537 (org-export-get-ordinal
538 (org-export-resolve-fuzzy-link link info
) info
)) info t
)))))
540 (defun test-org-export/resolve-coderef
()
541 "Test `org-export-resolve-coderef' specifications."
542 (let ((org-coderef-label-format "(ref:%s)"))
543 ;; 1. A link to a "-n -k -r" block returns line number.
544 (org-test-with-temp-text
545 "#+BEGIN_EXAMPLE -n -k -r\nText (ref:coderef)\n#+END_EXAMPLE"
546 (let ((tree (org-element-parse-buffer)))
548 (= (org-export-resolve-coderef "coderef" `(:parse-tree
,tree
)) 1))))
549 (org-test-with-temp-text
550 "#+BEGIN_SRC emacs-lisp -n -k -r\n(+ 1 1) (ref:coderef)\n#+END_SRC"
551 (let ((tree (org-element-parse-buffer)))
553 (= (org-export-resolve-coderef "coderef" `(:parse-tree
,tree
)) 1))))
554 ;; 2. A link to a "-n -r" block returns line number.
555 (org-test-with-temp-text
556 "#+BEGIN_EXAMPLE -n -r\nText (ref:coderef)\n#+END_EXAMPLE"
557 (let ((tree (org-element-parse-buffer)))
559 (= (org-export-resolve-coderef "coderef" `(:parse-tree
,tree
)) 1))))
560 (org-test-with-temp-text
561 "#+BEGIN_SRC emacs-lisp -n -r\n(+ 1 1) (ref:coderef)\n#+END_SRC"
562 (let ((tree (org-element-parse-buffer)))
564 (= (org-export-resolve-coderef "coderef" `(:parse-tree
,tree
)) 1))))
565 ;; 3. A link to a "-n" block returns coderef.
566 (org-test-with-temp-text
567 "#+BEGIN_SRC emacs-lisp -n\n(+ 1 1) (ref:coderef)\n#+END_SRC"
568 (let ((tree (org-element-parse-buffer)))
570 (equal (org-export-resolve-coderef "coderef" `(:parse-tree
,tree
))
572 (org-test-with-temp-text
573 "#+BEGIN_EXAMPLE -n\nText (ref:coderef)\n#+END_EXAMPLE"
574 (let ((tree (org-element-parse-buffer)))
576 (equal (org-export-resolve-coderef "coderef" `(:parse-tree
,tree
))
578 ;; 4. A link to a "-r" block returns line number.
579 (org-test-with-temp-text
580 "#+BEGIN_SRC emacs-lisp -r\n(+ 1 1) (ref:coderef)\n#+END_SRC"
581 (let ((tree (org-element-parse-buffer)))
583 (= (org-export-resolve-coderef "coderef" `(:parse-tree
,tree
)) 1))))
584 (org-test-with-temp-text
585 "#+BEGIN_EXAMPLE -r\nText (ref:coderef)\n#+END_EXAMPLE"
586 (let ((tree (org-element-parse-buffer)))
588 (= (org-export-resolve-coderef "coderef" `(:parse-tree
,tree
)) 1))))
589 ;; 5. A link to a block without a switch returns coderef.
590 (org-test-with-temp-text
591 "#+BEGIN_SRC emacs-lisp\n(+ 1 1) (ref:coderef)\n#+END_SRC"
592 (let ((tree (org-element-parse-buffer)))
594 (equal (org-export-resolve-coderef "coderef" `(:parse-tree
,tree
))
596 (org-test-with-temp-text
597 "#+BEGIN_EXAMPLE\nText (ref:coderef)\n#+END_EXAMPLE"
598 (let ((tree (org-element-parse-buffer)))
600 (equal (org-export-resolve-coderef "coderef" `(:parse-tree
,tree
))
602 ;; 6. Correctly handle continued line numbers. A "+n" switch
603 ;; should resume numbering from previous block with numbered
604 ;; lines, ignoring blocks not numbering lines in the process.
605 ;; A "-n" switch resets count.
606 (org-test-with-temp-text "
611 #+BEGIN_SRC emacs-lisp
615 #+BEGIN_SRC emacs-lisp +n -r
616 \(+ 1 1) (ref:addition)
619 #+BEGIN_EXAMPLE -n -r
620 Another text. (ref:text)
622 (let* ((tree (org-element-parse-buffer))
623 (info `(:parse-tree
,tree
)))
624 (should (= (org-export-resolve-coderef "addition" info
) 2))
625 (should (= (org-export-resolve-coderef "text" info
) 1))))
626 ;; 7. Recognize coderef with user-specified syntax.
627 (org-test-with-temp-text
628 "#+BEGIN_EXAMPLE -l \"[ref:%s]\"\nText. [ref:text]\n#+END_EXAMPLE"
629 (let ((tree (org-element-parse-buffer)))
630 (should (equal (org-export-resolve-coderef "text" `(:parse-tree
,tree
))
635 ;;; Src-block and example-block
637 (ert-deftest test-org-export
/unravel-code
()
638 "Test `org-export-unravel-code' function."
639 (let ((org-coderef-label-format "(ref:%s)"))
640 ;; 1. Code without reference.
641 (org-test-with-temp-text "#+BEGIN_EXAMPLE\n(+ 1 1)\n#+END_EXAMPLE"
642 (should (equal (org-export-unravel-code (org-element-current-element))
644 ;; 2. Code with reference.
645 (org-test-with-temp-text
646 "#+BEGIN_EXAMPLE\n(+ 1 1) (ref:test)\n#+END_EXAMPLE"
647 (should (equal (org-export-unravel-code (org-element-current-element))
648 '("(+ 1 1)\n" (1 .
"test")))))
649 ;; 3. Code with user-defined reference.
650 (org-test-with-temp-text
651 "#+BEGIN_EXAMPLE -l \"[ref:%s]\"\n(+ 1 1) [ref:test]\n#+END_EXAMPLE"
652 (should (equal (org-export-unravel-code (org-element-current-element))
653 '("(+ 1 1)\n" (1 .
"test")))))
654 ;; 4. Code references keys are relative to the current block.
655 (org-test-with-temp-text "
664 (should (equal (org-export-unravel-code (org-element-current-element))
665 '("(+ 2 2)\n(+ 3 3)\n" (2 .
"one")))))
666 ;; 5. Free up comma-protected lines.
668 ;; 5.1. In an Org source block, every line is protected.
669 (org-test-with-temp-text
670 "#+BEGIN_SRC org\n,* Test\n,# comment\n,Text\n#+END_SRC"
671 (should (equal (org-export-unravel-code (org-element-current-element))
672 '("* Test\n# comment\nText\n"))))
673 ;; 5.2. In other blocks, only headlines, comments and keywords are
675 (org-test-with-temp-text
676 "#+BEGIN_EXAMPLE\n,* Headline\n, * Not headline\n,Keep\n#+END_EXAMPLE"
677 (should (equal (org-export-unravel-code (org-element-current-element))
678 '("* Headline\n, * Not headline\n,Keep\n"))))))
684 (ert-deftest test-org-export
/special-column
()
685 "Test if the table's special column is properly recognized."
686 ;; 1. First column is special if it contains only a special marking
687 ;; characters or empty cells.
688 (org-test-with-temp-text "
692 (org-export-table-has-special-column-p
694 (org-element-parse-buffer) 'table
'identity nil
'first-match
))))
695 ;; 2. If the column contains anything else, it isn't special.
696 (org-test-with-temp-text "
700 (org-export-table-has-special-column-p
702 (org-element-parse-buffer) 'table
'identity nil
'first-match
))))
703 ;; 3. Special marking characters are "#", "^", "*", "_", "/", "$"
705 (org-test-with-temp-text "
714 (org-export-table-has-special-column-p
716 (org-element-parse-buffer) 'table
'identity nil
'first-match
))))
717 ;; 4. A first column with only empty cells isn't considered as
719 (org-test-with-temp-text "
723 (org-export-table-has-special-column-p
725 (org-element-parse-buffer) 'table
'identity nil
'first-match
)))))
727 (ert-deftest test-org-export
/special-row
()
728 "Test if special rows in a table are properly recognized."
729 ;; 1. A row is special if it has a special marking character in the
731 (org-test-with-parsed-data "| ! | 1 |"
733 (org-export-table-row-is-special-p
734 (org-element-map tree
'table-row
'identity nil
'first-match
) info
)))
735 ;; 2. A row is special when its first field is "/"
736 (org-test-with-parsed-data "
740 (org-export-table-row-is-special-p
741 (org-element-map tree
'table-row
'identity nil
'first-match
) info
)))
742 ;; 3. A row only containing alignment cookies is also considered as
744 (org-test-with-parsed-data "| <5> | | <l> | <l22> |"
746 (org-export-table-row-is-special-p
747 (org-element-map tree
'table-row
'identity nil
'first-match
) info
)))
748 ;; 4. Everything else isn't considered as special.
749 (org-test-with-parsed-data "| a | | c |"
751 (org-export-table-row-is-special-p
752 (org-element-map tree
'table-row
'identity nil
'first-match
) info
)))
753 ;; 5. Table's rules are never considered as special rows.
754 (org-test-with-parsed-data "|---+---|"
756 (org-export-table-row-is-special-p
757 (org-element-map tree
'table-row
'identity nil
'first-match
) info
))))
759 (ert-deftest test-org-export
/has-header-p
()
760 "Test `org-export-table-has-header-p' specifications."
761 ;; 1. With an header.
762 (org-test-with-parsed-data "
767 (org-export-table-has-header-p
768 (org-element-map tree
'table
'identity info
'first-match
)
770 ;; 2. Without an header.
771 (org-test-with-parsed-data "
775 (org-export-table-has-header-p
776 (org-element-map tree
'table
'identity info
'first-match
)
778 ;; 3. Don't get fooled with starting and ending rules.
779 (org-test-with-parsed-data "
785 (org-export-table-has-header-p
786 (org-element-map tree
'table
'identity info
'first-match
)
789 (ert-deftest test-org-export
/table-row-group
()
790 "Test `org-export-table-row-group' specifications."
791 ;; 1. A rule creates a new group.
792 (org-test-with-parsed-data "
799 (mapcar (lambda (row) (org-export-table-row-group row info
))
800 (org-element-map tree
'table-row
'identity
)))))
801 ;; 2. Special rows are ignored in count.
802 (org-test-with-parsed-data "
809 (mapcar (lambda (row) (org-export-table-row-group row info
))
810 (org-element-map tree
'table-row
'identity
)))))
811 ;; 3. Double rules also are ignored in count.
812 (org-test-with-parsed-data "
820 (mapcar (lambda (row) (org-export-table-row-group row info
))
821 (org-element-map tree
'table-row
'identity
))))))
823 (ert-deftest test-org-export
/table-cell-width
()
824 "Test `org-export-table-cell-width' specifications."
825 ;; 1. Width is primarily determined by width cookies. If no cookie
826 ;; is found, cell's width is nil.
827 (org-test-with-parsed-data "
828 | / | <l> | <6> | <l7> |
833 (mapcar (lambda (cell) (org-export-table-cell-width cell info
))
834 (org-element-map tree
'table-cell
'identity info
)))))
835 ;; 2. The last width cookie has precedence.
836 (org-test-with-parsed-data "
843 (mapcar (lambda (cell) (org-export-table-cell-width cell info
))
844 (org-element-map tree
'table-cell
'identity info
)))))
845 ;; 3. Valid width cookies must have a specific row.
846 (org-test-with-parsed-data "| <6> | cell |"
850 (mapcar (lambda (cell) (org-export-table-cell-width cell info
))
851 (org-element-map tree
'table-cell
'identity
))))))
853 (ert-deftest test-org-export
/table-cell-alignment
()
854 "Test `org-export-table-cell-alignment' specifications."
855 (let ((org-table-number-fraction 0.5)
856 (org-table-number-regexp "^[0-9]+$"))
857 ;; 1. Alignment is primarily determined by alignment cookies.
858 (org-test-with-temp-text "| <l> | <c> | <r> |"
859 (let* ((tree (org-element-parse-buffer))
860 (info `(:parse-tree
,tree
)))
864 (mapcar (lambda (cell) (org-export-table-cell-alignment cell info
))
865 (org-element-map tree
'table-cell
'identity
))))))
866 ;; 2. The last alignment cookie has precedence.
867 (org-test-with-temp-text "
871 (let* ((tree (org-element-parse-buffer))
872 (info `(:parse-tree
,tree
)))
876 (mapcar (lambda (cell) (org-export-table-cell-alignment cell info
))
877 (org-element-map tree
'table-cell
'identity
))))))
878 ;; 3. If there's no cookie, cell's contents determine alignment.
879 ;; A column mostly made of cells containing numbers will align
880 ;; its cells to the right.
881 (org-test-with-temp-text "
885 (let* ((tree (org-element-parse-buffer))
886 (info `(:parse-tree
,tree
)))
890 (mapcar (lambda (cell)
891 (org-export-table-cell-alignment cell info
))
892 (org-element-map tree
'table-cell
'identity
))))))
893 ;; 5. Otherwise, they will be aligned to the left.
894 (org-test-with-temp-text "
898 (let* ((tree (org-element-parse-buffer))
899 (info `(:parse-tree
,tree
)))
903 (mapcar (lambda (cell)
904 (org-export-table-cell-alignment cell info
))
905 (org-element-map tree
'table-cell
'identity
))))))))
907 (ert-deftest test-org-export
/table-cell-borders
()
908 "Test `org-export-table-cell-borders' specifications."
909 ;; 1. Recognize various column groups indicators.
910 (org-test-with-parsed-data "| / | < | > | <> |"
913 '((right bottom top
) (left bottom top
) (right bottom top
)
914 (right left bottom top
))
915 (mapcar (lambda (cell)
916 (org-export-table-cell-borders cell info
))
917 (org-element-map tree
'table-cell
'identity
)))))
918 ;; 2. Accept shortcuts to define column groups.
919 (org-test-with-parsed-data "| / | < | < |"
922 '((right bottom top
) (right left bottom top
) (left bottom top
))
923 (mapcar (lambda (cell)
924 (org-export-table-cell-borders cell info
))
925 (org-element-map tree
'table-cell
'identity
)))))
926 ;; 3. A valid column groups row must start with a "/".
927 (org-test-with-parsed-data "
931 (equal '((top) (top) (bottom) (bottom))
932 (mapcar (lambda (cell)
933 (org-export-table-cell-borders cell info
))
934 (org-element-map tree
'table-cell
'identity
)))))
935 ;; 4. Take table rules into consideration.
936 (org-test-with-parsed-data "
941 (equal '((below top
) (bottom above
))
942 (mapcar (lambda (cell)
943 (org-export-table-cell-borders cell info
))
944 (org-element-map tree
'table-cell
'identity
)))))
945 ;; 5. Top and (resp. bottom) rules induce both `top' and `above'
946 ;; (resp. `bottom' and `below') borders. Any special row is
948 (org-test-with-parsed-data "
954 (equal '((bottom below top above
))
956 (mapcar (lambda (cell)
957 (org-export-table-cell-borders cell info
))
958 (org-element-map tree
'table-cell
'identity
)))))))
960 (ert-deftest test-org-export
/table-dimensions
()
961 "Test `org-export-table-dimensions' specifications."
963 (org-test-with-parsed-data "
968 (org-export-table-dimensions
969 (org-element-map tree
'table
'identity info
'first-match
) info
))))
970 ;; 2. Ignore horizontal rules and special columns.
971 (org-test-with-parsed-data "
978 (org-export-table-dimensions
979 (org-element-map tree
'table
'identity info
'first-match
) info
)))))
981 (ert-deftest test-org-export
/table-cell-address
()
982 "Test `org-export-table-cell-address' specifications."
983 ;; 1. Standard test: index is 0-based.
984 (org-test-with-parsed-data "| a | b |"
986 (equal '((0 .
0) (0 .
1))
989 (lambda (cell) (org-export-table-cell-address cell info
))
991 ;; 2. Special column isn't counted, nor are special rows.
992 (org-test-with-parsed-data "
997 (org-export-table-cell-address
998 (car (last (org-element-map tree
'table-cell
'identity info
)))
1000 ;; 3. Tables rules do not count either.
1001 (org-test-with-parsed-data "
1009 (org-export-table-cell-address
1010 (car (last (org-element-map tree
'table-cell
'identity info
)))
1012 ;; 4. Return nil for special cells.
1013 (org-test-with-parsed-data "| / | a |"
1015 (org-export-table-cell-address
1016 (org-element-map tree
'table-cell
'identity nil
'first-match
)
1019 (ert-deftest test-org-export
/get-table-cell-at
()
1020 "Test `org-export-get-table-cell-at' specifications."
1021 ;; 1. Address ignores special columns, special rows and rules.
1022 (org-test-with-parsed-data "
1029 (org-element-contents
1030 (org-export-get-table-cell-at
1032 (org-element-map tree
'table
'identity info
'first-match
)
1034 ;; 2. Return value for a non-existent address is nil.
1035 (org-test-with-parsed-data "| a |"
1037 (org-export-get-table-cell-at
1039 (org-element-map tree
'table
'identity info
'first-match
)
1041 (org-test-with-parsed-data "| / |"
1043 (org-export-get-table-cell-at
1045 (org-element-map tree
'table
'identity info
'first-match
)
1048 (ert-deftest test-org-export
/table-cell-starts-colgroup-p
()
1049 "Test `org-export-table-cell-starts-colgroup-p' specifications."
1050 ;; 1. A cell at a beginning of a row always starts a column group.
1051 (org-test-with-parsed-data "| a |"
1053 (org-export-table-cell-starts-colgroup-p
1054 (org-element-map tree
'table-cell
'identity info
'first-match
)
1056 ;; 2. Special column should be ignored when determining the
1057 ;; beginning of the row.
1058 (org-test-with-parsed-data "
1062 (org-export-table-cell-starts-colgroup-p
1063 (org-element-map tree
'table-cell
'identity info
'first-match
)
1065 ;; 2. Explicit column groups.
1066 (org-test-with-parsed-data "
1075 (if (org-export-table-cell-starts-colgroup-p cell info
) 'yes
'no
))
1078 (ert-deftest test-org-export
/table-cell-ends-colgroup-p
()
1079 "Test `org-export-table-cell-ends-colgroup-p' specifications."
1080 ;; 1. A cell at the end of a row always ends a column group.
1081 (org-test-with-parsed-data "| a |"
1083 (org-export-table-cell-ends-colgroup-p
1084 (org-element-map tree
'table-cell
'identity info
'first-match
)
1086 ;; 2. Special column should be ignored when determining the
1087 ;; beginning of the row.
1088 (org-test-with-parsed-data "
1092 (org-export-table-cell-ends-colgroup-p
1093 (org-element-map tree
'table-cell
'identity info
'first-match
)
1095 ;; 3. Explicit column groups.
1096 (org-test-with-parsed-data "
1105 (if (org-export-table-cell-ends-colgroup-p cell info
) 'yes
'no
))
1108 (ert-deftest test-org-export
/table-row-starts-rowgroup-p
()
1109 "Test `org-export-table-row-starts-rowgroup-p' specifications."
1110 ;; 1. A row at the beginning of a table always starts a row group.
1111 ;; So does a row following a table rule.
1112 (org-test-with-parsed-data "
1122 (if (org-export-table-row-starts-rowgroup-p row info
) 'yes
'no
))
1124 ;; 2. Special rows should be ignored when determining the beginning
1126 (org-test-with-parsed-data "
1138 (if (org-export-table-row-starts-rowgroup-p row info
) 'yes
'no
))
1141 (ert-deftest test-org-export
/table-row-ends-rowgroup-p
()
1142 "Test `org-export-table-row-ends-rowgroup-p' specifications."
1143 ;; 1. A row at the end of a table always ends a row group. So does
1144 ;; a row preceding a table rule.
1145 (org-test-with-parsed-data "
1155 (if (org-export-table-row-ends-rowgroup-p row info
) 'yes
'no
))
1157 ;; 2. Special rows should be ignored when determining the beginning
1159 (org-test-with-parsed-data "
1171 (if (org-export-table-row-ends-rowgroup-p row info
) 'yes
'no
))
1174 (ert-deftest test-org-export
/table-row-starts-header-p
()
1175 "Test `org-export-table-row-starts-header-p' specifications."
1176 ;; 1. Only the row starting the first row group starts the table
1178 (org-test-with-parsed-data "
1189 (if (org-export-table-row-starts-header-p row info
) 'yes
'no
))
1191 ;; 2. A row cannot start an header if there's no header in the
1193 (org-test-with-parsed-data "
1197 (org-export-table-row-starts-header-p
1198 (org-element-map tree
'table-row
'identity info
'first-match
)
1201 (ert-deftest test-org-export
/table-row-ends-header-p
()
1202 "Test `org-export-table-row-ends-header-p' specifications."
1203 ;; 1. Only the row starting the first row group starts the table
1205 (org-test-with-parsed-data "
1216 (if (org-export-table-row-ends-header-p row info
) 'yes
'no
))
1218 ;; 2. A row cannot start an header if there's no header in the
1220 (org-test-with-parsed-data "
1224 (org-export-table-row-ends-header-p
1225 (org-element-map tree
'table-row
'identity info
'first-match
)
1229 (provide 'test-org-export
)
1230 ;;; test-org-export.el end here