lisp/org-table.el: fix table alignment
[org-mode/org-tableheadings.git] / testing / lisp / test-org-footnote.el
blobeca24d31570574c688bee6a9820807f71cdf3acf
1 ;;; test-org-footnote.el --- Tests for org-footnote.el
3 ;; Copyright (C) 2012-2015, 2019 Nicolas Goaziou
5 ;; Author: Nicolas Goaziou <mail at nicolasgoaziou dot fr>
7 ;; This program is free software; you can redistribute it and/or modify
8 ;; it under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation, either version 3 of the License, or
10 ;; (at your option) any later version.
12 ;; This program is distributed in the hope that it will be useful,
13 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ;; GNU General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
20 ;;; Code:
22 (ert-deftest test-org-footnote/new ()
23 "Test `org-footnote-new' specifications."
24 ;; `org-footnote-auto-label' is t.
25 (should
26 (string-match-p
27 "Test\\[fn:1\\]\n+\\[fn:1\\]"
28 (org-test-with-temp-text "Test<point>"
29 (let ((org-footnote-auto-label t)
30 (org-footnote-section nil))
31 (org-footnote-new))
32 (buffer-string))))
33 ;; `org-footnote-auto-label' is `random'.
34 (should
35 (string-match-p
36 "Test\\[fn:\\(.+?\\)\\]\n+\\[fn:\\1\\]"
37 (org-test-with-temp-text "Test<point>"
38 (let ((org-footnote-auto-label 'random)
39 (org-footnote-section nil))
40 (org-footnote-new))
41 (buffer-string))))
42 ;; Error at beginning of line.
43 (should-error
44 (org-test-with-temp-text "<point>Test"
45 (org-footnote-new)))
46 ;; Error at keywords.
47 (should-error
48 (org-test-with-temp-text "#+TIT<point>LE: value"
49 (org-footnote-new)))
50 (should-error
51 (org-test-with-temp-text "#+CAPTION: <point>\nParagraph"
52 (org-footnote-new)))
53 ;; Allow new footnotes in blank lines at the beginning of the
54 ;; document.
55 (should
56 (string-match-p
57 " \\[fn:1\\]"
58 (org-test-with-temp-text " <point>"
59 (let ((org-footnote-auto-label t)) (org-footnote-new))
60 (buffer-string))))
61 ;; In an headline or inlinetask, point must be either on the
62 ;; heading itself or on the blank lines below.
63 (should (org-test-with-temp-text "* H<point>" (org-footnote-new) t))
64 (should
65 (org-test-with-temp-text "* H\n <point>\nParagraph" (org-footnote-new) t))
66 (should-error (org-test-with-temp-text "*<point> H" (org-footnote-new) t))
67 (should-error
68 (org-test-with-temp-text "* H <point>:tag:" (org-footnote-new) t))
69 ;; Allow new footnotes within recursive objects, but not in links.
70 (should
71 (string-match-p
72 " \\*bold\\[fn:1\\]\\*"
73 (org-test-with-temp-text " *bold<point>*"
74 (let ((org-footnote-auto-label t)) (org-footnote-new))
75 (buffer-string))))
76 (should-error
77 (org-test-with-temp-text " [[https://orgmode.org][Org mode<point>]]"
78 (org-footnote-new)))
79 ;; Allow new footnotes in blank lines after an element or white
80 ;; spaces after an object.
81 (should
82 (string-match-p
83 " \\[fn:1\\]"
84 (org-test-with-temp-text "#+BEGIN_EXAMPLE\nA\n#+END_EXAMPLE\n <point>"
85 (let ((org-footnote-auto-label t)) (org-footnote-new))
86 (buffer-string))))
87 (should
88 (string-match-p
89 " \\*bold\\*\\[fn:1\\]"
90 (org-test-with-temp-text " *bold*<point>"
91 (let ((org-footnote-auto-label t)) (org-footnote-new))
92 (buffer-string))))
93 ;; When creating a new footnote, move to its definition.
94 (should
95 (string=
96 "[fn:1]"
97 (org-test-with-temp-text "Text<point>"
98 (let ((org-footnote-auto-label t)
99 (org-footnote-auto-adjust nil))
100 (org-footnote-new))
101 (buffer-substring-no-properties (line-beginning-position) (point)))))
102 ;; Re-order and re-label footnotes properly when
103 ;; `org-footnote-auto-adjust' is non-nil.
104 (should
105 (string=
106 "[fn:1] 1\n\n[fn:2] \n\n[fn:3] 2\n"
107 (org-test-with-temp-text
108 "Text[fn:1]Text<point>Text[fn:2]\n\n[fn:1] 1\n\n[fn:2] 2"
109 (let ((org-footnote-auto-label t)
110 (org-footnote-auto-adjust t)
111 (org-footnote-section nil))
112 (org-footnote-new))
113 (buffer-substring-no-properties
114 (line-beginning-position -1)
115 (line-beginning-position 4)))))
116 ;; Do not alter file local variables when inserting new definition
117 ;; label.
118 (should
119 (equal "Paragraph[fn:1]
121 \[fn:1]
122 # Local Variables:
123 # foo: t
124 # End:"
125 (org-test-with-temp-text
126 "Paragraph<point>\n# Local Variables:\n# foo: t\n# End:"
127 (let ((org-footnote-section nil)) (org-footnote-new))
128 (buffer-string))))
129 (should
130 (equal "Paragraph[fn:1]
132 * Footnotes
134 \[fn:1]
135 # Local Variables:
136 # foo: t
137 # End:"
138 (org-test-with-temp-text
139 "Paragraph<point>\n# Local Variables:\n# foo: t\n# End:"
140 (let ((org-footnote-section "Footnotes")) (org-footnote-new))
141 (buffer-string)))))
143 (ert-deftest test-org-footnote/delete ()
144 "Test `org-footnote-delete' specifications."
145 ;; Regular test.
146 (should
147 (equal "Paragraph"
148 (org-test-with-temp-text "Paragraph<point>[fn:1]\n\n[fn:1] Definition"
149 (org-footnote-delete)
150 (org-trim (buffer-string)))))
151 ;; Remove multiple definitions and references.
152 (should
153 (equal "Paragraph and another"
154 (org-test-with-temp-text
155 "Paragraph<point>[fn:1] and another[fn:1]
157 \[fn:1] def
159 \[fn:1] def"
160 (org-footnote-delete)
161 (org-trim (buffer-string)))))
162 ;; Delete inline footnotes and all references.
163 (should
164 (equal "Para and"
165 (org-test-with-temp-text "Para<point>[fn:label:def] and[fn:label]"
166 (org-footnote-delete)
167 (org-trim (buffer-string)))))
168 ;; Delete anonymous footnotes.
169 (should
170 (equal "Para"
171 (let ((org-footnote-section nil))
172 (org-test-with-temp-text "Para<point>[fn::def]"
173 (org-footnote-delete)
174 (org-trim (buffer-string))))))
175 ;; With an argument, delete footnote with specified label.
176 (should
177 (equal "Paragraph[fn:1] and another\n\n[fn:1] def"
178 (let ((org-footnote-section nil))
179 (org-test-with-temp-text
180 "Paragraph[fn:1] and another[fn:2]\n\n[fn:1] def\n\n[fn:2] def2"
181 (org-footnote-delete "2")
182 (org-trim (buffer-string))))))
183 ;; Error when no argument is specified at point is not at a footnote
184 ;; reference.
185 (should-error
186 (org-test-with-temp-text "Para[fn:1]\n\n[fn:1] Def"
187 (org-footnote-delete)))
188 ;; Correctly delete footnotes with multiple paragraphs.
189 (should
190 (equal "Para\n\n\nOutside footnote."
191 (let ((org-footnote-section nil))
192 (org-test-with-temp-text
193 "Para[fn:1]\n\n[fn:1] para1\n\npara2\n\n\nOutside footnote."
194 (org-footnote-delete "1")
195 (org-trim (buffer-string))))))
196 ;; Remove blank lines above the footnote but preserve those after
197 ;; it.
198 (should
199 (equal "Text\n\n\nOther text."
200 (let ((org-footnote-section nil))
201 (org-test-with-temp-text
202 "Text[fn:1]\n\n[fn:1] Definition.\n\n\nOther text."
203 (org-footnote-delete "1")
204 (buffer-string)))))
205 ;; Preserve file local variables when deleting a footnote.
206 (should
207 (equal
208 "Paragraph\n# Local Variables:\n# foo: t\n# End:"
209 (org-test-with-temp-text
210 "Paragraph[fn:1]\n[fn:1] Def 1\n# Local Variables:\n# foo: t\n# End:"
211 (let ((org-footnote-section nil)) (org-footnote-delete "1"))
212 (buffer-string)))))
214 (ert-deftest test-org-footnote/goto-definition ()
215 "Test `org-footnote-goto-definition' specifications."
216 ;; Error on unknown definitions.
217 (should-error
218 (org-test-with-temp-text "No footnote definition"
219 (org-footnote-goto-definition "1")))
220 ;; Error when trying to reach a definition outside narrowed part of
221 ;; buffer.
222 (should-error
223 (org-test-with-temp-text "Some text<point>\n[fn:1] Definition."
224 (narrow-to-region (point-min) (point))
225 (org-footnote-goto-definition "1")))
226 (should-error
227 (org-test-with-temp-text "[fn:1] Definition.\n<point>Some text"
228 (narrow-to-region (point) (point-max))
229 (org-footnote-goto-definition "1")))
230 ;; Otherwise, move at the beginning of the definition, including
231 ;; anonymous footnotes.
232 (should
233 (equal
234 " Definition."
235 (org-test-with-temp-text "Some text\n[fn:1] Definition."
236 (org-footnote-goto-definition "1")
237 (buffer-substring (point) (point-max)))))
238 (should
239 (equal
240 "definition]"
241 (org-test-with-temp-text "Some text[fn:label:definition]"
242 (org-footnote-goto-definition "label")
243 (buffer-substring (point) (point-max))))))
245 (ert-deftest test-org-footnote/goto-previous-reference ()
246 "Test `org-footnote-goto-previous-reference' specifications."
247 ;; Error on unknown reference.
248 (should-error
249 (org-test-with-temp-text "No footnote reference"
250 (org-footnote-goto-previous-reference "1")))
251 ;; Error when trying to reach a reference outside narrowed part of
252 ;; buffer.
253 (should-error
254 (org-test-with-temp-text "Some text<point>\nReference[fn:1]."
255 (narrow-to-region (point-min) (point))
256 (org-footnote-goto-previous-reference "1")))
257 ;; Otherwise, move to closest reference from point.
258 (should
259 (org-test-with-temp-text "First reference[fn:1]\nReference[fn:1].<point>"
260 (org-footnote-goto-previous-reference "1")
261 (= (line-end-position) (point-max))))
262 (should
263 (org-test-with-temp-text "First reference[fn:1]\nReference[fn:1]."
264 (org-footnote-goto-previous-reference "1")
265 (= (line-beginning-position) (point-min)))))
267 (ert-deftest test-org-footnote/sort ()
268 "Test `org-footnote-sort' specifications."
269 ;; Reorder definitions with a nil `org-footnote-section'. In this
270 ;; case each definition is written at the end of the section
271 ;; containing its first reference.
272 (should
273 (equal
275 Text[fn:1][fn:2]
277 \[fn:1] Def 1
279 \[fn:2] Def 2
281 (org-test-with-temp-text "
282 Text[fn:1][fn:2]
284 \[fn:2] Def 2
286 \[fn:1] Def 1"
287 (let ((org-footnote-section nil)) (org-footnote-sort))
288 (buffer-string))))
289 (should
290 (equal
292 * H1
293 Text[fn:1]
295 \[fn:1] Def 1
296 * H2
297 Text[fn:2]
299 \[fn:2] Def 2
301 (org-test-with-temp-text "
302 * H1
303 Text[fn:1]
304 * H2
305 Text[fn:2]
307 \[fn:1] Def 1
309 \[fn:2] Def 2
311 (let ((org-footnote-section nil)) (org-footnote-sort))
312 (buffer-string))))
313 ;; Reorder definitions with a non-nil `org-footnote-section'.
314 (should
315 (equal
317 Text[fn:1][fn:2]
319 * Footnotes
321 \[fn:1] Def 1
323 \[fn:2] Def 2
325 (org-test-with-temp-text "
326 Text[fn:1][fn:2]
328 \[fn:2] Def 2
330 \[fn:1] Def 1"
331 (let ((org-footnote-section "Footnotes")) (org-footnote-sort))
332 (buffer-string))))
333 ;; When `org-footnote-section' is non-nil, clear previous footnote
334 ;; sections.
335 (should
336 (equal
338 Text[fn:1]
340 * Headline
342 * Other headline
344 * Footnotes
346 \[fn:1] Def 1
348 (org-test-with-temp-text "
349 Text[fn:1]
351 * Footnotes
353 \[fn:1] Def 1
355 * Headline
357 ** Footnotes
359 * Other headline"
360 (let ((org-footnote-section "Footnotes")) (org-footnote-sort))
361 (buffer-string))))
362 ;; Ignore anonymous footnotes.
363 (should
364 (equal
366 Text[fn:1][fn::inline][fn:2]
368 \[fn:1] Def 1
370 \[fn:2] Def 2
372 (org-test-with-temp-text
374 Text[fn:1][fn::inline][fn:2]
376 \[fn:2] Def 2
378 \[fn:1] Def 1"
379 (let ((org-footnote-section nil)) (org-footnote-sort))
380 (buffer-string))))
381 ;; Ignore inline footnotes.
382 (should
383 (equal
385 Text[fn:1][fn:label:inline][fn:2]
387 \[fn:1] Def 1
389 \[fn:2] Def 2
391 (org-test-with-temp-text
393 Text[fn:1][fn:label:inline][fn:2]
395 \[fn:2] Def 2
397 \[fn:1] Def 1"
398 (let ((org-footnote-section nil)) (org-footnote-sort))
399 (buffer-string))))
400 ;; Handle (deeply) nested footnotes.
401 (should
402 (equal
404 Text[fn:1][fn:3]
406 \[fn:1] Def 1[fn:2]
408 \[fn:2] Def 2
410 \[fn:3] Def 3
412 (org-test-with-temp-text "
413 Text[fn:1][fn:3]
415 \[fn:1] Def 1[fn:2]
417 \[fn:3] Def 3
419 \[fn:2] Def 2
421 (let ((org-footnote-section nil)) (org-footnote-sort))
422 (buffer-string))))
423 (should
424 (equal
426 Text[fn:1][fn:4]
428 \[fn:1] Def 1[fn:2]
430 \[fn:2] Def 2[fn:3]
432 \[fn:3] Def 3
434 \[fn:4] Def 4
436 (org-test-with-temp-text "
437 Text[fn:1][fn:4]
439 \[fn:1] Def 1[fn:2]
441 \[fn:3] Def 3
443 \[fn:2] Def 2[fn:3]
445 \[fn:4] Def 4
447 (let ((org-footnote-section nil)) (org-footnote-sort))
448 (buffer-string))))
449 ;; When multiple (nested) references are used, make sure to insert
450 ;; definition only once.
451 (should
452 (equal
454 * Section 1
456 Text[fn:1]
458 \[fn:1] Def 1
460 * Section 2
462 Text[fn:1]"
463 (org-test-with-temp-text
465 * Section 1
467 Text[fn:1]
469 \[fn:1] Def 1
471 * Section 2
473 Text[fn:1]"
474 (let ((org-footnote-section nil)) (org-footnote-sort))
475 (buffer-string))))
476 (should
477 (equal
479 Text[fn:1][fn:4]
481 \[fn:1] Def 1[fn:2][fn:3]
483 \[fn:2] Def 2[fn:3]
485 \[fn:3] Def 3
487 \[fn:4] Def 4
489 (org-test-with-temp-text "
490 Text[fn:1][fn:4]
492 \[fn:1] Def 1[fn:2][fn:3]
494 \[fn:3] Def 3
496 \[fn:2] Def 2[fn:3]
498 \[fn:4] Def 4
500 (let ((org-footnote-section nil)) (org-footnote-sort))
501 (buffer-string))))
502 ;; Insert un-referenced definitions at the end.
503 (should
504 (equal
505 "Text[fn:9]
507 \[fn:9] B
509 \[fn:1] A
511 (org-test-with-temp-text "Text[fn:9]\n\n[fn:1] A\n[fn:9] B"
512 (let ((org-footnote-section nil)) (org-footnote-sort))
513 (buffer-string))))
514 ;; When sorting, preserve file local variables.
515 (should
516 (equal "
517 Paragraph[fn:1][fn:2]
519 \[fn:1] Def 1
521 \[fn:2] Def 2
523 # Local Variables:
524 # foo: t
525 # End:"
526 (org-test-with-temp-text
528 Paragraph[fn:1][fn:2]
530 \[fn:2] Def 2
532 \[fn:1] Def 1
534 # Local Variables:
535 # foo: t
536 # End:"
537 (let ((org-footnote-section nil)) (org-footnote-sort))
538 (buffer-string)))))
540 (ert-deftest test-org-footnote/renumber-fn:N ()
541 "Test `org-footnote-renumber-fn:N' specifications."
542 ;; Renumber (inline) references and definitions.
543 (should
544 (equal
545 "Test[fn:1]"
546 (org-test-with-temp-text "Test[fn:99]"
547 (org-footnote-renumber-fn:N)
548 (buffer-string))))
549 (should
550 (equal
551 "Test[fn:1]\n\n[fn:1] 99"
552 (org-test-with-temp-text "Test[fn:99]\n\n[fn:99] 99"
553 (org-footnote-renumber-fn:N)
554 (buffer-string))))
555 (should
556 (equal
557 "Test[fn:1:99]"
558 (org-test-with-temp-text "Test[fn:99:99]"
559 (org-footnote-renumber-fn:N)
560 (buffer-string))))
561 ;; No-op if there's no numbered footnote.
562 (should
563 (equal
564 "Test[fn:label]\n\n[fn:label] Def"
565 (org-test-with-temp-text "Test[fn:label]\n\n[fn:label] Def"
566 (org-footnote-renumber-fn:N)
567 (buffer-string))))
568 ;; Definitions without a reference get the highest numbers.
569 (should
570 (equal
571 "Test[fn:1]\n[fn:1] 1\n[fn:2] 99"
572 (org-test-with-temp-text "Test[fn:1]\n[fn:1] 1\n[fn:99] 99"
573 (org-footnote-renumber-fn:N)
574 (buffer-string))))
575 ;; Sort labels in sequence. Anonymous footnotes are ignored.
576 (should
577 (equal
578 "Test[fn:1][fn:2:def][fn:3]"
579 (org-test-with-temp-text "Test[fn:4][fn:3:def][fn:2]"
580 (org-footnote-renumber-fn:N)
581 (buffer-string))))
582 (should
583 (equal
584 "Test[fn:1][fn::def][fn:2]"
585 (org-test-with-temp-text "Test[fn:4][fn::def][fn:2]"
586 (org-footnote-renumber-fn:N)
587 (buffer-string)))))
589 (ert-deftest test-org-footnote/normalize ()
590 "Test `org-footnote-normalize' specifications."
591 ;; Normalize regular, inline and anonymous references.
592 (should
593 (equal
594 "Test[fn:1]\n\n[fn:1] def\n"
595 (org-test-with-temp-text "Test[fn:label]\n[fn:label] def"
596 (let ((org-footnote-section nil)) (org-footnote-normalize))
597 (buffer-string))))
598 (should
599 (equal
600 "Test[fn:1]\n\n[fn:1] def\n"
601 (org-test-with-temp-text "Test[fn:label:def]"
602 (let ((org-footnote-section nil)) (org-footnote-normalize))
603 (buffer-string))))
604 (should
605 (equal
606 "Test[fn:1]\n\n[fn:1] def\n"
607 (org-test-with-temp-text "Test[fn::def]"
608 (let ((org-footnote-section nil)) (org-footnote-normalize))
609 (buffer-string))))
610 ;; Normalization includes sorting.
611 (should
612 (equal
613 "Test[fn:1][fn:2]\n\n[fn:1] def2\n\n[fn:2] def\n"
614 (org-test-with-temp-text "Test[fn:2][fn:1]\n\n[fn:2] def2\n[fn:1] def"
615 (let ((org-footnote-section nil)) (org-footnote-normalize))
616 (buffer-string))))
617 (should
618 (equal
619 "Test[fn:1][fn:2]\n\n[fn:1] def\n\n[fn:2] inline\n"
620 (org-test-with-temp-text "Test[fn:2][fn::inline]\n[fn:2] def\n"
621 (let ((org-footnote-section nil)) (org-footnote-normalize))
622 (buffer-string))))
623 (should
624 (equal
625 "Test[fn:1][fn:3]
627 \[fn:1] def[fn:2]
629 \[fn:2] inline
631 \[fn:3] last
633 (org-test-with-temp-text
634 "Test[fn:lab1][fn:lab2]\n[fn:lab1] def[fn::inline]\n[fn:lab2] last"
635 (let ((org-footnote-section nil)) (org-footnote-normalize))
636 (buffer-string))))
637 ;; When normalizing an inline reference, fill paragraph whenever the
638 ;; `org-footnote-fill-after-inline-note-extraction' is non-nil.
639 (should
640 (equal
641 "Test[fn:1] Next\n\n[fn:1] def\n"
642 (org-test-with-temp-text "Test[fn::def]\nNext"
643 (let ((org-footnote-section nil)
644 (org-footnote-fill-after-inline-note-extraction t))
645 (org-footnote-normalize))
646 (buffer-string))))
647 ;; Insert un-referenced definitions at the end.
648 (should
649 (equal
650 "Test[fn:1]\nNext\n\n[fn:1] def\n\n[fn:2] A\n"
651 (org-test-with-temp-text "Test[fn::def]\nNext\n[fn:unref] A"
652 (let ((org-footnote-section nil)) (org-footnote-normalize))
653 (buffer-string))))
654 ;; Preserve file local variables when normalizing.
655 (should
656 (equal "
657 Paragraph[fn:1][fn:2]
659 \[fn:1] Def 1
661 \[fn:2] Def 2
663 # Local Variables:
664 # foo: t
665 # End:"
666 (org-test-with-temp-text
668 Paragraph[fn:foo][fn:bar]
670 \[fn:bar] Def 2
672 \[fn:foo] Def 1
674 # Local Variables:
675 # foo: t
676 # End:"
677 (let ((org-footnote-section nil)) (org-footnote-normalize))
678 (buffer-string)))))
681 (provide 'test-org-footnote)
682 ;;; test-org-footnote.el ends here