org-export: Internal changes to back-end definition
[org-mode.git] / testing / lisp / test-org-export.el
blobba70e208c8307a38ab9d32d7997827c5cfdfdf20
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"))
19 (defmacro org-test-with-backend (backend &rest body)
20 "Execute body with an export back-end defined.
22 BACKEND is the name of the back-end. BODY is the body to
23 execute. The defined back-end simply returns parsed data as Org
24 syntax."
25 (declare (debug (form body)) (indent 1))
26 `(let ((org-export-registered-backends
27 ',(list
28 (list backend
29 :translate-alist
30 (let (transcode-table)
31 (dolist (type (append org-element-all-elements
32 org-element-all-objects)
33 transcode-table)
34 (push
35 (cons type
36 (lambda (obj contents info)
37 (funcall
38 (intern (format "org-element-%s-interpreter"
39 type))
40 obj contents)))
41 transcode-table)))))))
42 (progn ,@body)))
44 (defmacro org-test-with-parsed-data (data &rest body)
45 "Execute body with parsed data available.
47 DATA is a string containing the data to be parsed. BODY is the
48 body to execute. Parse tree is available under the `tree'
49 variable, and communication channel under `info'.
51 This function calls `org-export-collect-tree-properties'. As
52 such, `:ignore-list' (for `org-element-map') and
53 `:parse-tree' (for `org-export-get-genealogy') properties are
54 already filled in `info'."
55 (declare (debug (form body)) (indent 1))
56 `(org-test-with-temp-text ,data
57 (let* ((tree (org-element-parse-buffer))
58 (info (org-export-collect-tree-properties
59 tree (org-export-get-environment))))
60 ,@body)))
64 ;;; Internal Tests
66 (ert-deftest test-org-export/bind-keyword ()
67 "Test reading #+BIND: keywords."
68 ;; Test with `org-export-all-BIND' set to t.
69 (should
70 (org-test-with-temp-text "#+BIND: variable value"
71 (let ((org-export-allow-BIND t))
72 (org-export--install-letbind-maybe)
73 (eq variable 'value))))
74 ;; Test with `org-export-all-BIND' set to nil.
75 (should-not
76 (org-test-with-temp-text "#+BIND: variable value"
77 (let ((org-export-allow-BIND nil))
78 (org-export--install-letbind-maybe)
79 (boundp 'variable))))
80 ;; Test with `org-export-all-BIND' set to 'confirm and
81 ;; `org-export--allow-BIND-local' to t .
82 (should
83 (org-test-with-temp-text "#+BIND: variable value"
84 (let ((org-export-allow-BIND 'confirm))
85 (org-set-local 'org-export--allow-BIND-local t)
86 (org-export--install-letbind-maybe)
87 (eq variable 'value))))
88 ;; Test with `org-export-all-BIND' set to 'confirm and
89 ;; `org-export--allow-BIND-local' to nil.
90 (should-not
91 (org-test-with-temp-text "#+BIND: variable value"
92 (let ((org-export-allow-BIND 'confirm))
93 (org-set-local 'org-export--allow-BIND-local nil)
94 (org-export--install-letbind-maybe)
95 (boundp 'variable))))
96 ;; BIND keywords are case-insensitive.
97 (should
98 (org-test-with-temp-text "#+bind: variable value"
99 (let ((org-export-allow-BIND t))
100 (org-export--install-letbind-maybe)
101 (eq variable 'value)))))
103 (ert-deftest test-org-export/parse-option-keyword ()
104 "Test reading all standard #+OPTIONS: items."
105 (should
106 (equal
107 (org-export--parse-option-keyword
108 "H:1 num:t \\n:t timestamp:t arch:t author:t creator:t d:t email:t
109 *:t e:t ::t f:t pri:t -:t ^:t toc:t |:t tags:t tasks:t <:t todo:t inline:nil
110 stat:t")
111 '(:headline-levels
112 1 :preserve-breaks t :section-numbers t :time-stamp-file t
113 :with-archived-trees t :with-author t :with-creator t :with-drawers t
114 :with-email t :with-emphasize t :with-entities t :with-fixed-width t
115 :with-footnotes t :with-inlinetasks nil :with-priority t
116 :with-special-strings t :with-statistics-cookies t :with-sub-superscript t
117 :with-toc t :with-tables t :with-tags t :with-tasks t :with-timestamps t
118 :with-todo-keywords t)))
119 ;; Test some special values.
120 (should
121 (equal
122 (org-export--parse-option-keyword
123 "arch:headline creator:comment d:(\"TEST\")
124 ^:{} toc:1 tags:not-in-toc tasks:todo num:2 <:active")
125 '( :section-numbers
127 :with-archived-trees headline :with-creator comment
128 :with-drawers ("TEST") :with-sub-superscript {} :with-toc 1
129 :with-tags not-in-toc :with-tasks todo :with-timestamps active))))
131 (ert-deftest test-org-export/get-inbuffer-options ()
132 "Test reading all standard export keywords."
133 (should
134 (equal
135 (org-test-with-temp-text "#+AUTHOR: Me, Myself and I
136 #+CREATOR: Idem
137 #+DATE: Today
138 #+DESCRIPTION: Testing
139 #+DESCRIPTION: with two lines
140 #+EMAIL: some@email.org
141 #+EXCLUDE_TAGS: noexport invisible
142 #+KEYWORDS: test
143 #+LANGUAGE: en
144 #+SELECT_TAGS: export
145 #+TITLE: Some title
146 #+TITLE: with spaces"
147 (org-export--get-inbuffer-options))
148 '(:author
149 ("Me, Myself and I") :creator "Idem" :date ("Today")
150 :description "Testing\nwith two lines" :email "some@email.org"
151 :exclude-tags ("noexport" "invisible") :keywords "test" :language "en"
152 :select-tags ("export") :title ("Some title with spaces")))))
154 (ert-deftest test-org-export/get-subtree-options ()
155 "Test setting options from headline's properties."
156 ;; EXPORT_TITLE.
157 (org-test-with-temp-text "#+TITLE: Title
158 * Headline
159 :PROPERTIES:
160 :EXPORT_TITLE: Subtree Title
161 :END:
162 Paragraph"
163 (forward-line)
164 (should (equal (plist-get (org-export-get-environment nil t) :title)
165 '("Subtree Title"))))
166 :title
167 '("subtree-title")
168 ;; EXPORT_OPTIONS.
169 (org-test-with-temp-text "#+OPTIONS: H:1
170 * Headline
171 :PROPERTIES:
172 :EXPORT_OPTIONS: H:2
173 :END:
174 Paragraph"
175 (forward-line)
176 (should
177 (= 2 (plist-get (org-export-get-environment nil t) :headline-levels))))
178 ;; EXPORT_DATE.
179 (org-test-with-temp-text "#+DATE: today
180 * Headline
181 :PROPERTIES:
182 :EXPORT_DATE: 29-03-2012
183 :END:
184 Paragraph"
185 (forward-line)
186 (should (equal (plist-get (org-export-get-environment nil t) :date)
187 '("29-03-2012"))))
188 ;; Export properties are case-insensitive.
189 (org-test-with-temp-text "* Headline
190 :PROPERTIES:
191 :EXPORT_Date: 29-03-2012
192 :END:
193 Paragraph"
194 (should (equal (plist-get (org-export-get-environment nil t) :date)
195 '("29-03-2012")))))
197 (ert-deftest test-org-export/handle-options ()
198 "Test if export options have an impact on output."
199 ;; Test exclude tags.
200 (org-test-with-temp-text "* Head1 :noexport:"
201 (org-test-with-backend test
202 (should
203 (equal (org-export-as 'test nil nil nil '(:exclude-tags ("noexport")))
204 ""))))
205 ;; Test include tags.
206 (org-test-with-temp-text "
207 * Head1
208 * Head2
209 ** Sub-Head2.1 :export:
210 *** Sub-Head2.1.1
211 * Head2"
212 (org-test-with-backend test
213 (should
214 (equal
215 "* Head2\n** Sub-Head2.1 :export:\n*** Sub-Head2.1.1\n"
216 (let ((org-tags-column 0))
217 (org-export-as 'test nil nil nil '(:select-tags ("export"))))))))
218 ;; Test mixing include tags and exclude tags.
219 (org-test-with-temp-text "
220 * Head1 :export:
221 ** Sub-Head1 :noexport:
222 ** Sub-Head2
223 * Head2 :noexport:
224 ** Sub-Head1 :export:"
225 (org-test-with-backend test
226 (should
227 (string-match
228 "\\* Head1[ \t]+:export:\n\\*\\* Sub-Head2\n"
229 (org-export-as
230 'test nil nil nil
231 '(:select-tags ("export") :exclude-tags ("noexport")))))))
232 ;; Ignore tasks.
233 (let ((org-todo-keywords '((sequence "TODO" "DONE"))))
234 (org-test-with-temp-text "* TODO Head1"
235 (org-test-with-backend test
236 (should (equal (org-export-as 'test nil nil nil '(:with-tasks nil))
237 "")))))
238 (let ((org-todo-keywords '((sequence "TODO" "DONE"))))
239 (org-test-with-temp-text "* TODO Head1"
240 (org-test-with-backend test
241 (should (equal (org-export-as 'test nil nil nil '(:with-tasks t))
242 "* TODO Head1\n")))))
243 ;; Archived tree.
244 (org-test-with-temp-text "* Head1 :archive:"
245 (let ((org-archive-tag "archive"))
246 (org-test-with-backend test
247 (should
248 (equal (org-export-as 'test nil nil nil '(:with-archived-trees nil))
249 "")))))
250 (org-test-with-temp-text "* Head1 :archive:\nbody\n** Sub-head 2"
251 (let ((org-archive-tag "archive"))
252 (org-test-with-backend test
253 (should
254 (string-match
255 "\\* Head1[ \t]+:archive:"
256 (org-export-as 'test nil nil nil
257 '(:with-archived-trees headline)))))))
258 (org-test-with-temp-text "* Head1 :archive:"
259 (let ((org-archive-tag "archive"))
260 (org-test-with-backend test
261 (should
262 (string-match
263 "\\`\\* Head1[ \t]+:archive:\n\\'"
264 (org-export-as 'test nil nil nil '(:with-archived-trees t)))))))
265 ;; Drawers.
266 (let ((org-drawers '("TEST")))
267 (org-test-with-temp-text ":TEST:\ncontents\n:END:"
268 (org-test-with-backend test
269 (should (equal (org-export-as 'test nil nil nil '(:with-drawers nil))
270 ""))
271 (should (equal (org-export-as 'test nil nil nil '(:with-drawers t))
272 ":TEST:\ncontents\n:END:\n")))))
273 (let ((org-drawers '("FOO" "BAR")))
274 (org-test-with-temp-text ":FOO:\nkeep\n:END:\n:BAR:\nremove\n:END:"
275 (org-test-with-backend test
276 (should
277 (equal (org-export-as 'test nil nil nil '(:with-drawers ("FOO")))
278 ":FOO:\nkeep\n:END:\n")))))
279 ;; Timestamps.
280 (org-test-with-temp-text "[2012-04-29 sun. 10:45]<2012-04-29 sun. 10:45>"
281 (org-test-with-backend test
282 (should
283 (equal (org-export-as 'test nil nil nil '(:with-timestamps t))
284 "[2012-04-29 sun. 10:45]<2012-04-29 sun. 10:45>\n"))
285 (should
286 (equal (org-export-as 'test nil nil nil '(:with-timestamps nil)) ""))
287 (should
288 (equal (org-export-as 'test nil nil nil '(:with-timestamps active))
289 "<2012-04-29 sun. 10:45>\n"))
290 (should
291 (equal (org-export-as 'test nil nil nil '(:with-timestamps inactive))
292 "[2012-04-29 sun. 10:45]\n"))))
293 ;; Clocks.
294 (let ((org-clock-string "CLOCK:"))
295 (org-test-with-temp-text "CLOCK: [2012-04-29 sun. 10:45]"
296 (org-test-with-backend test
297 (should
298 (equal (org-export-as 'test nil nil nil '(:with-clocks t))
299 "CLOCK: [2012-04-29 sun. 10:45]\n"))
300 (should
301 (equal (org-export-as 'test nil nil nil '(:with-clocks nil)) "")))))
302 ;; Plannings.
303 (let ((org-closed-string "CLOSED:"))
304 (org-test-with-temp-text "CLOSED: [2012-04-29 sun. 10:45]"
305 (org-test-with-backend test
306 (should
307 (equal (org-export-as 'test nil nil nil '(:with-plannings t))
308 "CLOSED: [2012-04-29 sun. 10:45]\n"))
309 (should
310 (equal (org-export-as 'test nil nil nil '(:with-plannings nil))
311 "")))))
312 ;; Inlinetasks.
313 (when (featurep 'org-inlinetask)
314 (should
315 (equal
316 (let ((org-inlinetask-min-level 15))
317 (org-test-with-temp-text "*************** Task"
318 (org-test-with-backend test
319 (org-export-as 'test nil nil nil '(:with-inlinetasks nil)))))
320 ""))
321 (should
322 (equal
323 (let ((org-inlinetask-min-level 15))
324 (org-test-with-temp-text
325 "*************** Task\nContents\n*************** END"
326 (org-test-with-backend test
327 (org-export-as 'test nil nil nil '(:with-inlinetasks nil)))))
328 "")))
329 ;; Statistics cookies.
330 (should
331 (equal ""
332 (org-test-with-temp-text "[0/0]"
333 (org-test-with-backend test
334 (org-export-as
335 'test nil nil nil '(:with-statistics-cookies nil)))))))
337 (ert-deftest test-org-export/comment-tree ()
338 "Test if export process ignores commented trees."
339 (let ((org-comment-string "COMMENT"))
340 (org-test-with-temp-text "* COMMENT Head1"
341 (org-test-with-backend test
342 (should (equal (org-export-as 'test) ""))))))
344 (ert-deftest test-org-export/export-scope ()
345 "Test all export scopes."
346 (org-test-with-temp-text "
347 * Head1
348 ** Head2
349 text
350 *** Head3"
351 (org-test-with-backend test
352 ;; Subtree.
353 (forward-line 3)
354 (should (equal (org-export-as 'test 'subtree) "text\n*** Head3\n"))
355 ;; Visible.
356 (goto-char (point-min))
357 (forward-line)
358 (org-cycle)
359 (should (equal (org-export-as 'test nil 'visible) "* Head1\n"))
360 ;; Region.
361 (goto-char (point-min))
362 (forward-line 3)
363 (transient-mark-mode 1)
364 (push-mark (point) t t)
365 (goto-char (point-at-eol))
366 (should (equal (org-export-as 'test) "text\n"))))
367 ;; Subtree with a code block calling another block outside.
368 (should
369 (equal ": 3\n"
370 (org-test-with-temp-text "
371 * Head1
372 #+BEGIN_SRC emacs-lisp :noweb yes :exports results
373 <<test>>
374 #+END_SRC
375 * Head2
376 #+NAME: test
377 #+BEGIN_SRC emacs-lisp
378 \(+ 1 2)
379 #+END_SRC"
380 (org-test-with-backend test
381 (forward-line 1)
382 (org-export-as 'test 'subtree)))))
383 ;; Body only.
384 (org-test-with-temp-text "Text"
385 (org-test-with-backend test
386 (plist-put
387 (cdr (assq 'test org-export-registered-backends))
388 :translate-alist
389 (cons (cons 'template (lambda (body info) (format "BEGIN\n%sEND" body)))
390 (org-export-backend-translate-table 'test)))
391 (should (equal (org-export-as 'test nil nil 'body-only) "Text\n"))
392 (should (equal (org-export-as 'test) "BEGIN\nText\nEND")))))
394 (ert-deftest test-org-export/expand-include ()
395 "Test file inclusion in an Org buffer."
396 ;; Error when file isn't specified.
397 (should-error
398 (org-test-with-temp-text "#+INCLUDE: dummy.org"
399 (org-export-expand-include-keyword)))
400 ;; Full insertion with recursive inclusion.
401 (org-test-with-temp-text
402 (format "#+INCLUDE: \"%s/examples/include.org\"" org-test-dir)
403 (org-export-expand-include-keyword)
404 (should (equal (buffer-string)
405 "Small Org file with an include keyword.
407 #+BEGIN_SRC emacs-lisp :exports results\n(+ 2 1)\n#+END_SRC
409 Success!
411 * Heading
412 body\n")))
413 ;; Localized insertion.
414 (org-test-with-temp-text
415 (format "#+INCLUDE: \"%s/examples/include.org\" :lines \"1-2\""
416 org-test-dir)
417 (org-export-expand-include-keyword)
418 (should (equal (buffer-string)
419 "Small Org file with an include keyword.\n")))
420 ;; Insertion with constraints on headlines level.
421 (org-test-with-temp-text
422 (format
423 "* Top heading\n#+INCLUDE: \"%s/examples/include.org\" :lines \"9-\""
424 org-test-dir)
425 (org-export-expand-include-keyword)
426 (should (equal (buffer-string) "* Top heading\n** Heading\nbody\n")))
427 ;; Inclusion within an example block.
428 (org-test-with-temp-text
429 (format "#+INCLUDE: \"%s/examples/include.org\" :lines \"1-2\" example"
430 org-test-dir)
431 (org-export-expand-include-keyword)
432 (should
433 (equal
434 (buffer-string)
435 "#+BEGIN_EXAMPLE\nSmall Org file with an include keyword.\n#+END_EXAMPLE\n")))
436 ;; Inclusion within a src-block.
437 (org-test-with-temp-text
438 (format
439 "#+INCLUDE: \"%s/examples/include.org\" :lines \"4-5\" src emacs-lisp"
440 org-test-dir)
441 (org-export-expand-include-keyword)
442 (should (equal (buffer-string)
443 "#+BEGIN_SRC emacs-lisp\n(+ 2 1)\n#+END_SRC\n"))))
445 (ert-deftest test-org-export/expand-macro ()
446 "Test macro expansion in an Org buffer."
447 ;; Standard macro expansion.
448 (should
449 (equal "#+MACRO: macro1 value\nvalue\n"
450 (org-test-with-temp-text "#+MACRO: macro1 value\n{{{macro1}}}"
451 (org-test-with-backend test (org-export-as 'test)))))
452 ;; Expand specific macros.
453 (should
454 (equal "me 2012-03-29 me@here Title\n"
455 (org-test-with-temp-text
457 #+TITLE: Title
458 #+DATE: 2012-03-29
459 #+AUTHOR: me
460 #+EMAIL: me@here
461 {{{author}}} {{{date}}} {{{email}}} {{{title}}}"
462 (let ((output (org-test-with-backend test (org-export-as 'test))))
463 (substring output (string-match ".*\n\\'" output))))))
464 ;; Expand specific macros when property contained a regular macro
465 ;; already.
466 (should
467 (equal "value\n"
468 (org-test-with-temp-text "
469 #+MACRO: macro1 value
470 #+TITLE: {{{macro1}}}
471 {{{title}}}"
472 (let ((output (org-test-with-backend test (org-export-as 'test))))
473 (substring output (string-match ".*\n\\'" output))))))
474 ;; Expand macros with templates in included files.
475 (should
476 (equal "success\n"
477 (org-test-with-temp-text
478 (format "#+INCLUDE: \"%s/examples/macro-templates.org\"
479 {{{included-macro}}}" org-test-dir)
480 (let ((output (org-test-with-backend test (org-export-as 'test))))
481 (substring output (string-match ".*\n\\'" output)))))))
483 (ert-deftest test-org-export/user-ignore-list ()
484 "Test if `:ignore-list' accepts user input."
485 (org-test-with-backend test
486 (flet ((skip-note-head
487 (data backend info)
488 ;; Ignore headlines with the word "note" in their title.
489 (org-element-map
490 data 'headline
491 (lambda (headline)
492 (when (string-match "\\<note\\>"
493 (org-element-property :raw-value headline))
494 (org-export-ignore-element headline info)))
495 info)
496 data))
497 ;; Install function in parse tree filters.
498 (let ((org-export-filter-parse-tree-functions '(skip-note-head)))
499 (org-test-with-temp-text "* Head1\n* Head2 (note)\n"
500 (should (equal (org-export-as 'test) "* Head1\n")))))))
502 (ert-deftest test-org-export/before-processing-hook ()
503 "Test `org-export-before-processing-hook'."
504 (should
505 (equal
506 "#+MACRO: mac val\nTest\n"
507 (org-test-with-backend test
508 (org-test-with-temp-text "#+MACRO: mac val\n{{{mac}}} Test"
509 (let ((org-export-before-processing-hook
510 '((lambda (backend)
511 (while (re-search-forward "{{{" nil t)
512 (let ((object (org-element-context)))
513 (when (eq (org-element-type object) 'macro)
514 (delete-region
515 (org-element-property :begin object)
516 (org-element-property :end object)))))))))
517 (org-export-as 'test)))))))
519 (ert-deftest test-org-export/before-parsing-hook ()
520 "Test `org-export-before-parsing-hook'."
521 (should
522 (equal "Body 1\nBody 2\n"
523 (org-test-with-backend test
524 (org-test-with-temp-text "* Headline 1\nBody 1\n* Headline 2\nBody 2"
525 (let ((org-export-before-parsing-hook
526 '((lambda (backend)
527 (org-map-entries
528 (lambda ()
529 (delete-region (point) (progn (forward-line) (point)))))))))
530 (org-export-as 'test)))))))
534 ;;; Affiliated Keywords
536 (ert-deftest test-org-export/read-attribute ()
537 "Test `org-export-read-attribute' specifications."
538 ;; Standard test.
539 (should
540 (equal
541 (org-export-read-attribute
542 :attr_html
543 (org-test-with-temp-text "#+ATTR_HTML: :a 1 :b 2\nParagraph"
544 (org-element-at-point)))
545 '(:a 1 :b 2)))
546 ;; Return nil on empty attribute.
547 (should-not
548 (org-export-read-attribute
549 :attr_html
550 (org-test-with-temp-text "Paragraph" (org-element-at-point)))))
552 (ert-deftest test-org-export/get-caption ()
553 "Test `org-export-get-caption' specifications."
554 ;; Without optional argument, return long caption
555 (should
556 (equal
557 '("l")
558 (org-test-with-temp-text "#+CAPTION[s]: l\nPara"
559 (org-export-get-caption (org-element-at-point)))))
560 ;; With optional argument, return short caption.
561 (should
562 (equal
563 '("s")
564 (org-test-with-temp-text "#+CAPTION[s]: l\nPara"
565 (org-export-get-caption (org-element-at-point) t))))
566 ;; Multiple lines are separated by white spaces.
567 (should
568 (equal
569 '("a" " " "b")
570 (org-test-with-temp-text "#+CAPTION: a\n#+CAPTION: b\nPara"
571 (org-export-get-caption (org-element-at-point))))))
575 ;;; Export Snippets
577 (ert-deftest test-org-export/export-snippet ()
578 "Test export snippets transcoding."
579 (org-test-with-temp-text "@@test:A@@@@t:B@@"
580 (org-test-with-backend test
581 (plist-put
582 (cdr (assq 'test org-export-registered-backends))
583 :translate-alist
584 (cons (cons 'export-snippet
585 (lambda (snippet contents info)
586 (when (eq (org-export-snippet-backend snippet) 'test)
587 (org-element-property :value snippet))))
588 (org-export-backend-translate-table 'test)))
589 (let ((org-export-snippet-translation-alist nil))
590 (should (equal (org-export-as 'test) "A\n")))
591 (let ((org-export-snippet-translation-alist '(("t" . "test"))))
592 (should (equal (org-export-as 'test) "AB\n"))))))
596 ;;; Footnotes
598 (ert-deftest test-org-export/footnotes ()
599 "Test footnotes specifications."
600 (let ((org-footnote-section nil)
601 (org-export-with-footnotes t))
602 ;; 1. Read every type of footnote.
603 (should
604 (equal
605 '((1 . "A\n") (2 . "B") (3 . "C") (4 . "D"))
606 (org-test-with-parsed-data
607 "Text[fn:1] [1] [fn:label:C] [fn::D]\n\n[fn:1] A\n\n[1] B"
608 (org-element-map
609 tree 'footnote-reference
610 (lambda (ref)
611 (let ((def (org-export-get-footnote-definition ref info)))
612 (cons (org-export-get-footnote-number ref info)
613 (if (eq (org-element-property :type ref) 'inline) (car def)
614 (car (org-element-contents
615 (car (org-element-contents def))))))))
616 info))))
617 ;; 2. Test nested footnotes order.
618 (org-test-with-parsed-data
619 "Text[fn:1:A[fn:2]] [fn:3].\n\n[fn:2] B [fn:3] [fn::D].\n\n[fn:3] C."
620 (should
621 (equal
622 '((1 . "fn:1") (2 . "fn:2") (3 . "fn:3") (4))
623 (org-element-map
624 tree 'footnote-reference
625 (lambda (ref)
626 (when (org-export-footnote-first-reference-p ref info)
627 (cons (org-export-get-footnote-number ref info)
628 (org-element-property :label ref))))
629 info))))
630 ;; 3. Test nested footnote in invisible definitions.
631 (org-test-with-temp-text "Text[1]\n\n[1] B [2]\n\n[2] C."
632 ;; Hide definitions.
633 (narrow-to-region (point) (point-at-eol))
634 (let* ((tree (org-element-parse-buffer))
635 (info (org-combine-plists
636 `(:parse-tree ,tree)
637 (org-export-collect-tree-properties
638 tree (org-export-get-environment)))))
639 ;; Both footnotes should be seen.
640 (should
641 (= (length (org-export-collect-footnote-definitions tree info)) 2))))
642 ;; 4. Test footnotes definitions collection.
643 (org-test-with-parsed-data "Text[fn:1:A[fn:2]] [fn:3].
645 \[fn:2] B [fn:3] [fn::D].
647 \[fn:3] C."
648 (should (= (length (org-export-collect-footnote-definitions tree info))
649 4)))
650 ;; 5. Test export of footnotes defined outside parsing scope.
651 (org-test-with-temp-text "[fn:1] Out of scope
652 * Title
653 Paragraph[fn:1]"
654 (org-test-with-backend test
655 (plist-put
656 (cdr (assq 'test org-export-registered-backends))
657 :translate-alist
658 (cons (cons 'footnote-reference
659 (lambda (fn contents info)
660 (org-element-interpret-data
661 (org-export-get-footnote-definition fn info))))
662 (org-export-backend-translate-table 'test)))
663 (forward-line)
664 (should (equal "ParagraphOut of scope\n"
665 (org-export-as 'test 'subtree)))))))
669 ;;; Headlines and Inlinetasks
671 (ert-deftest test-org-export/get-relative-level ()
672 "Test `org-export-get-relative-level' specifications."
673 ;; Standard test.
674 (should
675 (equal '(1 2)
676 (let ((org-odd-levels-only nil))
677 (org-test-with-parsed-data "* Headline 1\n** Headline 2"
678 (org-element-map
679 tree 'headline
680 (lambda (h) (org-export-get-relative-level h info))
681 info)))))
682 ;; Missing levels
683 (should
684 (equal '(1 3)
685 (let ((org-odd-levels-only nil))
686 (org-test-with-parsed-data "** Headline 1\n**** Headline 2"
687 (org-element-map
688 tree 'headline
689 (lambda (h) (org-export-get-relative-level h info))
690 info))))))
692 (ert-deftest test-org-export/low-level-p ()
693 "Test `org-export-low-level-p' specifications."
694 (should
695 (equal
696 '(no yes)
697 (let ((org-odd-levels-only nil))
698 (org-test-with-parsed-data "* Headline 1\n** Headline 2"
699 (org-element-map
700 tree 'headline
701 (lambda (h) (if (org-export-low-level-p h info) 'yes 'no))
702 (plist-put info :headline-levels 1)))))))
704 (ert-deftest test-org-export/get-headline-number ()
705 "Test `org-export-get-headline-number' specifications."
706 ;; Standard test.
707 (should
708 (equal
709 '((1) (1 1))
710 (let ((org-odd-levels-only nil))
711 (org-test-with-parsed-data "* Headline 1\n** Headline 2"
712 (org-element-map
713 tree 'headline
714 (lambda (h) (org-export-get-headline-number h info))
715 info)))))
716 ;; Missing levels are replaced with 0.
717 (should
718 (equal
719 '((1) (1 0 1))
720 (let ((org-odd-levels-only nil))
721 (org-test-with-parsed-data "* Headline 1\n*** Headline 2"
722 (org-element-map
723 tree 'headline
724 (lambda (h) (org-export-get-headline-number h info))
725 info))))))
727 (ert-deftest test-org-export/numbered-headline-p ()
728 "Test `org-export-numbered-headline-p' specifications."
729 ;; If `:section-numbers' is nil, never number headlines.
730 (should-not
731 (org-test-with-parsed-data "* Headline"
732 (org-element-map
733 tree 'headline
734 (lambda (h) (org-export-numbered-headline-p h info))
735 (plist-put info :section-numbers nil))))
736 ;; If `:section-numbers' is a number, only number headlines with
737 ;; a level greater that it.
738 (should
739 (equal
740 '(yes no)
741 (org-test-with-parsed-data "* Headline 1\n** Headline 2"
742 (org-element-map
743 tree 'headline
744 (lambda (h) (if (org-export-numbered-headline-p h info) 'yes 'no))
745 (plist-put info :section-numbers 1)))))
746 ;; Otherwise, headlines are always numbered.
747 (should
748 (org-test-with-parsed-data "* Headline"
749 (org-element-map
750 tree 'headline
751 (lambda (h) (org-export-numbered-headline-p h info))
752 (plist-put info :section-numbers t)))))
754 (ert-deftest test-org-export/number-to-roman ()
755 "Test `org-export-number-to-roman' specifications."
756 ;; If number is negative, return it as a string.
757 (should (equal (org-export-number-to-roman -1) "-1"))
758 ;; Otherwise, return it as a roman number.
759 (should (equal (org-export-number-to-roman 1449) "MCDXLIX")))
761 (ert-deftest test-org-export/get-tags ()
762 "Test `org-export-get-tags' specifications."
763 (let ((org-export-exclude-tags '("noexport"))
764 (org-export-select-tags '("export")))
765 ;; Standard test: tags which are not a select tag, an exclude tag,
766 ;; or specified as optional argument shouldn't be ignored.
767 (should
768 (org-test-with-parsed-data "* Headline :tag:"
769 (org-export-get-tags (org-element-map tree 'headline 'identity info t)
770 info)))
771 ;; Exclude tags are removed.
772 (should-not
773 (org-test-with-parsed-data "* Headline :noexport:"
774 (org-export-get-tags (org-element-map tree 'headline 'identity info t)
775 info)))
776 ;; Select tags are removed.
777 (should-not
778 (org-test-with-parsed-data "* Headline :export:"
779 (org-export-get-tags (org-element-map tree 'headline 'identity info t)
780 info)))
781 (should
782 (equal
783 '("tag")
784 (org-test-with-parsed-data "* Headline :tag:export:"
785 (org-export-get-tags (org-element-map tree 'headline 'identity info t)
786 info))))
787 ;; Tags provided in the optional argument are also ignored.
788 (should-not
789 (org-test-with-parsed-data "* Headline :ignore:"
790 (org-export-get-tags (org-element-map tree 'headline 'identity info t)
791 info '("ignore"))))
792 ;; Allow tag inheritance.
793 (should
794 (equal
795 '(("tag") ("tag"))
796 (org-test-with-parsed-data "* Headline :tag:\n** Sub-heading"
797 (org-element-map
798 tree 'headline
799 (lambda (hl) (org-export-get-tags hl info nil t)) info))))
800 ;; Tag inheritance checks FILETAGS keywords.
801 (should
802 (equal
803 '(("a" "b" "tag"))
804 (org-test-with-parsed-data "#+FILETAGS: :a:b:\n* Headline :tag:"
805 (org-element-map
806 tree 'headline
807 (lambda (hl) (org-export-get-tags hl info nil t)) info))))))
809 (ert-deftest test-org-export/get-node-property ()
810 "Test`org-export-get-node-property' specifications."
811 ;; Standard test.
812 (should
813 (equal "value"
814 (org-test-with-parsed-data "* Headline
815 :PROPERTIES:
816 :prop: value
817 :END:"
818 (org-export-get-node-property
819 :prop (org-element-map tree 'headline 'identity nil t)))))
820 ;; Test inheritance.
821 (should
822 (equal "value"
823 (org-test-with-parsed-data "* Parent
824 :PROPERTIES:
825 :prop: value
826 :END:
827 ** Headline
828 Paragraph"
829 (org-export-get-node-property
830 :prop (org-element-map tree 'paragraph 'identity nil t) t))))
831 ;; Cannot return a value before the first headline.
832 (should-not
833 (org-test-with-parsed-data "Paragraph
834 * Headline
835 :PROPERTIES:
836 :prop: value
837 :END:"
838 (org-export-get-node-property
839 :prop (org-element-map tree 'paragraph 'identity nil t)))))
841 (ert-deftest test-org-export/get-category ()
842 "Test `org-export-get-category' specifications."
843 ;; Standard test.
844 (should
845 (equal "value"
846 (org-test-with-parsed-data "* Headline
847 :PROPERTIES:
848 :CATEGORY: value
849 :END:"
850 (org-export-get-category
851 (org-element-map tree 'headline 'identity nil t) info))))
852 ;; Test inheritance from a parent headline.
853 (should
854 (equal '("value" "value")
855 (org-test-with-parsed-data "* Headline1
856 :PROPERTIES:
857 :CATEGORY: value
858 :END:
859 ** Headline2"
860 (org-element-map
861 tree 'headline
862 (lambda (hl) (org-export-get-category hl info)) info))))
863 ;; Test inheritance from #+CATEGORY keyword
864 (should
865 (equal "value"
866 (org-test-with-parsed-data "#+CATEGORY: value
867 * Headline"
868 (org-export-get-category
869 (org-element-map tree 'headline 'identity nil t) info))))
870 ;; Test inheritance from file name.
871 (should
872 (equal "test"
873 (org-test-with-parsed-data "* Headline"
874 (let ((info (plist-put info :input-file "~/test.org")))
875 (org-export-get-category
876 (org-element-map tree 'headline 'identity nil t) info)))))
877 ;; Fall-back value.
878 (should
879 (equal "???"
880 (org-test-with-parsed-data "* Headline"
881 (org-export-get-category
882 (org-element-map tree 'headline 'identity nil t) info)))))
884 (ert-deftest test-org-export/first-sibling-p ()
885 "Test `org-export-first-sibling-p' specifications."
886 ;; Standard test.
887 (should
888 (equal
889 '(yes yes no)
890 (org-test-with-parsed-data "* Headline\n** Headline 2\n** Headline 3"
891 (org-element-map
892 tree 'headline
893 (lambda (h) (if (org-export-first-sibling-p h info) 'yes 'no))
894 info))))
895 ;; Ignore headlines not exported.
896 (should
897 (equal
898 '(yes)
899 (let ((org-export-exclude-tags '("ignore")))
900 (org-test-with-parsed-data "* Headline :ignore:\n* Headline 2"
901 (org-element-map
902 tree 'headline
903 (lambda (h) (if (org-export-first-sibling-p h info) 'yes 'no))
904 info))))))
906 (ert-deftest test-org-export/last-sibling-p ()
907 "Test `org-export-last-sibling-p' specifications."
908 ;; Standard test.
909 (should
910 (equal
911 '(yes no yes)
912 (org-test-with-parsed-data "* Headline\n** Headline 2\n** Headline 3"
913 (org-element-map
914 tree 'headline
915 (lambda (h) (if (org-export-last-sibling-p h info) 'yes 'no))
916 info))))
917 ;; Ignore headlines not exported.
918 (should
919 (equal
920 '(yes)
921 (let ((org-export-exclude-tags '("ignore")))
922 (org-test-with-parsed-data "* Headline\n* Headline 2 :ignore:"
923 (org-element-map
924 tree 'headline
925 (lambda (h) (if (org-export-last-sibling-p h info) 'yes 'no))
926 info))))))
930 ;;; Links
932 (ert-deftest test-org-export/get-coderef-format ()
933 "Test `org-export-get-coderef-format' specifications."
934 ;; A link without description returns "%s"
935 (should (equal (org-export-get-coderef-format "(ref:line)" nil)
936 "%s"))
937 ;; Return "%s" when path is matched within description.
938 (should (equal (org-export-get-coderef-format "path" "desc (path)")
939 "desc %s"))
940 ;; Otherwise return description.
941 (should (equal (org-export-get-coderef-format "path" "desc")
942 "desc")))
944 (ert-deftest test-org-export/inline-image-p ()
945 "Test `org-export-inline-image-p' specifications."
946 (should
947 (org-export-inline-image-p
948 (org-test-with-temp-text "[[#id]]"
949 (org-element-map
950 (org-element-parse-buffer) 'link 'identity nil t))
951 '(("custom-id" . "id")))))
953 (ert-deftest test-org-export/fuzzy-link ()
954 "Test fuzzy links specifications."
955 ;; 1. Links to invisible (keyword) targets should be ignored.
956 (org-test-with-parsed-data
957 "Paragraph.\n#+TARGET: Test\n[[Test]]"
958 (should-not
959 (org-element-map
960 tree 'link
961 (lambda (link)
962 (org-export-get-ordinal
963 (org-export-resolve-fuzzy-link link info) info)) info)))
964 ;; 2. Link to an headline should return headline's number.
965 (org-test-with-parsed-data
966 "Paragraph.\n* Head1\n* Head2\n* Head3\n[[Head2]]"
967 (should
968 ;; Note: Headline's number is in fact a list of numbers.
969 (equal '(2)
970 (org-element-map
971 tree 'link
972 (lambda (link)
973 (org-export-get-ordinal
974 (org-export-resolve-fuzzy-link link info) info)) info t))))
975 ;; 3. Link to a target in an item should return item's number.
976 (org-test-with-parsed-data
977 "- Item1\n - Item11\n - <<test>>Item12\n- Item2\n\n\n[[test]]"
978 (should
979 ;; Note: Item's number is in fact a list of numbers.
980 (equal '(1 2)
981 (org-element-map
982 tree 'link
983 (lambda (link)
984 (org-export-get-ordinal
985 (org-export-resolve-fuzzy-link link info) info)) info t))))
986 ;; 4. Link to a target in a footnote should return footnote's
987 ;; number.
988 (org-test-with-parsed-data "
989 Paragraph[1][2][fn:lbl3:C<<target>>][[test]][[target]]\n[1] A\n\n[2] <<test>>B"
990 (should
991 (equal '(2 3)
992 (org-element-map
993 tree 'link
994 (lambda (link)
995 (org-export-get-ordinal
996 (org-export-resolve-fuzzy-link link info) info)) info))))
997 ;; 5. Link to a named element should return sequence number of that
998 ;; element.
999 (org-test-with-parsed-data
1000 "#+NAME: tbl1\n|1|2|\n#+NAME: tbl2\n|3|4|\n#+NAME: tbl3\n|5|6|\n[[tbl2]]"
1001 (should
1002 (= 2
1003 (org-element-map
1004 tree 'link
1005 (lambda (link)
1006 (org-export-get-ordinal
1007 (org-export-resolve-fuzzy-link link info) info)) info t))))
1008 ;; 6. Link to a target not within an item, a table, a footnote
1009 ;; reference or definition should return section number.
1010 (org-test-with-parsed-data
1011 "* Head1\n* Head2\nParagraph<<target>>\n* Head3\n[[target]]"
1012 (should
1013 (equal '(2)
1014 (org-element-map
1015 tree 'link
1016 (lambda (link)
1017 (org-export-get-ordinal
1018 (org-export-resolve-fuzzy-link link info) info)) info t)))))
1020 (ert-deftest test-org-export/resolve-coderef ()
1021 "Test `org-export-resolve-coderef' specifications."
1022 (let ((org-coderef-label-format "(ref:%s)"))
1023 ;; 1. A link to a "-n -k -r" block returns line number.
1024 (org-test-with-parsed-data
1025 "#+BEGIN_EXAMPLE -n -k -r\nText (ref:coderef)\n#+END_EXAMPLE"
1026 (should (= (org-export-resolve-coderef "coderef" info) 1)))
1027 (org-test-with-parsed-data
1028 "#+BEGIN_SRC emacs-lisp -n -k -r\n(+ 1 1) (ref:coderef)\n#+END_SRC"
1029 (should (= (org-export-resolve-coderef "coderef" info) 1)))
1030 ;; 2. A link to a "-n -r" block returns line number.
1031 (org-test-with-parsed-data
1032 "#+BEGIN_EXAMPLE -n -r\nText (ref:coderef)\n#+END_EXAMPLE"
1033 (should (= (org-export-resolve-coderef "coderef" info) 1)))
1034 (org-test-with-parsed-data
1035 "#+BEGIN_SRC emacs-lisp -n -r\n(+ 1 1) (ref:coderef)\n#+END_SRC"
1036 (should (= (org-export-resolve-coderef "coderef" info) 1)))
1037 ;; 3. A link to a "-n" block returns coderef.
1038 (org-test-with-parsed-data
1039 "#+BEGIN_SRC emacs-lisp -n\n(+ 1 1) (ref:coderef)\n#+END_SRC"
1040 (should (equal (org-export-resolve-coderef "coderef" info) "coderef")))
1041 (org-test-with-parsed-data
1042 "#+BEGIN_EXAMPLE -n\nText (ref:coderef)\n#+END_EXAMPLE"
1043 (should (equal (org-export-resolve-coderef "coderef" info) "coderef")))
1044 ;; 4. A link to a "-r" block returns line number.
1045 (org-test-with-parsed-data
1046 "#+BEGIN_SRC emacs-lisp -r\n(+ 1 1) (ref:coderef)\n#+END_SRC"
1047 (should (= (org-export-resolve-coderef "coderef" info) 1)))
1048 (org-test-with-parsed-data
1049 "#+BEGIN_EXAMPLE -r\nText (ref:coderef)\n#+END_EXAMPLE"
1050 (should (= (org-export-resolve-coderef "coderef" info) 1)))
1051 ;; 5. A link to a block without a switch returns coderef.
1052 (org-test-with-parsed-data
1053 "#+BEGIN_SRC emacs-lisp\n(+ 1 1) (ref:coderef)\n#+END_SRC"
1054 (should (equal (org-export-resolve-coderef "coderef" info) "coderef")))
1055 (org-test-with-parsed-data
1056 "#+BEGIN_EXAMPLE\nText (ref:coderef)\n#+END_EXAMPLE"
1057 (should (equal (org-export-resolve-coderef "coderef" info) "coderef")))
1058 ;; 6. Correctly handle continued line numbers. A "+n" switch
1059 ;; should resume numbering from previous block with numbered
1060 ;; lines, ignoring blocks not numbering lines in the process.
1061 ;; A "-n" switch resets count.
1062 (org-test-with-parsed-data "
1063 #+BEGIN_EXAMPLE -n
1064 Text.
1065 #+END_EXAMPLE
1067 #+BEGIN_SRC emacs-lisp
1068 \(- 1 1)
1069 #+END_SRC
1071 #+BEGIN_SRC emacs-lisp +n -r
1072 \(+ 1 1) (ref:addition)
1073 #+END_SRC
1075 #+BEGIN_EXAMPLE -n -r
1076 Another text. (ref:text)
1077 #+END_EXAMPLE"
1078 (should (= (org-export-resolve-coderef "addition" info) 2))
1079 (should (= (org-export-resolve-coderef "text" info) 1)))
1080 ;; 7. Recognize coderef with user-specified syntax.
1081 (org-test-with-parsed-data
1082 "#+BEGIN_EXAMPLE -l \"[ref:%s]\"\nText. [ref:text]\n#+END_EXAMPLE"
1083 (should (equal (org-export-resolve-coderef "text" info) "text")))))
1085 (ert-deftest test-org-export/resolve-fuzzy-link ()
1086 "Test `org-export-resolve-fuzzy-link' specifications."
1087 ;; 1. Match target objects.
1088 (org-test-with-parsed-data "<<target>> [[target]]"
1089 (should
1090 (org-export-resolve-fuzzy-link
1091 (org-element-map tree 'link 'identity info t) info)))
1092 ;; 2. Match target elements.
1093 (org-test-with-parsed-data "#+TARGET: target\n[[target]]"
1094 (should
1095 (org-export-resolve-fuzzy-link
1096 (org-element-map tree 'link 'identity info t) info)))
1097 ;; 3. Match named elements.
1098 (org-test-with-parsed-data "#+NAME: target\nParagraph\n\n[[target]]"
1099 (should
1100 (org-export-resolve-fuzzy-link
1101 (org-element-map tree 'link 'identity info t) info)))
1102 ;; 4. Match exact headline's name.
1103 (org-test-with-parsed-data "* My headline\n[[My headline]]"
1104 (should
1105 (org-export-resolve-fuzzy-link
1106 (org-element-map tree 'link 'identity info t) info)))
1107 ;; 5. Targets objects have priority over named elements and headline
1108 ;; titles.
1109 (org-test-with-parsed-data
1110 "* target\n#+NAME: target\n<<target>>\n\n[[target]]"
1111 (should
1112 (eq 'target
1113 (org-element-type
1114 (org-export-resolve-fuzzy-link
1115 (org-element-map tree 'link 'identity info t) info)))))
1116 ;; 6. Named elements have priority over headline titles.
1117 (org-test-with-parsed-data
1118 "* target\n#+NAME: target\nParagraph\n\n[[target]]"
1119 (should
1120 (eq 'paragraph
1121 (org-element-type
1122 (org-export-resolve-fuzzy-link
1123 (org-element-map tree 'link 'identity info t) info)))))
1124 ;; 7. If link's path starts with a "*", only match headline titles,
1125 ;; though.
1126 (org-test-with-parsed-data
1127 "* target\n#+NAME: target\n<<target>>\n\n[[*target]]"
1128 (should
1129 (eq 'headline
1130 (org-element-type
1131 (org-export-resolve-fuzzy-link
1132 (org-element-map tree 'link 'identity info t) info)))))
1133 ;; 8. Return nil if no match.
1134 (org-test-with-parsed-data "[[target]]"
1135 (should-not
1136 (org-export-resolve-fuzzy-link
1137 (org-element-map tree 'link 'identity info t) info))))
1139 (ert-deftest test-org-export/resolve-id-link ()
1140 "Test `org-export-resolve-id-link' specifications."
1141 ;; 1. Regular test for custom-id link.
1142 (org-test-with-parsed-data "* Headline1
1143 :PROPERTIES:
1144 :CUSTOM-ID: test
1145 :END:
1146 * Headline 2
1147 \[[#test]]"
1148 (should
1149 (org-export-resolve-id-link
1150 (org-element-map tree 'link 'identity info t) info)))
1151 ;; 2. Failing test for custom-id link.
1152 (org-test-with-parsed-data "* Headline1
1153 :PROPERTIES:
1154 :CUSTOM-ID: test
1155 :END:
1156 * Headline 2
1157 \[[#no-match]]"
1158 (should-not
1159 (org-export-resolve-id-link
1160 (org-element-map tree 'link 'identity info t) info)))
1161 ;; 3. Test for internal id target.
1162 (org-test-with-parsed-data "* Headline1
1163 :PROPERTIES:
1164 :ID: aaaa
1165 :END:
1166 * Headline 2
1167 \[[id:aaaa]]"
1168 (should
1169 (org-export-resolve-id-link
1170 (org-element-map tree 'link 'identity info t) info)))
1171 ;; 4. Test for external id target.
1172 (org-test-with-parsed-data "[[id:aaaa]]"
1173 (should
1174 (org-export-resolve-id-link
1175 (org-element-map tree 'link 'identity info t)
1176 (org-combine-plists info '(:id-alist (("aaaa" . "external-file"))))))))
1178 (ert-deftest test-org-export/resolve-radio-link ()
1179 "Test `org-export-resolve-radio-link' specifications."
1180 ;; Standard test.
1181 (org-test-with-temp-text "<<<radio>>> radio"
1182 (org-update-radio-target-regexp)
1183 (should
1184 (let* ((tree (org-element-parse-buffer))
1185 (info `(:parse-tree ,tree)))
1186 (org-export-resolve-radio-link
1187 (org-element-map tree 'link 'identity info t)
1188 info))))
1189 ;; Radio target with objects.
1190 (org-test-with-temp-text "<<<radio \\alpha>>> radio \\alpha"
1191 (org-update-radio-target-regexp)
1192 (should
1193 (let* ((tree (org-element-parse-buffer))
1194 (info `(:parse-tree ,tree)))
1195 (org-export-resolve-radio-link
1196 (org-element-map tree 'link 'identity info t)
1197 info)))))
1201 ;;; Src-block and example-block
1203 (ert-deftest test-org-export/unravel-code ()
1204 "Test `org-export-unravel-code' function."
1205 (let ((org-coderef-label-format "(ref:%s)"))
1206 ;; 1. Code without reference.
1207 (org-test-with-temp-text "#+BEGIN_EXAMPLE\n(+ 1 1)\n#+END_EXAMPLE"
1208 (should (equal (org-export-unravel-code (org-element-at-point))
1209 '("(+ 1 1)\n"))))
1210 ;; 2. Code with reference.
1211 (org-test-with-temp-text
1212 "#+BEGIN_EXAMPLE\n(+ 1 1) (ref:test)\n#+END_EXAMPLE"
1213 (should (equal (org-export-unravel-code (org-element-at-point))
1214 '("(+ 1 1)\n" (1 . "test")))))
1215 ;; 3. Code with user-defined reference.
1216 (org-test-with-temp-text
1217 "#+BEGIN_EXAMPLE -l \"[ref:%s]\"\n(+ 1 1) [ref:test]\n#+END_EXAMPLE"
1218 (should (equal (org-export-unravel-code (org-element-at-point))
1219 '("(+ 1 1)\n" (1 . "test")))))
1220 ;; 4. Code references keys are relative to the current block.
1221 (org-test-with-temp-text "
1222 #+BEGIN_EXAMPLE -n
1223 \(+ 1 1)
1224 #+END_EXAMPLE
1225 #+BEGIN_EXAMPLE +n
1226 \(+ 2 2)
1227 \(+ 3 3) (ref:one)
1228 #+END_EXAMPLE"
1229 (goto-line 5)
1230 (should (equal (org-export-unravel-code (org-element-at-point))
1231 '("(+ 2 2)\n(+ 3 3)\n" (2 . "one")))))))
1235 ;;; Smart Quotes
1237 (ert-deftest test-org-export/activate-smart-quotes ()
1238 "Test `org-export-activate-smart-quotes' specifications."
1239 ;; Opening double quotes: standard test.
1240 (should
1241 (equal
1242 '("some &ldquo;paragraph")
1243 (let ((org-export-default-language "en"))
1244 (org-test-with-parsed-data "some \"paragraph"
1245 (org-element-map
1246 tree 'plain-text
1247 (lambda (s) (org-export-activate-smart-quotes s :html info))
1248 info)))))
1249 ;; Opening quotes: at the beginning of a paragraph.
1250 (should
1251 (equal
1252 '("&ldquo;begin")
1253 (let ((org-export-default-language "en"))
1254 (org-test-with-parsed-data "\"begin"
1255 (org-element-map
1256 tree 'plain-text
1257 (lambda (s) (org-export-activate-smart-quotes s :html info))
1258 info)))))
1259 ;; Opening quotes: after an object.
1260 (should
1261 (equal
1262 '("&ldquo;begin")
1263 (let ((org-export-default-language "en"))
1264 (org-test-with-parsed-data "=verb= \"begin"
1265 (org-element-map
1266 tree 'plain-text
1267 (lambda (s) (org-export-activate-smart-quotes s :html info))
1268 info)))))
1269 ;; Closing quotes: standard test.
1270 (should
1271 (equal
1272 '("some&rdquo; paragraph")
1273 (let ((org-export-default-language "en"))
1274 (org-test-with-parsed-data "some\" paragraph"
1275 (org-element-map
1276 tree 'plain-text
1277 (lambda (s) (org-export-activate-smart-quotes s :html info))
1278 info)))))
1279 ;; Closing quotes: at the end of a paragraph.
1280 (should
1281 (equal
1282 '("end&rdquo;")
1283 (let ((org-export-default-language "en"))
1284 (org-test-with-parsed-data "end\""
1285 (org-element-map
1286 tree 'plain-text
1287 (lambda (s) (org-export-activate-smart-quotes s :html info))
1288 info)))))
1289 ;; Apostrophe: standard test.
1290 (should
1291 (equal
1292 '("It shouldn&rsquo;t fail")
1293 (let ((org-export-default-language "en"))
1294 (org-test-with-parsed-data "It shouldn't fail"
1295 (org-element-map
1296 tree 'plain-text
1297 (lambda (s) (org-export-activate-smart-quotes s :html info))
1298 info)))))
1299 ;; Apostrophe: before an object.
1300 (should
1301 (equal
1302 '("a&rsquo;")
1303 (let ((org-export-default-language "en"))
1304 (org-test-with-parsed-data "a'=b="
1305 (org-element-map
1306 tree 'plain-text
1307 (lambda (s) (org-export-activate-smart-quotes s :html info))
1308 info)))))
1309 ;; Apostrophe: after an object.
1310 (should
1311 (equal
1312 '("&rsquo;s")
1313 (let ((org-export-default-language "en"))
1314 (org-test-with-parsed-data "=code='s"
1315 (org-element-map
1316 tree 'plain-text
1317 (lambda (s) (org-export-activate-smart-quotes s :html info))
1318 info)))))
1319 ;; Special case: isolated quotes.
1320 (should
1321 (equal '("&ldquo;" "&rdquo;")
1322 (let ((org-export-default-language "en"))
1323 (org-test-with-parsed-data "\"$x$\""
1324 (org-element-map
1325 tree 'plain-text
1326 (lambda (s) (org-export-activate-smart-quotes s :html info))
1327 info)))))
1328 ;; Smart quotes in secondary strings.
1329 (should
1330 (equal '("&ldquo;" "&rdquo;")
1331 (let ((org-export-default-language "en"))
1332 (org-test-with-parsed-data "* \"$x$\""
1333 (org-element-map
1334 tree 'plain-text
1335 (lambda (s) (org-export-activate-smart-quotes s :html info))
1336 info)))))
1337 ;; Smart quotes in document keywords.
1338 (should
1339 (equal '("&ldquo;" "&rdquo;")
1340 (let ((org-export-default-language "en"))
1341 (org-test-with-parsed-data "#+TITLE: \"$x$\""
1342 (org-element-map
1343 (plist-get info :title) 'plain-text
1344 (lambda (s) (org-export-activate-smart-quotes s :html info))
1345 info)))))
1346 ;; Smart quotes in parsed affiliated keywords.
1347 (should
1348 (equal '("&ldquo;" "&rdquo;" "Paragraph")
1349 (let ((org-export-default-language "en"))
1350 (org-test-with-parsed-data "#+CAPTION: \"$x$\"\nParagraph"
1351 (org-element-map
1352 tree 'plain-text
1353 (lambda (s) (org-export-activate-smart-quotes s :html info))
1354 info nil nil t))))))
1358 ;;; Tables
1360 (ert-deftest test-org-export/special-column ()
1361 "Test if the table's special column is properly recognized."
1362 ;; 1. First column is special if it contains only a special marking
1363 ;; characters or empty cells.
1364 (org-test-with-temp-text "
1365 | ! | 1 |
1366 | | 2 |"
1367 (should
1368 (org-export-table-has-special-column-p
1369 (org-element-map
1370 (org-element-parse-buffer) 'table 'identity nil 'first-match))))
1371 ;; 2. If the column contains anything else, it isn't special.
1372 (org-test-with-temp-text "
1373 | ! | 1 |
1374 | b | 2 |"
1375 (should-not
1376 (org-export-table-has-special-column-p
1377 (org-element-map
1378 (org-element-parse-buffer) 'table 'identity nil 'first-match))))
1379 ;; 3. Special marking characters are "#", "^", "*", "_", "/", "$"
1380 ;; and "!".
1381 (org-test-with-temp-text "
1382 | # | 1 |
1383 | ^ | 2 |
1384 | * | 3 |
1385 | _ | 4 |
1386 | / | 5 |
1387 | $ | 6 |
1388 | ! | 7 |"
1389 (should
1390 (org-export-table-has-special-column-p
1391 (org-element-map
1392 (org-element-parse-buffer) 'table 'identity nil 'first-match))))
1393 ;; 4. A first column with only empty cells isn't considered as
1394 ;; special.
1395 (org-test-with-temp-text "
1396 | | 1 |
1397 | | 2 |"
1398 (should-not
1399 (org-export-table-has-special-column-p
1400 (org-element-map
1401 (org-element-parse-buffer) 'table 'identity nil 'first-match)))))
1403 (ert-deftest test-org-export/table-row-is-special-p ()
1404 "Test `org-export-table-row-is-special-p' specifications."
1405 ;; 1. A row is special if it has a special marking character in the
1406 ;; special column.
1407 (org-test-with-parsed-data "| ! | 1 |"
1408 (should
1409 (org-export-table-row-is-special-p
1410 (org-element-map tree 'table-row 'identity nil 'first-match) info)))
1411 ;; 2. A row is special when its first field is "/"
1412 (org-test-with-parsed-data "
1413 | / | 1 |
1414 | a | b |"
1415 (should
1416 (org-export-table-row-is-special-p
1417 (org-element-map tree 'table-row 'identity nil 'first-match) info)))
1418 ;; 3. A row only containing alignment cookies is also considered as
1419 ;; special.
1420 (org-test-with-parsed-data "| <5> | | <l> | <l22> |"
1421 (should
1422 (org-export-table-row-is-special-p
1423 (org-element-map tree 'table-row 'identity nil 'first-match) info)))
1424 ;; 4. Everything else isn't considered as special.
1425 (org-test-with-parsed-data "| \alpha | | c |"
1426 (should-not
1427 (org-export-table-row-is-special-p
1428 (org-element-map tree 'table-row 'identity nil 'first-match) info)))
1429 ;; 5. Table's rules are never considered as special rows.
1430 (org-test-with-parsed-data "|---+---|"
1431 (should-not
1432 (org-export-table-row-is-special-p
1433 (org-element-map tree 'table-row 'identity nil 'first-match) info))))
1435 (ert-deftest test-org-export/has-header-p ()
1436 "Test `org-export-table-has-header-p' specifications."
1437 ;; 1. With an header.
1438 (org-test-with-parsed-data "
1439 | a | b |
1440 |---+---|
1441 | c | d |"
1442 (should
1443 (org-export-table-has-header-p
1444 (org-element-map tree 'table 'identity info 'first-match)
1445 info)))
1446 ;; 2. Without an header.
1447 (org-test-with-parsed-data "
1448 | a | b |
1449 | c | d |"
1450 (should-not
1451 (org-export-table-has-header-p
1452 (org-element-map tree 'table 'identity info 'first-match)
1453 info)))
1454 ;; 3. Don't get fooled with starting and ending rules.
1455 (org-test-with-parsed-data "
1456 |---+---|
1457 | a | b |
1458 | c | d |
1459 |---+---|"
1460 (should-not
1461 (org-export-table-has-header-p
1462 (org-element-map tree 'table 'identity info 'first-match)
1463 info))))
1465 (ert-deftest test-org-export/table-row-group ()
1466 "Test `org-export-table-row-group' specifications."
1467 ;; 1. A rule creates a new group.
1468 (org-test-with-parsed-data "
1469 | a | b |
1470 |---+---|
1471 | 1 | 2 |"
1472 (should
1473 (equal
1474 '(1 nil 2)
1475 (mapcar (lambda (row) (org-export-table-row-group row info))
1476 (org-element-map tree 'table-row 'identity)))))
1477 ;; 2. Special rows are ignored in count.
1478 (org-test-with-parsed-data "
1479 | / | < | > |
1480 |---|---+---|
1481 | | 1 | 2 |"
1482 (should
1483 (equal
1484 '(nil nil 1)
1485 (mapcar (lambda (row) (org-export-table-row-group row info))
1486 (org-element-map tree 'table-row 'identity)))))
1487 ;; 3. Double rules also are ignored in count.
1488 (org-test-with-parsed-data "
1489 | a | b |
1490 |---+---|
1491 |---+---|
1492 | 1 | 2 |"
1493 (should
1494 (equal
1495 '(1 nil nil 2)
1496 (mapcar (lambda (row) (org-export-table-row-group row info))
1497 (org-element-map tree 'table-row 'identity))))))
1499 (ert-deftest test-org-export/table-cell-width ()
1500 "Test `org-export-table-cell-width' specifications."
1501 ;; 1. Width is primarily determined by width cookies. If no cookie
1502 ;; is found, cell's width is nil.
1503 (org-test-with-parsed-data "
1504 | / | <l> | <6> | <l7> |
1505 | | a | b | c |"
1506 (should
1507 (equal
1508 '(nil 6 7)
1509 (mapcar (lambda (cell) (org-export-table-cell-width cell info))
1510 (org-element-map tree 'table-cell 'identity info)))))
1511 ;; 2. The last width cookie has precedence.
1512 (org-test-with-parsed-data "
1513 | <6> |
1514 | <7> |
1515 | a |"
1516 (should
1517 (equal
1518 '(7)
1519 (mapcar (lambda (cell) (org-export-table-cell-width cell info))
1520 (org-element-map tree 'table-cell 'identity info)))))
1521 ;; 3. Valid width cookies must have a specific row.
1522 (org-test-with-parsed-data "| <6> | cell |"
1523 (should
1524 (equal
1525 '(nil nil)
1526 (mapcar (lambda (cell) (org-export-table-cell-width cell info))
1527 (org-element-map tree 'table-cell 'identity))))))
1529 (ert-deftest test-org-export/table-cell-alignment ()
1530 "Test `org-export-table-cell-alignment' specifications."
1531 (let ((org-table-number-fraction 0.5)
1532 (org-table-number-regexp "^[0-9]+$"))
1533 ;; 1. Alignment is primarily determined by alignment cookies.
1534 (org-test-with-temp-text "| <l> | <c> | <r> |"
1535 (let* ((tree (org-element-parse-buffer))
1536 (info `(:parse-tree ,tree)))
1537 (should
1538 (equal
1539 '(left center right)
1540 (mapcar (lambda (cell) (org-export-table-cell-alignment cell info))
1541 (org-element-map tree 'table-cell 'identity))))))
1542 ;; 2. The last alignment cookie has precedence.
1543 (org-test-with-parsed-data "
1544 | <l8> |
1545 | cell |
1546 | <r9> |"
1547 (should
1548 (equal
1549 '(right right right)
1550 (mapcar (lambda (cell) (org-export-table-cell-alignment cell info))
1551 (org-element-map tree 'table-cell 'identity)))))
1552 ;; 3. If there's no cookie, cell's contents determine alignment.
1553 ;; A column mostly made of cells containing numbers will align
1554 ;; its cells to the right.
1555 (org-test-with-parsed-data "
1556 | 123 |
1557 | some text |
1558 | 12345 |"
1559 (should
1560 (equal
1561 '(right right right)
1562 (mapcar (lambda (cell)
1563 (org-export-table-cell-alignment cell info))
1564 (org-element-map tree 'table-cell 'identity)))))
1565 ;; 4. Otherwise, they will be aligned to the left.
1566 (org-test-with-parsed-data "
1567 | text |
1568 | some text |
1569 | \alpha |"
1570 (should
1571 (equal
1572 '(left left left)
1573 (mapcar (lambda (cell)
1574 (org-export-table-cell-alignment cell info))
1575 (org-element-map tree 'table-cell 'identity)))))))
1577 (ert-deftest test-org-export/table-cell-borders ()
1578 "Test `org-export-table-cell-borders' specifications."
1579 ;; 1. Recognize various column groups indicators.
1580 (org-test-with-parsed-data "| / | < | > | <> |"
1581 (should
1582 (equal
1583 '((right bottom top) (left bottom top) (right bottom top)
1584 (right left bottom top))
1585 (mapcar (lambda (cell)
1586 (org-export-table-cell-borders cell info))
1587 (org-element-map tree 'table-cell 'identity)))))
1588 ;; 2. Accept shortcuts to define column groups.
1589 (org-test-with-parsed-data "| / | < | < |"
1590 (should
1591 (equal
1592 '((right bottom top) (right left bottom top) (left bottom top))
1593 (mapcar (lambda (cell)
1594 (org-export-table-cell-borders cell info))
1595 (org-element-map tree 'table-cell 'identity)))))
1596 ;; 3. A valid column groups row must start with a "/".
1597 (org-test-with-parsed-data "
1598 | | < |
1599 | a | b |"
1600 (should
1601 (equal '((top) (top) (bottom) (bottom))
1602 (mapcar (lambda (cell)
1603 (org-export-table-cell-borders cell info))
1604 (org-element-map tree 'table-cell 'identity)))))
1605 ;; 4. Take table rules into consideration.
1606 (org-test-with-parsed-data "
1607 | 1 |
1608 |---|
1609 | 2 |"
1610 (should
1611 (equal '((below top) (bottom above))
1612 (mapcar (lambda (cell)
1613 (org-export-table-cell-borders cell info))
1614 (org-element-map tree 'table-cell 'identity)))))
1615 ;; 5. Top and (resp. bottom) rules induce both `top' and `above'
1616 ;; (resp. `bottom' and `below') borders. Any special row is
1617 ;; ignored.
1618 (org-test-with-parsed-data "
1619 |---+----|
1620 | / | |
1621 | | 1 |
1622 |---+----|"
1623 (should
1624 (equal '((bottom below top above))
1625 (last
1626 (mapcar (lambda (cell)
1627 (org-export-table-cell-borders cell info))
1628 (org-element-map tree 'table-cell 'identity)))))))
1630 (ert-deftest test-org-export/table-dimensions ()
1631 "Test `org-export-table-dimensions' specifications."
1632 ;; 1. Standard test.
1633 (org-test-with-parsed-data "
1634 | 1 | 2 | 3 |
1635 | 4 | 5 | 6 |"
1636 (should
1637 (equal '(2 . 3)
1638 (org-export-table-dimensions
1639 (org-element-map tree 'table 'identity info 'first-match) info))))
1640 ;; 2. Ignore horizontal rules and special columns.
1641 (org-test-with-parsed-data "
1642 | / | < | > |
1643 | 1 | 2 | 3 |
1644 |---+---+---|
1645 | 4 | 5 | 6 |"
1646 (should
1647 (equal '(2 . 3)
1648 (org-export-table-dimensions
1649 (org-element-map tree 'table 'identity info 'first-match) info)))))
1651 (ert-deftest test-org-export/table-cell-address ()
1652 "Test `org-export-table-cell-address' specifications."
1653 ;; 1. Standard test: index is 0-based.
1654 (org-test-with-parsed-data "| a | b |"
1655 (should
1656 (equal '((0 . 0) (0 . 1))
1657 (org-element-map
1658 tree 'table-cell
1659 (lambda (cell) (org-export-table-cell-address cell info))
1660 info))))
1661 ;; 2. Special column isn't counted, nor are special rows.
1662 (org-test-with-parsed-data "
1663 | / | <> |
1664 | | c |"
1665 (should
1666 (equal '(0 . 0)
1667 (org-export-table-cell-address
1668 (car (last (org-element-map tree 'table-cell 'identity info)))
1669 info))))
1670 ;; 3. Tables rules do not count either.
1671 (org-test-with-parsed-data "
1672 | a |
1673 |---|
1674 | b |
1675 |---|
1676 | c |"
1677 (should
1678 (equal '(2 . 0)
1679 (org-export-table-cell-address
1680 (car (last (org-element-map tree 'table-cell 'identity info)))
1681 info))))
1682 ;; 4. Return nil for special cells.
1683 (org-test-with-parsed-data "| / | a |"
1684 (should-not
1685 (org-export-table-cell-address
1686 (org-element-map tree 'table-cell 'identity nil 'first-match)
1687 info))))
1689 (ert-deftest test-org-export/get-table-cell-at ()
1690 "Test `org-export-get-table-cell-at' specifications."
1691 ;; 1. Address ignores special columns, special rows and rules.
1692 (org-test-with-parsed-data "
1693 | / | <> |
1694 | | a |
1695 |---+----|
1696 | | b |"
1697 (should
1698 (equal '("b")
1699 (org-element-contents
1700 (org-export-get-table-cell-at
1701 '(1 . 0)
1702 (org-element-map tree 'table 'identity info 'first-match)
1703 info)))))
1704 ;; 2. Return value for a non-existent address is nil.
1705 (org-test-with-parsed-data "| a |"
1706 (should-not
1707 (org-export-get-table-cell-at
1708 '(2 . 2)
1709 (org-element-map tree 'table 'identity info 'first-match)
1710 info)))
1711 (org-test-with-parsed-data "| / |"
1712 (should-not
1713 (org-export-get-table-cell-at
1714 '(0 . 0)
1715 (org-element-map tree 'table 'identity info 'first-match)
1716 info))))
1718 (ert-deftest test-org-export/table-cell-starts-colgroup-p ()
1719 "Test `org-export-table-cell-starts-colgroup-p' specifications."
1720 ;; 1. A cell at a beginning of a row always starts a column group.
1721 (org-test-with-parsed-data "| a |"
1722 (should
1723 (org-export-table-cell-starts-colgroup-p
1724 (org-element-map tree 'table-cell 'identity info 'first-match)
1725 info)))
1726 ;; 2. Special column should be ignored when determining the
1727 ;; beginning of the row.
1728 (org-test-with-parsed-data "
1729 | / | |
1730 | | a |"
1731 (should
1732 (org-export-table-cell-starts-colgroup-p
1733 (org-element-map tree 'table-cell 'identity info 'first-match)
1734 info)))
1735 ;; 2. Explicit column groups.
1736 (org-test-with-parsed-data "
1737 | / | | < |
1738 | a | b | c |"
1739 (should
1740 (equal
1741 '(yes no yes)
1742 (org-element-map
1743 tree 'table-cell
1744 (lambda (cell)
1745 (if (org-export-table-cell-starts-colgroup-p cell info) 'yes 'no))
1746 info)))))
1748 (ert-deftest test-org-export/table-cell-ends-colgroup-p ()
1749 "Test `org-export-table-cell-ends-colgroup-p' specifications."
1750 ;; 1. A cell at the end of a row always ends a column group.
1751 (org-test-with-parsed-data "| a |"
1752 (should
1753 (org-export-table-cell-ends-colgroup-p
1754 (org-element-map tree 'table-cell 'identity info 'first-match)
1755 info)))
1756 ;; 2. Special column should be ignored when determining the
1757 ;; beginning of the row.
1758 (org-test-with-parsed-data "
1759 | / | |
1760 | | a |"
1761 (should
1762 (org-export-table-cell-ends-colgroup-p
1763 (org-element-map tree 'table-cell 'identity info 'first-match)
1764 info)))
1765 ;; 3. Explicit column groups.
1766 (org-test-with-parsed-data "
1767 | / | < | |
1768 | a | b | c |"
1769 (should
1770 (equal
1771 '(yes no yes)
1772 (org-element-map
1773 tree 'table-cell
1774 (lambda (cell)
1775 (if (org-export-table-cell-ends-colgroup-p cell info) 'yes 'no))
1776 info)))))
1778 (ert-deftest test-org-export/table-row-starts-rowgroup-p ()
1779 "Test `org-export-table-row-starts-rowgroup-p' specifications."
1780 ;; 1. A row at the beginning of a table always starts a row group.
1781 ;; So does a row following a table rule.
1782 (org-test-with-parsed-data "
1783 | a |
1784 |---|
1785 | b |"
1786 (should
1787 (equal
1788 '(yes no yes)
1789 (org-element-map
1790 tree 'table-row
1791 (lambda (row)
1792 (if (org-export-table-row-starts-rowgroup-p row info) 'yes 'no))
1793 info))))
1794 ;; 2. Special rows should be ignored when determining the beginning
1795 ;; of the row.
1796 (org-test-with-parsed-data "
1797 | / | < |
1798 | | a |
1799 |---+---|
1800 | / | < |
1801 | | b |"
1802 (should
1803 (equal
1804 '(yes no yes)
1805 (org-element-map
1806 tree 'table-row
1807 (lambda (row)
1808 (if (org-export-table-row-starts-rowgroup-p row info) 'yes 'no))
1809 info)))))
1811 (ert-deftest test-org-export/table-row-ends-rowgroup-p ()
1812 "Test `org-export-table-row-ends-rowgroup-p' specifications."
1813 ;; 1. A row at the end of a table always ends a row group. So does
1814 ;; a row preceding a table rule.
1815 (org-test-with-parsed-data "
1816 | a |
1817 |---|
1818 | b |"
1819 (should
1820 (equal
1821 '(yes no yes)
1822 (org-element-map
1823 tree 'table-row
1824 (lambda (row)
1825 (if (org-export-table-row-ends-rowgroup-p row info) 'yes 'no))
1826 info))))
1827 ;; 2. Special rows should be ignored when determining the beginning
1828 ;; of the row.
1829 (org-test-with-parsed-data "
1830 | | a |
1831 | / | < |
1832 |---+---|
1833 | | b |
1834 | / | < |"
1835 (should
1836 (equal
1837 '(yes no yes)
1838 (org-element-map
1839 tree 'table-row
1840 (lambda (row)
1841 (if (org-export-table-row-ends-rowgroup-p row info) 'yes 'no))
1842 info)))))
1844 (ert-deftest test-org-export/table-row-starts-header-p ()
1845 "Test `org-export-table-row-starts-header-p' specifications."
1846 ;; 1. Only the row starting the first row group starts the table
1847 ;; header.
1848 (org-test-with-parsed-data "
1849 | a |
1850 | b |
1851 |---|
1852 | c |"
1853 (should
1854 (equal
1855 '(yes no no no)
1856 (org-element-map
1857 tree 'table-row
1858 (lambda (row)
1859 (if (org-export-table-row-starts-header-p row info) 'yes 'no))
1860 info))))
1861 ;; 2. A row cannot start an header if there's no header in the
1862 ;; table.
1863 (org-test-with-parsed-data "
1864 | a |
1865 |---|"
1866 (should-not
1867 (org-export-table-row-starts-header-p
1868 (org-element-map tree 'table-row 'identity info 'first-match)
1869 info))))
1871 (ert-deftest test-org-export/table-row-ends-header-p ()
1872 "Test `org-export-table-row-ends-header-p' specifications."
1873 ;; 1. Only the row starting the first row group starts the table
1874 ;; header.
1875 (org-test-with-parsed-data "
1876 | a |
1877 | b |
1878 |---|
1879 | c |"
1880 (should
1881 (equal
1882 '(no yes no no)
1883 (org-element-map
1884 tree 'table-row
1885 (lambda (row)
1886 (if (org-export-table-row-ends-header-p row info) 'yes 'no))
1887 info))))
1888 ;; 2. A row cannot start an header if there's no header in the
1889 ;; table.
1890 (org-test-with-parsed-data "
1891 | a |
1892 |---|"
1893 (should-not
1894 (org-export-table-row-ends-header-p
1895 (org-element-map tree 'table-row 'identity info 'first-match)
1896 info))))
1900 ;;; Topology
1902 (ert-deftest test-org-export/get-next-element ()
1903 "Test `org-export-get-next-element' specifications."
1904 ;; Standard test.
1905 (should
1906 (equal "b"
1907 (org-test-with-parsed-data "* Headline\n*a* b"
1908 (org-export-get-next-element
1909 (org-element-map tree 'bold 'identity info t) info))))
1910 ;; Return nil when no previous element.
1911 (should-not
1912 (org-test-with-parsed-data "* Headline\na *b*"
1913 (org-export-get-next-element
1914 (org-element-map tree 'bold 'identity info t) info)))
1915 ;; Non-exportable elements are ignored.
1916 (should-not
1917 (let ((org-export-with-timestamps nil))
1918 (org-test-with-parsed-data "\alpha <2012-03-29 Thu>"
1919 (org-export-get-next-element
1920 (org-element-map tree 'entity 'identity info t) info))))
1921 ;; Find next element in secondary strings.
1922 (should
1923 (eq 'verbatim
1924 (org-test-with-parsed-data "* a =verb="
1925 (org-element-type
1926 (org-export-get-next-element
1927 (org-element-map tree 'plain-text 'identity info t) info)))))
1928 ;; Find next element in document keywords.
1929 (should
1930 (eq 'verbatim
1931 (org-test-with-parsed-data "#+TITLE: a =verb="
1932 (org-element-type
1933 (org-export-get-next-element
1934 (org-element-map
1935 (plist-get info :title) 'plain-text 'identity info t) info)))))
1936 ;; Find next element in parsed affiliated keywords.
1937 (should
1938 (eq 'verbatim
1939 (org-test-with-parsed-data "#+CAPTION: a =verb=\nParagraph"
1940 (org-element-type
1941 (org-export-get-next-element
1942 (org-element-map tree 'plain-text 'identity info t nil t) info))))))
1944 (ert-deftest test-org-export/get-previous-element ()
1945 "Test `org-export-get-previous-element' specifications."
1946 ;; Standard test.
1947 (should
1948 (equal "a "
1949 (org-test-with-parsed-data "* Headline\na *b*"
1950 (org-export-get-previous-element
1951 (org-element-map tree 'bold 'identity info t) info))))
1952 ;; Return nil when no previous element.
1953 (should-not
1954 (org-test-with-parsed-data "* Headline\n*a* b"
1955 (org-export-get-previous-element
1956 (org-element-map tree 'bold 'identity info t) info)))
1957 ;; Non-exportable elements are ignored.
1958 (should-not
1959 (let ((org-export-with-timestamps nil))
1960 (org-test-with-parsed-data "<2012-03-29 Thu> \alpha"
1961 (org-export-get-previous-element
1962 (org-element-map tree 'entity 'identity info t) info))))
1963 ;; Find previous element in secondary strings.
1964 (should
1965 (eq 'verbatim
1966 (org-test-with-parsed-data "* =verb= a"
1967 (org-element-type
1968 (org-export-get-previous-element
1969 (org-element-map tree 'plain-text 'identity info t) info)))))
1970 ;; Find previous element in document keywords.
1971 (should
1972 (eq 'verbatim
1973 (org-test-with-parsed-data "#+TITLE: =verb= a"
1974 (org-element-type
1975 (org-export-get-previous-element
1976 (org-element-map
1977 (plist-get info :title) 'plain-text 'identity info t) info)))))
1978 ;; Find previous element in parsed affiliated keywords.
1979 (should
1980 (eq 'verbatim
1981 (org-test-with-parsed-data "#+CAPTION: =verb= a\nParagraph"
1982 (org-element-type
1983 (org-export-get-previous-element
1984 (org-element-map tree 'plain-text 'identity info t nil t) info))))))
1987 (provide 'test-org-export)
1988 ;;; test-org-export.el end here