org-footnote: Fix 5954f6aa25b51a3a9a8f258fb0f15ef51be31366
[org-mode.git] / testing / lisp / test-org-footnote.el
blob4e43fe1f781f929fd4652889f5623fa077e77621
1 ;;; test-org-footnote.el --- Tests for org-footnote.el
3 ;; Copyright (C) 2012-2015 Nicolas Goaziou
5 ;; Author: Nicolas Goaziou <n.goaziou at gmail dot com>
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 `plain'.
34 (should
35 (string-match-p
36 "Test\\[1\\]\n+\\[1\\]"
37 (org-test-with-temp-text "Test<point>"
38 (let ((org-footnote-auto-label 'plain)
39 (org-footnote-section nil))
40 (org-footnote-new))
41 (buffer-string))))
42 ;; `org-footnote-auto-label' is `random'.
43 (should
44 (string-match-p
45 "Test\\[fn:\\(.+?\\)\\]\n+\\[fn:\\1\\]"
46 (org-test-with-temp-text "Test<point>"
47 (let ((org-footnote-auto-label 'random)
48 (org-footnote-section nil))
49 (org-footnote-new))
50 (buffer-string))))
51 ;; Error at beginning of line.
52 (should-error
53 (org-test-with-temp-text "<point>Test"
54 (org-footnote-new)))
55 ;; Error at keywords.
56 (should-error
57 (org-test-with-temp-text "#+TIT<point>LE: value"
58 (org-footnote-new)))
59 (should-error
60 (org-test-with-temp-text "#+CAPTION: <point>\nParagraph"
61 (org-footnote-new)))
62 ;; Allow new footnotes in blank lines at the beginning of the
63 ;; document.
64 (should
65 (string-match-p
66 " \\[fn:1\\]"
67 (org-test-with-temp-text " <point>"
68 (let ((org-footnote-auto-label t)) (org-footnote-new))
69 (buffer-string))))
70 ;; In an headline or inlinetask, point must be either on the
71 ;; heading itself or on the blank lines below.
72 (should (org-test-with-temp-text "* H<point>" (org-footnote-new) t))
73 (should
74 (org-test-with-temp-text "* H\n <point>\nParagraph" (org-footnote-new) t))
75 (should-error (org-test-with-temp-text "*<point> H" (org-footnote-new) t))
76 (should-error
77 (org-test-with-temp-text "* H <point>:tag:" (org-footnote-new) t))
78 ;; Allow new footnotes within recursive objects, but not in links.
79 (should
80 (string-match-p
81 " \\*bold\\[fn:1\\]\\*"
82 (org-test-with-temp-text " *bold<point>*"
83 (let ((org-footnote-auto-label t)) (org-footnote-new))
84 (buffer-string))))
85 (should-error
86 (org-test-with-temp-text " [[http://orgmode.org][Org mode<point>]]"
87 (org-footnote-new)))
88 ;; Allow new footnotes in blank lines after an element or white
89 ;; spaces after an object.
90 (should
91 (string-match-p
92 " \\[fn:1\\]"
93 (org-test-with-temp-text "#+BEGIN_EXAMPLE\nA\n#+END_EXAMPLE\n <point>"
94 (let ((org-footnote-auto-label t)) (org-footnote-new))
95 (buffer-string))))
96 (should
97 (string-match-p
98 " \\*bold\\*\\[fn:1\\]"
99 (org-test-with-temp-text " *bold*<point>"
100 (let ((org-footnote-auto-label t)) (org-footnote-new))
101 (buffer-string)))))
103 (ert-deftest test-org-footnote/delete ()
104 "Test `org-footnote-delete' specifications."
105 ;; Regular test.
106 (should
107 (equal "Paragraph"
108 (org-test-with-temp-text "Paragraph[1]\n\n[1] Definition"
109 (search-forward "[")
110 (org-footnote-delete)
111 (org-trim (buffer-string)))))
112 ;; Remove multiple definitions and references.
113 (should
114 (equal "Paragraph and another"
115 (org-test-with-temp-text
116 "Paragraph[1] and another[1]\n\n[1] def\n\n[1] def"
117 (search-forward "[")
118 (org-footnote-delete)
119 (org-trim (buffer-string)))))
120 ;; Delete inline footnotes and all references.
121 (should
122 (equal "Para and"
123 (org-test-with-temp-text "Para[fn:label:def] and[fn:label]"
124 (search-forward "[")
125 (org-footnote-delete)
126 (org-trim (buffer-string)))))
127 ;; Delete anonymous footnotes.
128 (should
129 (equal "Para"
130 (org-test-with-temp-text "Para[fn::def]"
131 (search-forward "[")
132 (org-footnote-delete)
133 (org-trim (buffer-string)))))
134 ;; With an argument, delete footnote with specified label.
135 (should
136 (equal "Paragraph[1] and another\n\n[1] def"
137 (let ((org-footnote-section nil))
138 (org-test-with-temp-text
139 "Paragraph[1] and another[2]\n\n[1] def\n\n[2] def2"
140 (org-footnote-delete "2")
141 (org-trim (buffer-string))))))
142 ;; Error when no argument is specified at point is not at a footnote
143 ;; reference.
144 (should-error
145 (org-test-with-temp-text "Para[1]\n\n[1] Def"
146 (org-footnote-delete)))
147 ;; Correctly delete footnotes with multiple paragraphs.
148 (should
149 (equal "Para\n\n\nOutside footnote."
150 (org-test-with-temp-text
151 "Para[1]\n\n[1] para1\n\npara2\n\n\nOutside footnote."
152 (org-footnote-delete "1")
153 (org-trim (buffer-string))))))
155 (ert-deftest test-org-footnote/goto-definition ()
156 "Test `org-footnote-goto-definition' specifications."
157 ;; Error on unknown definitions.
158 (should-error
159 (org-test-with-temp-text "No footnote definition"
160 (org-footnote-goto-definition "fn:1")))
161 ;; Error when trying to reach a definition outside narrowed part of
162 ;; buffer.
163 (should-error
164 (org-test-with-temp-text "Some text<point>\n[fn:1] Definition."
165 (narrow-to-region (point-min) (point))
166 (org-footnote-goto-definition "fn:1")))
167 (should-error
168 (org-test-with-temp-text "[fn:1] Definition.\n<point>Some text"
169 (narrow-to-region (point) (point-max))
170 (org-footnote-goto-definition "fn:1")))
171 ;; Otherwise, move at the beginning of the definition, including
172 ;; anonymous footnotes.
173 (should
174 (equal
175 " Definition."
176 (org-test-with-temp-text "Some text\n[fn:1] Definition."
177 (org-footnote-goto-definition "fn:1")
178 (buffer-substring (point) (point-max)))))
179 (should
180 (equal
181 "definition]"
182 (org-test-with-temp-text "Some text[fn:label:definition]"
183 (org-footnote-goto-definition "fn:label")
184 (buffer-substring (point) (point-max))))))
186 (ert-deftest test-org-footnote/normalize-in-org ()
187 "Test specifications for `org-footnote-normalize' in an Org buffer."
188 ;; 1. With a non-nil `org-footnote-section'.
189 (let ((org-footnote-section "Footnotes")
190 (org-blank-before-new-entry '((heading . auto))))
191 ;; 1.1. Normalize each type of footnote: standard, labelled,
192 ;; numbered, inline, anonymous.
193 (org-test-with-temp-text
194 "Paragraph[fn:1][fn:label][1][fn:inline:Inline][fn::Anonymous]
196 * Footnotes
198 \[fn:1] Standard
200 \[fn:label] Labelled
202 \[1] Numbered"
203 (org-footnote-normalize)
204 (should
205 (equal (buffer-string)
206 "Paragraph[1][2][3][4][5]
208 * Footnotes
210 \[1] Standard
212 \[2] Labelled
214 \[3] Numbered
216 \[4] Inline
218 \[5] Anonymous
221 ")))
222 ;; 1.2. When no footnote section is present, create it. Follow
223 ;; `org-blank-before-new-entry' specifications when doing so.
224 (org-test-with-temp-text "Paragraph[fn:1]\n\n[fn:1] Definition"
225 (org-footnote-normalize)
226 (should (equal (buffer-string)
227 "Paragraph[1]\n\n* Footnotes\n\n[1] Definition")))
228 (org-test-with-temp-text "Paragraph[fn:1]\n* Head1\n[fn:1] Definition"
229 (let ((org-blank-before-new-entry '((heading))))
230 (org-footnote-normalize))
231 (should (equal (buffer-string)
232 "Paragraph[1]\n* Head1\n* Footnotes\n\n[1] Definition")))
233 ;; 1.3. When the footnote section is misplaced, move it at the end
234 ;; of the buffer.
235 (org-test-with-temp-text "* Head1
236 Body[fn:1]
237 * Footnotes
238 \[fn:1] Definition 1
239 * Head2"
240 (org-footnote-normalize)
241 (should
242 (equal (buffer-string)
243 "* Head1
244 Body[1]
245 * Head2
247 * Footnotes
249 \[1] Definition 1"))))
250 ;; 2. With a nil `org-footnote-section'.
251 (let ((org-footnote-section nil))
252 ;; 2.1. Normalize each type of footnote: standard, labelled,
253 ;; numbered, inline, anonymous.
254 (org-test-with-temp-text
255 "Paragraph[fn:1][fn:label][1][fn:inline:Inline][fn::Anonymous]
257 \[fn:1] Standard
259 \[fn:label] Labelled
261 \[1] Numbered"
262 (org-footnote-normalize)
263 (should
264 (equal (buffer-string)
265 "Paragraph[1][2][3][4][5]
267 \[1] Standard
269 \[2] Labelled
271 \[3] Numbered
273 \[4] Inline
275 \[5] Anonymous
276 ")))
277 ;; 2.2. Put each footnote definition at the end of the section
278 ;; containing its first reference.
279 (org-test-with-temp-text
280 "* Head 1
281 Text[fn:1:Def1]
282 * Head 2
283 Text[fn:1]
284 * Head 3
285 Text[fn:2:Def2]"
286 (org-footnote-normalize)
287 (should
288 (equal (buffer-string)
289 "* Head 1
290 Text[1]
292 \[1] Def1
293 * Head 2
294 Text[1]
295 * Head 3
296 Text[2]
298 \[2] Def2
299 ")))))
301 (ert-deftest test-org-footnote/normalize-outside-org ()
302 "Test `org-footnote-normalize' specifications for buffers not in Org mode."
303 ;; 1. In a non-Org buffer, footnotes definitions are always put at
304 ;; its end.
305 (should
306 (equal
307 "Paragraph[1][2][3][4][5]
310 Some additional text.
312 \[1] Standard
314 \[2] Labelled
316 \[3] Numbered
318 \[4] Inline
320 \[5] Anonymous"
321 (let ((org-footnote-tag-for-non-org-mode-files nil))
322 (with-temp-buffer
323 (insert "Paragraph[fn:1][fn:label][1][fn:inline:Inline][fn::Anonymous]
325 \[fn:1] Standard
327 \[fn:label] Labelled
329 \[1] Numbered
332 Some additional text.")
333 (org-footnote-normalize)
334 (buffer-string)))))
335 ;; 2. With a special tag.
336 (let ((org-footnote-tag-for-non-org-mode-files "Footnotes:"))
337 ;; 2.1. The tag must be inserted before the footnotes, separated
338 ;; from the rest of the text with a blank line.
339 (with-temp-buffer
340 (insert "Paragraph[fn:1][fn::Anonymous]
342 \[fn:1] Standard
345 Some additional text.")
346 (org-footnote-normalize)
347 (should
348 (equal (buffer-string)
349 "Paragraph[1][2]
352 Some additional text.
354 Footnotes:
356 \[1] Standard
358 \[2] Anonymous")))
359 ;; 2.2. Any tag already inserted in the buffer should be removed
360 ;; prior to footnotes insertion.
361 (with-temp-buffer
362 (insert "Text[fn:1]
363 Footnotes:
365 Additional text.
367 Footnotes:
369 \[fn:1] Definition")
370 (org-footnote-normalize)
371 (should
372 (equal (buffer-string)
373 "Text[1]
375 Additional text.
377 Footnotes:
379 \[1] Definition"))))
380 ;; 3. As an exception, in `message-mode' buffer, if a signature is
381 ;; present, insert footnotes before it.n
382 (let ((org-footnote-tag-for-non-org-mode-files nil))
383 (with-temp-buffer
384 (insert "Body[fn::def]
386 Fake signature
388 Signature")
389 ;; Mimic `message-mode'.
390 (let ((major-mode 'message-mode)
391 (message-cite-prefix-regexp "\\([ ]*[_.[:word:]]+>+\\|[ ]*[]>|]\\)+")
392 (message-signature-separator "^-- $"))
393 (flet ((message-point-in-header-p nil nil))
394 (org-footnote-normalize)))
395 (should
396 (equal (buffer-string)
397 "Body[1]
399 Fake signature
401 \[1] def
404 Signature")))))
406 (ert-deftest test-org-footnote/sort ()
407 "Test footnotes definitions sorting."
408 (let ((org-footnote-section nil))
409 (org-test-with-temp-text
410 "Text[fn:1][fn::inline][fn:2][fn:label]
412 \[fn:label] C
414 \[fn:1] A
416 \[fn:2] B"
417 (org-footnote-normalize 'sort)
418 (should
419 (equal (buffer-string)
420 "Text[fn:1][fn::inline][fn:2][fn:label]
422 \[fn:1] A
424 \[fn:2] B
426 \[fn:label] C
427 ")))))
430 (provide 'test-org-footnote)
431 ;;; test-org-footnote.el ends here