Tiny refactoring
[org-mode.git] / testing / lisp / test-org-footnote.el
blob253f4ee544797d5b224b4fcb13adc27866ac18af
1 ;;; test-org-footnote.el --- Tests for org-footnote.el
3 ;; Copyright (C) 2012-2015 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 " [[http://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))))))
117 (ert-deftest test-org-footnote/delete ()
118 "Test `org-footnote-delete' specifications."
119 ;; Regular test.
120 (should
121 (equal "Paragraph"
122 (org-test-with-temp-text "Paragraph<point>[fn:1]\n\n[fn:1] Definition"
123 (org-footnote-delete)
124 (org-trim (buffer-string)))))
125 ;; Remove multiple definitions and references.
126 (should
127 (equal "Paragraph and another"
128 (org-test-with-temp-text
129 "Paragraph<point>[fn:1] and another[fn:1]
131 \[fn:1] def
133 \[fn:1] def"
134 (org-footnote-delete)
135 (org-trim (buffer-string)))))
136 ;; Delete inline footnotes and all references.
137 (should
138 (equal "Para and"
139 (org-test-with-temp-text "Para<point>[fn:label:def] and[fn:label]"
140 (org-footnote-delete)
141 (org-trim (buffer-string)))))
142 ;; Delete anonymous footnotes.
143 (should
144 (equal "Para"
145 (let ((org-footnote-section nil))
146 (org-test-with-temp-text "Para<point>[fn::def]"
147 (org-footnote-delete)
148 (org-trim (buffer-string))))))
149 ;; With an argument, delete footnote with specified label.
150 (should
151 (equal "Paragraph[fn:1] and another\n\n[fn:1] def"
152 (let ((org-footnote-section nil))
153 (org-test-with-temp-text
154 "Paragraph[fn:1] and another[fn:2]\n\n[fn:1] def\n\n[fn:2] def2"
155 (org-footnote-delete "2")
156 (org-trim (buffer-string))))))
157 ;; Error when no argument is specified at point is not at a footnote
158 ;; reference.
159 (should-error
160 (org-test-with-temp-text "Para[fn:1]\n\n[fn:1] Def"
161 (org-footnote-delete)))
162 ;; Correctly delete footnotes with multiple paragraphs.
163 (should
164 (equal "Para\n\n\nOutside footnote."
165 (let ((org-footnote-section nil))
166 (org-test-with-temp-text
167 "Para[fn:1]\n\n[fn:1] para1\n\npara2\n\n\nOutside footnote."
168 (org-footnote-delete "1")
169 (org-trim (buffer-string)))))))
171 (ert-deftest test-org-footnote/goto-definition ()
172 "Test `org-footnote-goto-definition' specifications."
173 ;; Error on unknown definitions.
174 (should-error
175 (org-test-with-temp-text "No footnote definition"
176 (org-footnote-goto-definition "1")))
177 ;; Error when trying to reach a definition outside narrowed part of
178 ;; buffer.
179 (should-error
180 (org-test-with-temp-text "Some text<point>\n[fn:1] Definition."
181 (narrow-to-region (point-min) (point))
182 (org-footnote-goto-definition "1")))
183 (should-error
184 (org-test-with-temp-text "[fn:1] Definition.\n<point>Some text"
185 (narrow-to-region (point) (point-max))
186 (org-footnote-goto-definition "1")))
187 ;; Otherwise, move at the beginning of the definition, including
188 ;; anonymous footnotes.
189 (should
190 (equal
191 "Definition."
192 (org-test-with-temp-text "Some text\n[fn:1] Definition."
193 (org-footnote-goto-definition "1")
194 (buffer-substring (point) (point-max)))))
195 (should
196 (equal
197 "definition]"
198 (org-test-with-temp-text "Some text[fn:label:definition]"
199 (org-footnote-goto-definition "label")
200 (buffer-substring (point) (point-max))))))
202 (ert-deftest test-org-footnote/sort ()
203 "Test `org-footnote-sort' specifications."
204 ;; Reorder definitions with a nil `org-footnote-section'. In this
205 ;; case each definition is written at the end of the section
206 ;; containing its first reference.
207 (should
208 (equal
210 Text[fn:1][fn:2]
212 \[fn:1] Def 1
214 \[fn:2] Def 2
216 (org-test-with-temp-text "
217 Text[fn:1][fn:2]
219 \[fn:2] Def 2
221 \[fn:1] Def 1"
222 (let ((org-footnote-section nil)) (org-footnote-sort))
223 (buffer-string))))
224 (should
225 (equal
227 * H1
228 Text[fn:1]
230 \[fn:1] Def 1
231 * H2
232 Text[fn:2]
234 \[fn:2] Def 2
236 (org-test-with-temp-text "
237 * H1
238 Text[fn:1]
239 * H2
240 Text[fn:2]
242 \[fn:1] Def 1
244 \[fn:2] Def 2
246 (let ((org-footnote-section nil)) (org-footnote-sort))
247 (buffer-string))))
248 ;; Reorder definitions with a non-nil `org-footnote-section'.
249 (should
250 (equal
252 Text[fn:1][fn:2]
254 * Footnotes
256 \[fn:1] Def 1
258 \[fn:2] Def 2
260 (org-test-with-temp-text "
261 Text[fn:1][fn:2]
263 \[fn:2] Def 2
265 \[fn:1] Def 1"
266 (let ((org-footnote-section "Footnotes")) (org-footnote-sort))
267 (buffer-string))))
268 ;; When `org-footnote-section' is non-nil, clear previous footnote
269 ;; sections.
270 (should
271 (equal
273 Text[fn:1]
275 * Headline
277 * Other headline
279 * Footnotes
281 \[fn:1] Def 1
283 (org-test-with-temp-text "
284 Text[fn:1]
286 * Footnotes
288 \[fn:1] Def 1
290 * Headline
292 ** Footnotes
294 * Other headline"
295 (let ((org-footnote-section "Footnotes")) (org-footnote-sort))
296 (buffer-string))))
297 ;; Ignore anonymous footnotes.
298 (should
299 (equal
301 Text[fn:1][fn::inline][fn:2]
303 \[fn:1] Def 1
305 \[fn:2] Def 2
307 (org-test-with-temp-text
309 Text[fn:1][fn::inline][fn:2]
311 \[fn:2] Def 2
313 \[fn:1] Def 1"
314 (let ((org-footnote-section nil)) (org-footnote-sort))
315 (buffer-string))))
316 ;; Ignore inline footnotes.
317 (should
318 (equal
320 Text[fn:1][fn:label:inline][fn:2]
322 \[fn:1] Def 1
324 \[fn:2] Def 2
326 (org-test-with-temp-text
328 Text[fn:1][fn:label:inline][fn:2]
330 \[fn:2] Def 2
332 \[fn:1] Def 1"
333 (let ((org-footnote-section nil)) (org-footnote-sort))
334 (buffer-string))))
335 ;; Handle (deeply) nested footnotes.
336 (should
337 (equal
339 Text[fn:1][fn:3]
341 \[fn:1] Def 1[fn:2]
343 \[fn:2] Def 2
345 \[fn:3] Def 3
347 (org-test-with-temp-text "
348 Text[fn:1][fn:3]
350 \[fn:1] Def 1[fn:2]
352 \[fn:3] Def 3
354 \[fn:2] Def 2
356 (let ((org-footnote-section nil)) (org-footnote-sort))
357 (buffer-string))))
358 (should
359 (equal
361 Text[fn:1][fn:4]
363 \[fn:1] Def 1[fn:2]
365 \[fn:2] Def 2[fn:3]
367 \[fn:3] Def 3
369 \[fn:4] Def 4
371 (org-test-with-temp-text "
372 Text[fn:1][fn:4]
374 \[fn:1] Def 1[fn:2]
376 \[fn:3] Def 3
378 \[fn:2] Def 2[fn:3]
380 \[fn:4] Def 4
382 (let ((org-footnote-section nil)) (org-footnote-sort))
383 (buffer-string))))
384 ;; When multiple (nested) references are used, make sure to insert
385 ;; definition only once.
386 (should
387 (equal
389 * Section 1
391 Text[fn:1]
393 \[fn:1] Def 1
395 * Section 2
397 Text[fn:1]"
398 (org-test-with-temp-text
400 * Section 1
402 Text[fn:1]
404 \[fn:1] Def 1
406 * Section 2
408 Text[fn:1]"
409 (let ((org-footnote-section nil)) (org-footnote-sort))
410 (buffer-string))))
411 (should
412 (equal
414 Text[fn:1][fn:4]
416 \[fn:1] Def 1[fn:2][fn:3]
418 \[fn:2] Def 2[fn:3]
420 \[fn:3] Def 3
422 \[fn:4] Def 4
424 (org-test-with-temp-text "
425 Text[fn:1][fn:4]
427 \[fn:1] Def 1[fn:2][fn:3]
429 \[fn:3] Def 3
431 \[fn:2] Def 2[fn:3]
433 \[fn:4] Def 4
435 (let ((org-footnote-section nil)) (org-footnote-sort))
436 (buffer-string))))
437 ;; Insert un-referenced definitions at the end.
438 (should
439 (equal
440 "Text[fn:9]
442 \[fn:9] B
444 \[fn:1] A
446 (org-test-with-temp-text "Text[fn:9]\n\n[fn:1] A\n[fn:9] B"
447 (let ((org-footnote-section nil)) (org-footnote-sort))
448 (buffer-string)))))
450 (ert-deftest test-org-footnote/renumber-fn:N ()
451 "Test `org-footnote-renumber-fn:N' specifications."
452 ;; Renumber (inline) references and definitions.
453 (should
454 (equal
455 "Test[fn:1]"
456 (org-test-with-temp-text "Test[fn:99]"
457 (org-footnote-renumber-fn:N)
458 (buffer-string))))
459 (should
460 (equal
461 "Test[fn:1]\n\n[fn:1] 99"
462 (org-test-with-temp-text "Test[fn:99]\n\n[fn:99] 99"
463 (org-footnote-renumber-fn:N)
464 (buffer-string))))
465 (should
466 (equal
467 "Test[fn:1:99]"
468 (org-test-with-temp-text "Test[fn:99:99]"
469 (org-footnote-renumber-fn:N)
470 (buffer-string))))
471 ;; No-op if there's no numbered footnote.
472 (should
473 (equal
474 "Test[fn:label]\n\n[fn:label] Def"
475 (org-test-with-temp-text "Test[fn:label]\n\n[fn:label] Def"
476 (org-footnote-renumber-fn:N)
477 (buffer-string))))
478 ;; Definitions without a reference get the highest numbers.
479 (should
480 (equal
481 "Test[fn:1]\n[fn:1] 1\n[fn:2] 99"
482 (org-test-with-temp-text "Test[fn:1]\n[fn:1] 1\n[fn:99] 99"
483 (org-footnote-renumber-fn:N)
484 (buffer-string))))
485 ;; Sort labels in sequence. Anonymous footnotes are ignored.
486 (should
487 (equal
488 "Test[fn:1][fn:2:def][fn:3]"
489 (org-test-with-temp-text "Test[fn:4][fn:3:def][fn:2]"
490 (org-footnote-renumber-fn:N)
491 (buffer-string))))
492 (should
493 (equal
494 "Test[fn:1][fn::def][fn:2]"
495 (org-test-with-temp-text "Test[fn:4][fn::def][fn:2]"
496 (org-footnote-renumber-fn:N)
497 (buffer-string)))))
499 (ert-deftest test-org-footnote/normalize ()
500 "Test `org-footnote-normalize' specifications."
501 ;; Normalize regular, inline and anonymous references.
502 (should
503 (equal
504 "Test[fn:1]\n\n[fn:1] def\n"
505 (org-test-with-temp-text "Test[fn:label]\n[fn:label] def"
506 (let ((org-footnote-section nil)) (org-footnote-normalize))
507 (buffer-string))))
508 (should
509 (equal
510 "Test[fn:1]\n\n[fn:1] def\n"
511 (org-test-with-temp-text "Test[fn:label:def]"
512 (let ((org-footnote-section nil)) (org-footnote-normalize))
513 (buffer-string))))
514 (should
515 (equal
516 "Test[fn:1]\n\n[fn:1] def\n"
517 (org-test-with-temp-text "Test[fn::def]"
518 (let ((org-footnote-section nil)) (org-footnote-normalize))
519 (buffer-string))))
520 ;; Normalization includes sorting.
521 (should
522 (equal
523 "Test[fn:1][fn:2]\n\n[fn:1] def2\n\n[fn:2] def\n"
524 (org-test-with-temp-text "Test[fn:2][fn:1]\n\n[fn:2] def2\n[fn:1] def"
525 (let ((org-footnote-section nil)) (org-footnote-normalize))
526 (buffer-string))))
527 (should
528 (equal
529 "Test[fn:1][fn:2]\n\n[fn:1] def\n\n[fn:2] inline\n"
530 (org-test-with-temp-text "Test[fn:2][fn::inline]\n[fn:2] def\n"
531 (let ((org-footnote-section nil)) (org-footnote-normalize))
532 (buffer-string))))
533 (should
534 (equal
535 "Test[fn:1][fn:3]
537 \[fn:1] def[fn:2]
539 \[fn:2] inline
541 \[fn:3] last
543 (org-test-with-temp-text
544 "Test[fn:lab1][fn:lab2]\n[fn:lab1] def[fn::inline]\n[fn:lab2] last"
545 (let ((org-footnote-section nil)) (org-footnote-normalize))
546 (buffer-string))))
547 ;; When normalizing an inline reference, fill paragraph whenever the
548 ;; `org-footnote-fill-after-inline-note-extraction' is non-nil.
549 (should
550 (equal
551 "Test[fn:1] Next\n\n[fn:1] def\n"
552 (org-test-with-temp-text "Test[fn::def]\nNext"
553 (let ((org-footnote-section nil)
554 (org-footnote-fill-after-inline-note-extraction t))
555 (org-footnote-normalize))
556 (buffer-string))))
557 ;; Insert un-referenced definitions at the end.
558 (should
559 (equal
560 "Test[fn:1]\nNext\n\n[fn:1] def\n\n[fn:2] A\n"
561 (org-test-with-temp-text "Test[fn::def]\nNext\n[fn:unref] A"
562 (let ((org-footnote-section nil)) (org-footnote-normalize))
563 (buffer-string)))))
566 (provide 'test-org-footnote)
567 ;;; test-org-footnote.el ends here