Merge branch 'maint'
[org-mode/org-mode-NeilSmithlineMods.git] / testing / lisp / test-org-export.el
blob244d0df2d4ba8b4234bdaebea7b2407cf77f20a1
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
10 ;;;; Comments
14 ;;; Code:
16 (unless (featurep 'org-export)
17 (signal 'missing-test-dependency "org-export"))
21 ;;; Tests
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
28 as Org syntax."
29 (declare (debug (form body)) (indent 1))
30 `(flet ,(let (transcoders)
31 (dolist (type (append org-element-all-elements
32 org-element-all-objects)
33 transcoders)
34 (push `(,(intern (format "org-%s-%s" backend type))
35 (obj contents info)
36 (,(intern (format "org-element-%s-interpreter" type))
37 obj contents))
38 transcoders)))
39 ,@body))
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)))
56 ,@body)))
58 (ert-deftest test-org-export/parse-option-keyword ()
59 "Test reading all standard #+OPTIONS: items."
60 (should
61 (equal
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")
65 '(:headline-levels
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.
73 (should
74 (equal
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")
78 '( :section-numbers
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."
86 (should
87 (equal
88 (org-test-with-temp-text "#+AUTHOR: Me, Myself and I
89 #+CREATOR: Idem
90 #+DATE: Today
91 #+DESCRIPTION: Testing
92 #+DESCRIPTION: with two lines
93 #+EMAIL: some@email.org
94 #+EXPORT_EXCLUDE_TAGS: noexport invisible
95 #+KEYWORDS: test
96 #+LANGUAGE: en
97 #+EXPORT_SELECT_TAGS: export
98 #+TITLE: Some title
99 #+TITLE: with spaces"
100 (org-export-get-inbuffer-options))
101 '(:author
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."
109 ;; Parsed macro.
110 (should (equal (org-test-with-temp-text "#+MACRO: one 1"
111 (org-export-get-inbuffer-options))
112 '(:macro-one ("1"))))
113 ;; Evaled macro.
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))")))
117 ;; Incomplete macro.
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"))))
128 ;; Recursive macro.
129 (org-test-with-temp-text "#+MACRO: six 6\n#+MACRO: seven 1 + {{{six}}}"
130 (should
131 (equal
132 (org-export-get-inbuffer-options)
133 '(:macro-six
134 ("6")
135 :macro-seven
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"
144 (should
145 (equal (org-export-as 'test nil nil nil '(:exclude-tags ("noexport")))
146 ""))))
147 ;; Test include tags.
148 (org-test-with-temp-text "
149 * Head1
150 ** Sub-Head1.1 :export:
151 *** Sub-Head1.1.1
152 * Head2"
153 (org-test-with-backend "test"
154 (should
155 (string-match
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 "
160 * Head1 :export:
161 ** Sub-Head1 :noexport:
162 ** Sub-Head2
163 * Head2 :noexport:
164 ** Sub-Head1 :export:"
165 (org-test-with-backend "test"
166 (should
167 (string-match
168 "\\* Head1[ \t]+:export:\n\\*\\* Sub-Head2\n"
169 (org-export-as
170 'test nil nil nil
171 '(:select-tags ("export") :exclude-tags ("noexport")))))))
172 ;; Ignore tasks.
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))
177 "")))))
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")))))
183 ;; Archived tree.
184 (org-test-with-temp-text "* Head1 :archive:"
185 (let ((org-archive-tag "archive"))
186 (org-test-with-backend "test"
187 (should
188 (equal (org-export-as 'test nil nil nil '(:with-archived-trees nil))
189 "")))))
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"
193 (should
194 (string-match
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"
201 (should
202 (string-match
203 "\\`\\* Head1[ \t]+:archive:\n\\'"
204 (org-export-as 'test nil nil nil '(:with-archived-trees t)))))))
205 ;; Drawers.
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))
210 ""))
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"
216 (should
217 (equal (org-export-as 'test nil nil nil '(:with-drawers ("FOO")))
218 ":FOO:\nkeep\n:END:\n")))))
219 ;; Timestamps.
220 (org-test-with-temp-text "[2012-04-29 sun. 10:45]<2012-04-29 sun. 10:45>"
221 (org-test-with-backend "test"
222 (should
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"))
225 (should
226 (equal (org-export-as 'test nil nil nil '(:with-timestamps nil)) ""))
227 (should
228 (equal (org-export-as 'test nil nil nil '(:with-timestamps active))
229 "<2012-04-29 sun. 10:45>\n"))
230 (should
231 (equal (org-export-as 'test nil nil nil '(:with-timestamps inactive))
232 "[2012-04-29 sun. 10:45]\n"))))
233 ;; Clocks.
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"
237 (should
238 (equal (org-export-as 'test nil nil nil '(:with-clocks t))
239 "CLOCK: [2012-04-29 sun. 10:45]\n"))
240 (should
241 (equal (org-export-as 'test nil nil nil '(:with-clocks nil)) "")))))
242 ;; Plannings.
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"
246 (should
247 (equal (org-export-as 'test nil nil nil '(:with-plannings t))
248 "CLOSED: [2012-04-29 sun. 10:45]\n"))
249 (should
250 (equal (org-export-as 'test nil nil nil '(:with-plannings nil))
251 ""))))))
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 "
263 * Head1
264 ** Head2
265 text
266 *** Head3"
267 (org-test-with-backend "test"
268 ;; Subtree.
269 (forward-line 3)
270 (should (equal (org-export-as 'test 'subtree) "text\n*** Head3\n"))
271 ;; Visible.
272 (goto-char (point-min))
273 (forward-line)
274 (org-cycle)
275 (should (equal (org-export-as 'test nil 'visible) "* Head1\n"))
276 ;; Body only.
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")))
282 ;; Region.
283 (goto-char (point-min))
284 (forward-line 3)
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 "
291 * Head1
292 #+BEGIN_SRC emacs-lisp :noweb yes :exports results
293 <<test>>
294 #+END_SRC
295 * Head2
296 #+NAME: test
297 #+BEGIN_SRC emacs-lisp
298 \(+ 1 2)
299 #+END_SRC"
300 (org-test-with-backend "test"
301 (forward-line 1)
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
328 Success!
330 * Heading
331 body\n")))
332 ;; Localized insertion.
333 (org-test-with-temp-text
334 (format "#+INCLUDE: \"%s/examples/include.org\" :lines \"1-2\""
335 org-test-dir)
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
341 (format
342 "* Top heading\n#+INCLUDE: \"%s/examples/include.org\" :lines \"9-\""
343 org-test-dir)
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"
349 org-test-dir)
350 (org-export-expand-include-keyword)
351 (should
352 (equal
353 (buffer-string)
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
357 (format
358 "#+INCLUDE: \"%s/examples/include.org\" :lines \"4-5\" src emacs-lisp"
359 org-test-dir)
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
368 (data backend info)
369 ;; Ignore headlines with the word "note" in their title.
370 (org-element-map
371 data 'headline
372 (lambda (headline)
373 (when (string-match "\\<note\\>"
374 (org-element-property :raw-value headline))
375 (org-export-ignore-element headline info)))
376 info)
377 data))
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
388 '((lambda ()
389 (org-map-entries
390 (lambda ()
391 (delete-region (point) (progn (forward-line) (point)))))))))
392 (should (equal (org-export-as 'test) "Body 1\nBody 2\n"))))))
396 ;;; Footnotes
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))))
407 (should
408 (equal
409 '((1 . "A") (2 . "B") (3 . "C") (4 . "D"))
410 (org-element-map
411 tree 'footnote-reference
412 (lambda (ref)
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))))))))
418 info)))))
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))))
425 (should
426 (equal
427 '((1 . "fn:1") (2 . "fn:2") (3 . "fn:3") (4))
428 (org-element-map
429 tree 'footnote-reference
430 (lambda (ref)
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))))
434 info)))))
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."
437 ;; Hide definitions.
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.
443 (should
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].
450 \[fn:3] C."
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))
455 4))))
456 ;; 5. Test export of footnotes defined outside parsing scope.
457 (org-test-with-temp-text "[fn:1] Out of scope
458 * Title
459 Paragraph[fn:1]"
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))))
465 (forward-line)
466 (should (equal "ParagraphOut of scope\n"
467 (org-export-as 'test 'subtree))))))))
471 ;;; Links
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]]"
478 (should-not
479 (org-element-map
480 tree 'link
481 (lambda (link)
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]]"
487 (should
488 ;; Note: Headline's number is in fact a list of numbers.
489 (equal '(2)
490 (org-element-map
491 tree 'link
492 (lambda (link)
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]]"
498 (should
499 ;; Note: Item's number is in fact a list of numbers.
500 (equal '(1 2)
501 (org-element-map
502 tree 'link
503 (lambda (link)
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
507 ;; number.
508 (org-test-with-parsed-data "
509 Paragraph[1][2][fn:lbl3:C<<target>>][[test]][[target]]\n[1] A\n\n[2] <<test>>B"
510 (should
511 (equal '(2 3)
512 (org-element-map
513 tree 'link
514 (lambda (link)
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
518 ;; element.
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]]"
521 (should
522 (= 2
523 (org-element-map
524 tree 'link
525 (lambda (link)
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]]"
532 (should
533 (equal '(2)
534 (org-element-map
535 tree 'link
536 (lambda (link)
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)))
547 (should
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)))
552 (should
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)))
558 (should
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)))
563 (should
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)))
569 (should
570 (equal (org-export-resolve-coderef "coderef" `(:parse-tree ,tree))
571 "coderef"))))
572 (org-test-with-temp-text
573 "#+BEGIN_EXAMPLE -n\nText (ref:coderef)\n#+END_EXAMPLE"
574 (let ((tree (org-element-parse-buffer)))
575 (should
576 (equal (org-export-resolve-coderef "coderef" `(:parse-tree ,tree))
577 "coderef"))))
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)))
582 (should
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)))
587 (should
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)))
593 (should
594 (equal (org-export-resolve-coderef "coderef" `(:parse-tree ,tree))
595 "coderef"))))
596 (org-test-with-temp-text
597 "#+BEGIN_EXAMPLE\nText (ref:coderef)\n#+END_EXAMPLE"
598 (let ((tree (org-element-parse-buffer)))
599 (should
600 (equal (org-export-resolve-coderef "coderef" `(:parse-tree ,tree))
601 "coderef"))))
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 "
607 #+BEGIN_EXAMPLE -n
608 Text.
609 #+END_EXAMPLE
611 #+BEGIN_SRC emacs-lisp
612 \(- 1 1)
613 #+END_SRC
615 #+BEGIN_SRC emacs-lisp +n -r
616 \(+ 1 1) (ref:addition)
617 #+END_SRC
619 #+BEGIN_EXAMPLE -n -r
620 Another text. (ref:text)
621 #+END_EXAMPLE"
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))
631 "text"))))))
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))
643 '("(+ 1 1)\n"))))
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 "
656 #+BEGIN_EXAMPLE -n
657 \(+ 1 1)
658 #+END_EXAMPLE
659 #+BEGIN_EXAMPLE +n
660 \(+ 2 2)
661 \(+ 3 3) (ref:one)
662 #+END_EXAMPLE"
663 (goto-line 5)
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
674 ;; protected.
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"))))))
682 ;;; Tables
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 "
689 | ! | 1 |
690 | | 2 |"
691 (should
692 (org-export-table-has-special-column-p
693 (org-element-map
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 "
697 | ! | 1 |
698 | b | 2 |"
699 (should-not
700 (org-export-table-has-special-column-p
701 (org-element-map
702 (org-element-parse-buffer) 'table 'identity nil 'first-match))))
703 ;; 3. Special marking characters are "#", "^", "*", "_", "/", "$"
704 ;; and "!".
705 (org-test-with-temp-text "
706 | # | 1 |
707 | ^ | 2 |
708 | * | 3 |
709 | _ | 4 |
710 | / | 5 |
711 | $ | 6 |
712 | ! | 7 |"
713 (should
714 (org-export-table-has-special-column-p
715 (org-element-map
716 (org-element-parse-buffer) 'table 'identity nil 'first-match))))
717 ;; 4. A first column with only empty cells isn't considered as
718 ;; special.
719 (org-test-with-temp-text "
720 | | 1 |
721 | | 2 |"
722 (should-not
723 (org-export-table-has-special-column-p
724 (org-element-map
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
730 ;; special column.
731 (org-test-with-parsed-data "| ! | 1 |"
732 (should
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 "
737 | / | 1 |
738 | a | b |"
739 (should
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
743 ;; special.
744 (org-test-with-parsed-data "| <5> | | <l> | <l22> |"
745 (should
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 |"
750 (should-not
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 "|---+---|"
755 (should-not
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 "
763 | a | b |
764 |---+---|
765 | c | d |"
766 (should
767 (org-export-table-has-header-p
768 (org-element-map tree 'table 'identity info 'first-match)
769 info)))
770 ;; 2. Without an header.
771 (org-test-with-parsed-data "
772 | a | b |
773 | c | d |"
774 (should-not
775 (org-export-table-has-header-p
776 (org-element-map tree 'table 'identity info 'first-match)
777 info)))
778 ;; 3. Don't get fooled with starting and ending rules.
779 (org-test-with-parsed-data "
780 |---+---|
781 | a | b |
782 | c | d |
783 |---+---|"
784 (should-not
785 (org-export-table-has-header-p
786 (org-element-map tree 'table 'identity info 'first-match)
787 info))))
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 "
793 | a | b |
794 |---+---|
795 | 1 | 2 |"
796 (should
797 (equal
798 '(1 nil 2)
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 "
803 | / | < | > |
804 |---|---+---|
805 | | 1 | 2 |"
806 (should
807 (equal
808 '(nil nil 1)
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 "
813 | a | b |
814 |---+---|
815 |---+---|
816 | 1 | 2 |"
817 (should
818 (equal
819 '(1 nil nil 2)
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> |
829 | | a | b | c |"
830 (should
831 (equal
832 '(nil 6 7)
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 "
837 | <6> |
838 | <7> |
839 | a |"
840 (should
841 (equal
842 '(7)
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 |"
847 (should
848 (equal
849 '(nil nil)
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)))
861 (should
862 (equal
863 '(left center right)
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 "
868 | <l8> |
869 | cell |
870 | <r9> |"
871 (let* ((tree (org-element-parse-buffer))
872 (info `(:parse-tree ,tree)))
873 (should
874 (equal
875 '(right right right)
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 "
882 | 123 |
883 | some text |
884 | 12345 |"
885 (let* ((tree (org-element-parse-buffer))
886 (info `(:parse-tree ,tree)))
887 (should
888 (equal
889 '(right right right)
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 "
895 | text |
896 | some text |
897 | 12345 |"
898 (let* ((tree (org-element-parse-buffer))
899 (info `(:parse-tree ,tree)))
900 (should
901 (equal
902 '(left left left)
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 "| / | < | > | <> |"
911 (should
912 (equal
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 "| / | < | < |"
920 (should
921 (equal
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 "
928 | | < |
929 | a | b |"
930 (should
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 "
937 | 1 |
938 |---|
939 | 2 |"
940 (should
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
947 ;; ignored.
948 (org-test-with-parsed-data "
949 |---+----|
950 | / | |
951 | | 1 |
952 |---+----|"
953 (should
954 (equal '((bottom below top above))
955 (last
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."
962 ;; 1. Standard test.
963 (org-test-with-parsed-data "
964 | 1 | 2 | 3 |
965 | 4 | 5 | 6 |"
966 (should
967 (equal '(2 . 3)
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 "
972 | / | < | > |
973 | 1 | 2 | 3 |
974 |---+---+---|
975 | 4 | 5 | 6 |"
976 (should
977 (equal '(2 . 3)
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 |"
985 (should
986 (equal '((0 . 0) (0 . 1))
987 (org-element-map
988 tree 'table-cell
989 (lambda (cell) (org-export-table-cell-address cell info))
990 info))))
991 ;; 2. Special column isn't counted, nor are special rows.
992 (org-test-with-parsed-data "
993 | / | <> |
994 | | c |"
995 (should
996 (equal '(0 . 0)
997 (org-export-table-cell-address
998 (car (last (org-element-map tree 'table-cell 'identity info)))
999 info))))
1000 ;; 3. Tables rules do not count either.
1001 (org-test-with-parsed-data "
1002 | a |
1003 |---|
1004 | b |
1005 |---|
1006 | c |"
1007 (should
1008 (equal '(2 . 0)
1009 (org-export-table-cell-address
1010 (car (last (org-element-map tree 'table-cell 'identity info)))
1011 info))))
1012 ;; 4. Return nil for special cells.
1013 (org-test-with-parsed-data "| / | a |"
1014 (should-not
1015 (org-export-table-cell-address
1016 (org-element-map tree 'table-cell 'identity nil 'first-match)
1017 info))))
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 "
1023 | / | <> |
1024 | | a |
1025 |---+----|
1026 | | b |"
1027 (should
1028 (equal '("b")
1029 (org-element-contents
1030 (org-export-get-table-cell-at
1031 '(1 . 0)
1032 (org-element-map tree 'table 'identity info 'first-match)
1033 info)))))
1034 ;; 2. Return value for a non-existent address is nil.
1035 (org-test-with-parsed-data "| a |"
1036 (should-not
1037 (org-export-get-table-cell-at
1038 '(2 . 2)
1039 (org-element-map tree 'table 'identity info 'first-match)
1040 info)))
1041 (org-test-with-parsed-data "| / |"
1042 (should-not
1043 (org-export-get-table-cell-at
1044 '(0 . 0)
1045 (org-element-map tree 'table 'identity info 'first-match)
1046 info))))
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 |"
1052 (should
1053 (org-export-table-cell-starts-colgroup-p
1054 (org-element-map tree 'table-cell 'identity info 'first-match)
1055 info)))
1056 ;; 2. Special column should be ignored when determining the
1057 ;; beginning of the row.
1058 (org-test-with-parsed-data "
1059 | / | |
1060 | | a |"
1061 (should
1062 (org-export-table-cell-starts-colgroup-p
1063 (org-element-map tree 'table-cell 'identity info 'first-match)
1064 info)))
1065 ;; 2. Explicit column groups.
1066 (org-test-with-parsed-data "
1067 | / | | < |
1068 | a | b | c |"
1069 (should
1070 (equal
1071 '(yes no yes)
1072 (org-element-map
1073 tree 'table-cell
1074 (lambda (cell)
1075 (if (org-export-table-cell-starts-colgroup-p cell info) 'yes 'no))
1076 info)))))
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 |"
1082 (should
1083 (org-export-table-cell-ends-colgroup-p
1084 (org-element-map tree 'table-cell 'identity info 'first-match)
1085 info)))
1086 ;; 2. Special column should be ignored when determining the
1087 ;; beginning of the row.
1088 (org-test-with-parsed-data "
1089 | / | |
1090 | | a |"
1091 (should
1092 (org-export-table-cell-ends-colgroup-p
1093 (org-element-map tree 'table-cell 'identity info 'first-match)
1094 info)))
1095 ;; 3. Explicit column groups.
1096 (org-test-with-parsed-data "
1097 | / | < | |
1098 | a | b | c |"
1099 (should
1100 (equal
1101 '(yes no yes)
1102 (org-element-map
1103 tree 'table-cell
1104 (lambda (cell)
1105 (if (org-export-table-cell-ends-colgroup-p cell info) 'yes 'no))
1106 info)))))
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 "
1113 | a |
1114 |---|
1115 | b |"
1116 (should
1117 (equal
1118 '(yes no yes)
1119 (org-element-map
1120 tree 'table-row
1121 (lambda (row)
1122 (if (org-export-table-row-starts-rowgroup-p row info) 'yes 'no))
1123 info))))
1124 ;; 2. Special rows should be ignored when determining the beginning
1125 ;; of the row.
1126 (org-test-with-parsed-data "
1127 | / | < |
1128 | | a |
1129 |---+---|
1130 | / | < |
1131 | | b |"
1132 (should
1133 (equal
1134 '(yes no yes)
1135 (org-element-map
1136 tree 'table-row
1137 (lambda (row)
1138 (if (org-export-table-row-starts-rowgroup-p row info) 'yes 'no))
1139 info)))))
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 "
1146 | a |
1147 |---|
1148 | b |"
1149 (should
1150 (equal
1151 '(yes no yes)
1152 (org-element-map
1153 tree 'table-row
1154 (lambda (row)
1155 (if (org-export-table-row-ends-rowgroup-p row info) 'yes 'no))
1156 info))))
1157 ;; 2. Special rows should be ignored when determining the beginning
1158 ;; of the row.
1159 (org-test-with-parsed-data "
1160 | | a |
1161 | / | < |
1162 |---+---|
1163 | | b |
1164 | / | < |"
1165 (should
1166 (equal
1167 '(yes no yes)
1168 (org-element-map
1169 tree 'table-row
1170 (lambda (row)
1171 (if (org-export-table-row-ends-rowgroup-p row info) 'yes 'no))
1172 info)))))
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
1177 ;; header.
1178 (org-test-with-parsed-data "
1179 | a |
1180 | b |
1181 |---|
1182 | c |"
1183 (should
1184 (equal
1185 '(yes no no no)
1186 (org-element-map
1187 tree 'table-row
1188 (lambda (row)
1189 (if (org-export-table-row-starts-header-p row info) 'yes 'no))
1190 info))))
1191 ;; 2. A row cannot start an header if there's no header in the
1192 ;; table.
1193 (org-test-with-parsed-data "
1194 | a |
1195 |---|"
1196 (should-not
1197 (org-export-table-row-starts-header-p
1198 (org-element-map tree 'table-row 'identity info 'first-match)
1199 info))))
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
1204 ;; header.
1205 (org-test-with-parsed-data "
1206 | a |
1207 | b |
1208 |---|
1209 | c |"
1210 (should
1211 (equal
1212 '(no yes no no)
1213 (org-element-map
1214 tree 'table-row
1215 (lambda (row)
1216 (if (org-export-table-row-ends-header-p row info) 'yes 'no))
1217 info))))
1218 ;; 2. A row cannot start an header if there's no header in the
1219 ;; table.
1220 (org-test-with-parsed-data "
1221 | a |
1222 |---|"
1223 (should-not
1224 (org-export-table-row-ends-header-p
1225 (org-element-map tree 'table-row 'identity info 'first-match)
1226 info))))
1229 (provide 'test-org-export)
1230 ;;; test-org-export.el end here