test-ol.el 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. ;;; test-ol.el --- Tests for Org Links library -*- lexical-binding: t; -*-
  2. ;; Copyright (C) 2019 Nicolas Goaziou
  3. ;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
  4. ;; This program is free software; you can redistribute it and/or modify
  5. ;; it under the terms of the GNU General Public License as published by
  6. ;; the Free Software Foundation, either version 3 of the License, or
  7. ;; (at your option) any later version.
  8. ;; This program is distributed in the hope that it will be useful,
  9. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. ;; GNU General Public License for more details.
  12. ;; You should have received a copy of the GNU General Public License
  13. ;; along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. ;;; Code:
  15. ;;; Decode and Encode Links
  16. (ert-deftest test-ol/encode ()
  17. "Test `org-link-encode' specifications."
  18. ;; Regural test.
  19. (should (string= "Foo%3A%42ar" (org-link-encode "Foo:Bar" '(?\: ?\B))))
  20. ;; Encode an ASCII character.
  21. (should (string= "%5B" (org-link-encode "[" '(?\[))))
  22. ;; Encode an ASCII control character.
  23. (should (string= "%09" (org-link-encode "\t" '(9))))
  24. ;; Encode a Unicode multibyte character.
  25. (should (string= "%E2%82%AC" (org-link-encode "€" '(?\€)))))
  26. (ert-deftest test-ol/decode ()
  27. "Test `org-link-decode' specifications."
  28. ;; Decode an ASCII character.
  29. (should (string= "[" (org-link-decode "%5B")))
  30. ;; Decode an ASCII control character.
  31. (should (string= "\n" (org-link-decode "%0A")))
  32. ;; Decode a Unicode multibyte character.
  33. (should (string= "€" (org-link-decode "%E2%82%AC"))))
  34. (ert-deftest test-ol/encode-url-with-escaped-char ()
  35. "Encode and decode a URL that includes an encoded char."
  36. (should
  37. (string= "http://some.host.com/form?&id=blah%2Bblah25"
  38. (org-link-decode
  39. (org-link-encode "http://some.host.com/form?&id=blah%2Bblah25"
  40. '(?\s ?\[ ?\] ?%))))))
  41. ;;; Escape and Unescape Links
  42. (ert-deftest test-ol/escape ()
  43. "Test `org-link-escape' specifications."
  44. ;; No-op when there is no backslash or closing square bracket.
  45. (should (string= "foo[" (org-link-escape "foo[")))
  46. ;; Escape closing square bracket at the end of the link.
  47. (should (string= "[foo\\]" (org-link-escape "[foo]")))
  48. ;; Escape closing square brackets followed by another square
  49. ;; bracket.
  50. (should (string= "foo\\][bar" (org-link-escape "foo][bar")))
  51. (should (string= "foo\\]]bar" (org-link-escape "foo]]bar")))
  52. ;; However, escaping closing square bracket at the end of the link
  53. ;; has precedence over the previous rule.
  54. (should (string= "foo]\\]" (org-link-escape "foo]]")))
  55. ;; Escape backslashes at the end of the link.
  56. (should (string= "foo\\\\" (org-link-escape "foo\\")))
  57. ;; Escape backslashes that could be confused with escaping
  58. ;; characters.
  59. (should (string= "foo\\\\\\]" (org-link-escape "foo\\]")))
  60. (should (string= "foo\\\\\\][" (org-link-escape "foo\\][")))
  61. (should (string= "foo\\\\\\]]bar" (org-link-escape "foo\\]]bar")))
  62. ;; Do not escape backslash characters when unnecessary.
  63. (should (string= "foo\\bar" (org-link-escape "foo\\bar")))
  64. (should (string= "foo\\]bar" (org-link-escape "foo\\]bar")))
  65. ;; Pathological cases: consecutive closing square brackets.
  66. (should (string= "[[[foo\\]]\\]" (org-link-escape "[[[foo]]]")))
  67. (should (string= "[[[foo]\\]] bar" (org-link-escape "[[[foo]]] bar"))))
  68. (ert-deftest test-ol/unescape ()
  69. "Test `org-link-unescape' specifications."
  70. ;; No-op if there is no backslash.
  71. (should (string= "foo[" (org-link-unescape "foo[")))
  72. ;; No-op if backslashes are not escaping backslashes.
  73. (should (string= "foo\\bar" (org-link-unescape "foo\\bar")))
  74. (should (string= "foo\\]bar" (org-link-unescape "foo\\]bar")))
  75. ;;
  76. (should (string= "foo\\]" (org-link-unescape "foo\\\\\\]")))
  77. (should (string= "foo\\][" (org-link-unescape "foo\\\\\\][")))
  78. (should (string= "foo\\]]bar" (org-link-unescape "foo\\\\\\]]bar")))
  79. ;; Unescape backslashes at the end of the link.
  80. (should (string= "foo\\" (org-link-unescape "foo\\\\")))
  81. ;; Unescape closing square bracket at the end of the link.
  82. (should (string= "[foo]" (org-link-unescape "[foo\\]")))
  83. ;; Pathological cases: consecutive closing square brackets.
  84. (should (string= "[[[foo]]]" (org-link-unescape "[[[foo\\]]\\]")))
  85. (should (string= "[[[foo]]] bar" (org-link-unescape "[[[foo]\\]] bar"))))
  86. (ert-deftest test-ol/make-string ()
  87. "Test `org-link-make-string' specifications."
  88. ;; Throw an error on empty URI.
  89. (should-error (org-link-make-string ""))
  90. ;; Empty description returns a [[URI]] construct.
  91. (should (string= "[[uri]]"(org-link-make-string "uri")))
  92. ;; Non-empty description returns a [[URI][DESCRIPTION]] construct.
  93. (should
  94. (string= "[[uri][description]]"
  95. (org-link-make-string "uri" "description")))
  96. ;; Escape "]]" strings in the description with zero-width spaces.
  97. (should
  98. (let ((zws (string ?\x200B)))
  99. (string= (format "[[uri][foo]%s]bar]]" zws)
  100. (org-link-make-string "uri" "foo]]bar"))))
  101. ;; Prevent description from ending with a closing square bracket
  102. ;; with a zero-width space.
  103. (should
  104. (let ((zws (string ?\x200B)))
  105. (string= (format "[[uri][foo]%s]]" zws)
  106. (org-link-make-string "uri" "foo]")))))
  107. ;;; Store links
  108. (ert-deftest test-ol/store-link ()
  109. "Test `org-store-link' specifications."
  110. ;; On a headline, link to that headline. Use heading as the
  111. ;; description of the link.
  112. (should
  113. (let (org-store-link-props org-stored-links)
  114. (org-test-with-temp-text-in-file "* H1"
  115. (let ((file (buffer-file-name)))
  116. (equal (format "[[file:%s::*H1][H1]]" file)
  117. (org-store-link nil))))))
  118. ;; On a headline, remove any link from description.
  119. (should
  120. (let (org-store-link-props org-stored-links)
  121. (org-test-with-temp-text-in-file "* [[#l][d]]"
  122. (let ((file (buffer-file-name)))
  123. (equal (format "[[file:%s::*%s][d]]"
  124. file
  125. (org-link-escape "[[#l][d]]"))
  126. (org-store-link nil))))))
  127. (should
  128. (let (org-store-link-props org-stored-links)
  129. (org-test-with-temp-text-in-file "* [[l]]"
  130. (let ((file (buffer-file-name)))
  131. (equal (format "[[file:%s::*%s][l]]" file (org-link-escape "[[l]]"))
  132. (org-store-link nil))))))
  133. (should
  134. (let (org-store-link-props org-stored-links)
  135. (org-test-with-temp-text-in-file "* [[l1][d1]] [[l2][d2]]"
  136. (let ((file (buffer-file-name)))
  137. (equal (format "[[file:%s::*%s][d1 d2]]"
  138. file
  139. (org-link-escape "[[l1][d1]] [[l2][d2]]"))
  140. (org-store-link nil))))))
  141. ;; On a named element, link to that element.
  142. (should
  143. (let (org-store-link-props org-stored-links)
  144. (org-test-with-temp-text-in-file "#+NAME: foo\nParagraph"
  145. (let ((file (buffer-file-name)))
  146. (equal (format "[[file:%s::foo][foo]]" file)
  147. (org-store-link nil))))))
  148. ;; Store link to Org buffer, with context.
  149. (should
  150. (let ((org-stored-links nil)
  151. (org-id-link-to-org-use-id nil)
  152. (org-context-in-file-links t))
  153. (org-test-with-temp-text-in-file "* h1"
  154. (let ((file (buffer-file-name)))
  155. (equal (format "[[file:%s::*h1][h1]]" file)
  156. (org-store-link nil))))))
  157. ;; Store link to Org buffer, without context.
  158. (should
  159. (let ((org-stored-links nil)
  160. (org-id-link-to-org-use-id nil)
  161. (org-context-in-file-links nil))
  162. (org-test-with-temp-text-in-file "* h1"
  163. (let ((file (buffer-file-name)))
  164. (equal (format "[[file:%s][file:%s]]" file file)
  165. (org-store-link nil))))))
  166. ;; C-u prefix reverses `org-context-in-file-links' in Org buffer.
  167. (should
  168. (let ((org-stored-links nil)
  169. (org-id-link-to-org-use-id nil)
  170. (org-context-in-file-links nil))
  171. (org-test-with-temp-text-in-file "* h1"
  172. (let ((file (buffer-file-name)))
  173. (equal (format "[[file:%s::*h1][h1]]" file)
  174. (org-store-link '(4)))))))
  175. ;; A C-u C-u does *not* reverse `org-context-in-file-links' in Org
  176. ;; buffer.
  177. (should
  178. (let ((org-stored-links nil)
  179. (org-id-link-to-org-use-id nil)
  180. (org-context-in-file-links nil))
  181. (org-test-with-temp-text-in-file "* h1"
  182. (let ((file (buffer-file-name)))
  183. (equal (format "[[file:%s][file:%s]]" file file)
  184. (org-store-link '(16)))))))
  185. ;; Store file link to non-Org buffer, with context.
  186. (should
  187. (let ((org-stored-links nil)
  188. (org-context-in-file-links t))
  189. (org-test-with-temp-text-in-file "one\n<point>two"
  190. (fundamental-mode)
  191. (let ((file (buffer-file-name)))
  192. (equal (format "[[file:%s::one]]" file)
  193. (org-store-link nil))))))
  194. ;; Store file link to non-Org buffer, without context.
  195. (should
  196. (let ((org-stored-links nil)
  197. (org-context-in-file-links nil))
  198. (org-test-with-temp-text-in-file "one\n<point>two"
  199. (fundamental-mode)
  200. (let ((file (buffer-file-name)))
  201. (equal (format "[[file:%s][file:%s]]" file file)
  202. (org-store-link nil))))))
  203. ;; C-u prefix reverses `org-context-in-file-links' in non-Org
  204. ;; buffer.
  205. (should
  206. (let ((org-stored-links nil)
  207. (org-context-in-file-links nil))
  208. (org-test-with-temp-text-in-file "one\n<point>two"
  209. (fundamental-mode)
  210. (let ((file (buffer-file-name)))
  211. (equal (format "[[file:%s::one]]" file)
  212. (org-store-link '(4)))))))
  213. ;; A C-u C-u does *not* reverse `org-context-in-file-links' in
  214. ;; non-Org buffer.
  215. (should
  216. (let ((org-stored-links nil)
  217. (org-context-in-file-links nil))
  218. (org-test-with-temp-text-in-file "one\n<point>two"
  219. (fundamental-mode)
  220. (let ((file (buffer-file-name)))
  221. (equal (format "[[file:%s][file:%s]]" file file)
  222. (org-store-link '(16))))))))
  223. ;;; Radio Targets
  224. (ert-deftest test-ol/update-radio-target-regexp ()
  225. "Test `org-update-radio-target-regexp' specifications."
  226. ;; Properly update cache with no previous radio target regexp.
  227. (should
  228. (eq 'link
  229. (org-test-with-temp-text "radio\n\nParagraph\n\nradio"
  230. (save-excursion (goto-char (point-max)) (org-element-context))
  231. (insert "<<<")
  232. (search-forward "o")
  233. (insert ">>>")
  234. (org-update-radio-target-regexp)
  235. (goto-char (point-max))
  236. (org-element-type (org-element-context)))))
  237. ;; Properly update cache with previous radio target regexp.
  238. (should
  239. (eq 'link
  240. (org-test-with-temp-text "radio\n\nParagraph\n\nradio"
  241. (save-excursion (goto-char (point-max)) (org-element-context))
  242. (insert "<<<")
  243. (search-forward "o")
  244. (insert ">>>")
  245. (org-update-radio-target-regexp)
  246. (search-backward "r")
  247. (delete-char 5)
  248. (insert "new")
  249. (org-update-radio-target-regexp)
  250. (goto-char (point-max))
  251. (delete-region (line-beginning-position) (point))
  252. (insert "new")
  253. (org-element-type (org-element-context))))))
  254. ;;; Navigation
  255. (ert-deftest test-ol/next-link ()
  256. "Test `org-next-link' specifications."
  257. ;; Move to any type of link.
  258. (should
  259. (equal "[[link]]"
  260. (org-test-with-temp-text "foo [[link]]"
  261. (org-next-link)
  262. (buffer-substring (point) (line-end-position)))))
  263. (should
  264. (equal "http://link"
  265. (org-test-with-temp-text "foo http://link"
  266. (org-next-link)
  267. (buffer-substring (point) (line-end-position)))))
  268. (should
  269. (equal "<http://link>"
  270. (org-test-with-temp-text "foo <http://link>"
  271. (org-next-link)
  272. (buffer-substring (point) (line-end-position)))))
  273. ;; Ignore link at point.
  274. (should
  275. (equal "[[link2]]"
  276. (org-test-with-temp-text "[[link1]] [[link2]]"
  277. (org-next-link)
  278. (buffer-substring (point) (line-end-position)))))
  279. ;; Ignore fake links.
  280. (should
  281. (equal "[[truelink]]"
  282. (org-test-with-temp-text "foo\n: [[link]]\n[[truelink]]"
  283. (org-next-link)
  284. (buffer-substring (point) (line-end-position)))))
  285. ;; Do not move point when there is no link.
  286. (should
  287. (org-test-with-temp-text "foo bar"
  288. (org-next-link)
  289. (bobp)))
  290. ;; Wrap around after a failed search.
  291. (should
  292. (equal "[[link]]"
  293. (org-test-with-temp-text "[[link]]\n<point>foo"
  294. (org-next-link)
  295. (let* ((this-command 'org-next-link)
  296. (last-command this-command))
  297. (org-next-link))
  298. (buffer-substring (point) (line-end-position)))))
  299. ;; Find links with item tags.
  300. (should
  301. (equal "[[link1]]"
  302. (org-test-with-temp-text "- tag [[link1]] :: description"
  303. (org-next-link)
  304. (buffer-substring (point) (search-forward "]]" nil t))))))
  305. (ert-deftest test-ol/previous-link ()
  306. "Test `org-previous-link' specifications."
  307. ;; Move to any type of link.
  308. (should
  309. (equal "[[link]]"
  310. (org-test-with-temp-text "[[link]]\nfoo<point>"
  311. (org-previous-link)
  312. (buffer-substring (point) (line-end-position)))))
  313. (should
  314. (equal "http://link"
  315. (org-test-with-temp-text "http://link\nfoo<point>"
  316. (org-previous-link)
  317. (buffer-substring (point) (line-end-position)))))
  318. (should
  319. (equal "<http://link>"
  320. (org-test-with-temp-text "<http://link>\nfoo<point>"
  321. (org-previous-link)
  322. (buffer-substring (point) (line-end-position)))))
  323. ;; Ignore link at point.
  324. (should
  325. (equal "[[link1]]"
  326. (org-test-with-temp-text "[[link1]]\n[[link2<point>]]"
  327. (org-previous-link)
  328. (buffer-substring (point) (line-end-position)))))
  329. ;; Ignore fake links.
  330. (should
  331. (equal "[[truelink]]"
  332. (org-test-with-temp-text "[[truelink]]\n: [[link]]\n<point>"
  333. (org-previous-link)
  334. (buffer-substring (point) (line-end-position)))))
  335. ;; Do not move point when there is no link.
  336. (should
  337. (org-test-with-temp-text "foo bar<point>"
  338. (org-previous-link)
  339. (eobp)))
  340. ;; Wrap around after a failed search.
  341. (should
  342. (equal "[[link]]"
  343. (org-test-with-temp-text "foo\n[[link]]"
  344. (org-previous-link)
  345. (let* ((this-command 'org-previous-link)
  346. (last-command this-command))
  347. (org-previous-link))
  348. (buffer-substring (point) (line-end-position))))))
  349. (provide 'test-ol)
  350. ;;; test-ol.el ends here