test-ol.el 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725
  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. (require 'cl-lib)
  16. (require 'ol)
  17. (require 'org-id)
  18. ;;; Decode and Encode Links
  19. (ert-deftest test-org-link/encode ()
  20. "Test `org-link-encode' specifications."
  21. ;; Regural test.
  22. (should (string= "Foo%3A%42ar" (org-link-encode "Foo:Bar" '(?\: ?\B))))
  23. ;; Encode an ASCII character.
  24. (should (string= "%5B" (org-link-encode "[" '(?\[))))
  25. ;; Encode an ASCII control character.
  26. (should (string= "%09" (org-link-encode "\t" '(9))))
  27. ;; Encode a Unicode multibyte character.
  28. (should (string= "%E2%82%AC" (org-link-encode "€" '(?\€)))))
  29. (ert-deftest test-org-link/decode ()
  30. "Test `org-link-decode' specifications."
  31. ;; Decode an ASCII character.
  32. (should (string= "[" (org-link-decode "%5B")))
  33. ;; Decode an ASCII control character.
  34. (should (string= "\n" (org-link-decode "%0A")))
  35. ;; Decode a Unicode multibyte character.
  36. (should (string= "€" (org-link-decode "%E2%82%AC"))))
  37. (ert-deftest test-org-link/encode-url-with-escaped-char ()
  38. "Encode and decode a URL that includes an encoded char."
  39. (should
  40. (string= "http://some.host.com/form?&id=blah%2Bblah25"
  41. (org-link-decode
  42. (org-link-encode "http://some.host.com/form?&id=blah%2Bblah25"
  43. '(?\s ?\[ ?\] ?%))))))
  44. (ert-deftest test-org-link/toggle-link-display ()
  45. "Make sure that `org-toggle-link-display' is working.
  46. See https://github.com/yantar92/org/issues/4."
  47. (dolist (org-link-descriptive '(nil t))
  48. (org-test-with-temp-text "* Org link test
  49. [[https://example.com][A link to a site]]"
  50. (dotimes (_ 2)
  51. (goto-char 1)
  52. (re-search-forward "\\[")
  53. (should-not (org-xor org-link-descriptive (org-invisible-p)))
  54. (re-search-forward "example")
  55. (should-not (org-xor org-link-descriptive (org-invisible-p)))
  56. (re-search-forward "com")
  57. (should-not (org-xor org-link-descriptive (org-invisible-p)))
  58. (re-search-forward "]")
  59. (should-not (org-xor org-link-descriptive (org-invisible-p)))
  60. (re-search-forward "\\[")
  61. (should-not (org-invisible-p))
  62. (re-search-forward "link")
  63. (should-not (org-invisible-p))
  64. (re-search-forward "]")
  65. (should-not (org-xor org-link-descriptive (org-invisible-p)))
  66. (org-toggle-link-display)))))
  67. ;;; Escape and Unescape Links
  68. (ert-deftest test-org-link/escape ()
  69. "Test `org-link-escape' specifications."
  70. ;; No-op when there is no backslash or square bracket.
  71. (should (string= "foo" (org-link-escape "foo")))
  72. ;; Escape square brackets at boundaries of the link.
  73. (should (string= "\\[foo\\]" (org-link-escape "[foo]")))
  74. ;; Escape square brackets followed by another square bracket.
  75. (should (string= "foo\\]\\[bar" (org-link-escape "foo][bar")))
  76. (should (string= "foo\\]\\]bar" (org-link-escape "foo]]bar")))
  77. (should (string= "foo\\[\\[bar" (org-link-escape "foo[[bar")))
  78. (should (string= "foo\\[\\]bar" (org-link-escape "foo[]bar")))
  79. ;; Escape backslashes at the end of the link.
  80. (should (string= "foo\\\\" (org-link-escape "foo\\")))
  81. ;; Escape backslashes that could be confused with escaping
  82. ;; characters.
  83. (should (string= "foo\\\\\\]" (org-link-escape "foo\\]")))
  84. (should (string= "foo\\\\\\]\\[" (org-link-escape "foo\\][")))
  85. (should (string= "foo\\\\\\]\\]bar" (org-link-escape "foo\\]]bar")))
  86. ;; Do not escape backslash characters when unnecessary.
  87. (should (string= "foo\\bar" (org-link-escape "foo\\bar")))
  88. ;; Pathological cases: consecutive closing square brackets.
  89. (should (string= "\\[\\[\\[foo\\]\\]\\]" (org-link-escape "[[[foo]]]")))
  90. (should (string= "\\[\\[foo\\]\\] bar" (org-link-escape "[[foo]] bar"))))
  91. (ert-deftest test-org-link/unescape ()
  92. "Test `org-link-unescape' specifications."
  93. ;; No-op if there is no backslash.
  94. (should (string= "foo" (org-link-unescape "foo")))
  95. ;; No-op if backslashes are not escaping backslashes.
  96. (should (string= "foo\\bar" (org-link-unescape "foo\\bar")))
  97. ;; Unescape backslashes before square brackets.
  98. (should (string= "foo]bar" (org-link-unescape "foo\\]bar")))
  99. (should (string= "foo\\]" (org-link-unescape "foo\\\\\\]")))
  100. (should (string= "foo\\][" (org-link-unescape "foo\\\\\\][")))
  101. (should (string= "foo\\]]bar" (org-link-unescape "foo\\\\\\]\\]bar")))
  102. (should (string= "foo\\[[bar" (org-link-unescape "foo\\\\\\[\\[bar")))
  103. (should (string= "foo\\[]bar" (org-link-unescape "foo\\\\\\[\\]bar")))
  104. ;; Unescape backslashes at the end of the link.
  105. (should (string= "foo\\" (org-link-unescape "foo\\\\")))
  106. ;; Unescape closing square bracket at boundaries of the link.
  107. (should (string= "[foo]" (org-link-unescape "\\[foo\\]")))
  108. ;; Pathological cases: consecutive closing square brackets.
  109. (should (string= "[[[foo]]]" (org-link-unescape "\\[\\[\\[foo\\]\\]\\]")))
  110. (should (string= "[[foo]] bar" (org-link-unescape "\\[\\[foo\\]\\] bar"))))
  111. (ert-deftest test-org-link/make-string ()
  112. "Test `org-link-make-string' specifications."
  113. ;; Throw an error on empty URI.
  114. (should-error (org-link-make-string ""))
  115. ;; Empty description returns a [[URI]] construct.
  116. (should (string= "[[uri]]"(org-link-make-string "uri")))
  117. ;; Non-empty description returns a [[URI][DESCRIPTION]] construct.
  118. (should
  119. (string= "[[uri][description]]"
  120. (org-link-make-string "uri" "description")))
  121. ;; Escape "]]" strings in the description with zero-width spaces.
  122. (should
  123. (let ((zws (string ?\x200B)))
  124. (string= (format "[[uri][foo]%s]bar]]" zws)
  125. (org-link-make-string "uri" "foo]]bar"))))
  126. ;; Prevent description from ending with a closing square bracket
  127. ;; with a zero-width space.
  128. (should
  129. (let ((zws (string ?\x200B)))
  130. (string= (format "[[uri][foo]%s]]" zws)
  131. (org-link-make-string "uri" "foo]")))))
  132. ;;; Store links
  133. (ert-deftest test-org-link/store-link ()
  134. "Test `org-store-link' specifications."
  135. (defvar org-store-link-props) ;; FIXME: Unknown var!
  136. ;; On a headline, link to that headline. Use heading as the
  137. ;; description of the link.
  138. (should
  139. (let (org-store-link-props org-stored-links)
  140. (org-test-with-temp-text-in-file "* H1"
  141. (let ((file (buffer-file-name)))
  142. (equal (format "[[file:%s::*H1][H1]]" file)
  143. (org-store-link nil))))))
  144. ;; On a headline, remove TODO and COMMENT keywords, priority cookie,
  145. ;; and tags.
  146. (should
  147. (let (org-store-link-props org-stored-links)
  148. (org-test-with-temp-text-in-file "* TODO H1"
  149. (let ((file (buffer-file-name)))
  150. (equal (format "[[file:%s::*H1][H1]]" file)
  151. (org-store-link nil))))))
  152. (should
  153. (let (org-store-link-props org-stored-links)
  154. (org-test-with-temp-text-in-file "* COMMENT H1"
  155. (let ((file (buffer-file-name)))
  156. (equal (format "[[file:%s::*H1][H1]]" file)
  157. (org-store-link nil))))))
  158. (should
  159. (let (org-store-link-props org-stored-links)
  160. (org-test-with-temp-text-in-file "* [#A] H1"
  161. (let ((file (buffer-file-name)))
  162. (equal (format "[[file:%s::*H1][H1]]" file)
  163. (org-store-link nil))))))
  164. (should
  165. (let (org-store-link-props org-stored-links)
  166. (org-test-with-temp-text-in-file "* H1 :tag:"
  167. (let ((file (buffer-file-name)))
  168. (equal (format "[[file:%s::*H1][H1]]" file)
  169. (org-store-link nil))))))
  170. ;; On a headline, remove any link from description.
  171. (should
  172. (let (org-store-link-props org-stored-links)
  173. (org-test-with-temp-text-in-file "* [[#l][d]]"
  174. (let ((file (buffer-file-name)))
  175. (equal (format "[[file:%s::*%s][d]]"
  176. file
  177. (org-link-escape "[[#l][d]]"))
  178. (org-store-link nil))))))
  179. (should
  180. (let (org-store-link-props org-stored-links)
  181. (org-test-with-temp-text-in-file "* [[l]]"
  182. (let ((file (buffer-file-name)))
  183. (equal (format "[[file:%s::*%s][l]]" file (org-link-escape "[[l]]"))
  184. (org-store-link nil))))))
  185. (should
  186. (let (org-store-link-props org-stored-links)
  187. (org-test-with-temp-text-in-file "* [[l1][d1]] [[l2][d2]]"
  188. (let ((file (buffer-file-name)))
  189. (equal (format "[[file:%s::*%s][d1 d2]]"
  190. file
  191. (org-link-escape "[[l1][d1]] [[l2][d2]]"))
  192. (org-store-link nil))))))
  193. ;; On a named element, link to that element.
  194. (should
  195. (let (org-store-link-props org-stored-links)
  196. (org-test-with-temp-text-in-file "#+NAME: foo\nParagraph"
  197. (let ((file (buffer-file-name)))
  198. (equal (format "[[file:%s::foo][foo]]" file)
  199. (org-store-link nil))))))
  200. ;; Store link to Org buffer, with context.
  201. (should
  202. (let ((org-stored-links nil)
  203. (org-id-link-to-org-use-id nil)
  204. (org-context-in-file-links t))
  205. (org-test-with-temp-text-in-file "* h1"
  206. (let ((file (buffer-file-name)))
  207. (equal (format "[[file:%s::*h1][h1]]" file)
  208. (org-store-link nil))))))
  209. ;; Store link to Org buffer, without context.
  210. (should
  211. (let ((org-stored-links nil)
  212. (org-id-link-to-org-use-id nil)
  213. (org-context-in-file-links nil))
  214. (org-test-with-temp-text-in-file "* h1"
  215. (let ((file (buffer-file-name)))
  216. (equal (format "[[file:%s]]" file file)
  217. (org-store-link nil))))))
  218. ;; C-u prefix reverses `org-context-in-file-links' in Org buffer.
  219. (should
  220. (let ((org-stored-links nil)
  221. (org-id-link-to-org-use-id nil)
  222. (org-context-in-file-links nil))
  223. (org-test-with-temp-text-in-file "* h1"
  224. (let ((file (buffer-file-name)))
  225. (equal (format "[[file:%s::*h1][h1]]" file)
  226. (org-store-link '(4)))))))
  227. ;; A C-u C-u does *not* reverse `org-context-in-file-links' in Org
  228. ;; buffer.
  229. (should
  230. (let ((org-stored-links nil)
  231. (org-id-link-to-org-use-id nil)
  232. (org-context-in-file-links nil))
  233. (org-test-with-temp-text-in-file "* h1"
  234. (let ((file (buffer-file-name)))
  235. (equal (format "[[file:%s]]" file file)
  236. (org-store-link '(16)))))))
  237. ;; Store file link to non-Org buffer, with context.
  238. (should
  239. (let ((org-stored-links nil)
  240. (org-link-context-for-files t))
  241. (org-test-with-temp-text-in-file "one\n<point>two"
  242. (fundamental-mode)
  243. (let ((file (buffer-file-name)))
  244. (equal (format "[[file:%s::two]]" file)
  245. (org-store-link nil))))))
  246. ;; Store file link to non-Org buffer, without context.
  247. (should
  248. (let ((org-stored-links nil)
  249. (org-context-in-file-links nil))
  250. (org-test-with-temp-text-in-file "one\n<point>two"
  251. (fundamental-mode)
  252. (let ((file (buffer-file-name)))
  253. (equal (format "[[file:%s]]" file file)
  254. (org-store-link nil))))))
  255. ;; C-u prefix reverses `org-context-in-file-links' in non-Org
  256. ;; buffer.
  257. (should
  258. (let ((org-stored-links nil)
  259. (org-link-context-for-files nil))
  260. (org-test-with-temp-text-in-file "one\n<point>two"
  261. (fundamental-mode)
  262. (let ((file (buffer-file-name)))
  263. (equal (format "[[file:%s::two]]" file)
  264. (org-store-link '(4)))))))
  265. ;; A C-u C-u does *not* reverse `org-context-in-file-links' in
  266. ;; non-Org buffer.
  267. (should
  268. (let ((org-stored-links nil)
  269. (org-context-in-file-links nil))
  270. (org-test-with-temp-text-in-file "one\n<point>two"
  271. (fundamental-mode)
  272. (let ((file (buffer-file-name)))
  273. (equal (format "[[file:%s]]" file file)
  274. (org-store-link '(16)))))))
  275. ;; Context does not include special search syntax.
  276. (should
  277. (let ((org-stored-links nil)
  278. (org-context-in-file-links t))
  279. (org-test-with-temp-text-in-file "(two)"
  280. (fundamental-mode)
  281. (let ((file (buffer-file-name)))
  282. (equal (format "[[file:%s::two]]" file file)
  283. (org-store-link nil))))))
  284. (should
  285. (let ((org-stored-links nil)
  286. (org-context-in-file-links t))
  287. (org-test-with-temp-text-in-file "# two"
  288. (fundamental-mode)
  289. (let ((file (buffer-file-name)))
  290. (equal (format "[[file:%s::two]]" file file)
  291. (org-store-link nil))))))
  292. (should
  293. (let ((org-stored-links nil)
  294. (org-context-in-file-links t))
  295. (org-test-with-temp-text-in-file "*two"
  296. (fundamental-mode)
  297. (let ((file (buffer-file-name)))
  298. (equal (format "[[file:%s::two]]" file file)
  299. (org-store-link nil))))))
  300. (should
  301. (let ((org-stored-links nil)
  302. (org-context-in-file-links t))
  303. (org-test-with-temp-text-in-file "( two )"
  304. (fundamental-mode)
  305. (let ((file (buffer-file-name)))
  306. (equal (format "[[file:%s::two]]" file file)
  307. (org-store-link nil))))))
  308. (should
  309. (let ((org-stored-links nil)
  310. (org-context-in-file-links t))
  311. (org-test-with-temp-text-in-file "# two"
  312. (fundamental-mode)
  313. (let ((file (buffer-file-name)))
  314. (equal (format "[[file:%s::two]]" file file)
  315. (org-store-link nil))))))
  316. (should
  317. (let ((org-stored-links nil)
  318. (org-context-in-file-links t))
  319. (org-test-with-temp-text-in-file "#( two )"
  320. (fundamental-mode)
  321. (let ((file (buffer-file-name)))
  322. (equal (format "[[file:%s::two]]" file file)
  323. (org-store-link nil))))))
  324. (should
  325. (let ((org-stored-links nil)
  326. (org-context-in-file-links t))
  327. (org-test-with-temp-text-in-file "#** ((## two) )"
  328. (fundamental-mode)
  329. (let ((file (buffer-file-name)))
  330. (equal (format "[[file:%s::two]]" file file)
  331. (org-store-link nil))))))
  332. (should-not
  333. (let ((org-stored-links nil)
  334. (org-context-in-file-links t))
  335. (org-test-with-temp-text-in-file "(two"
  336. (fundamental-mode)
  337. (let ((file (buffer-file-name)))
  338. (equal (format "[[file:%s::two]]" file file)
  339. (org-store-link nil))))))
  340. ;; Context also ignore statistics cookies and special headlines
  341. ;; data.
  342. (should
  343. (let ((org-stored-links nil)
  344. (org-context-in-file-links t))
  345. (org-test-with-temp-text-in-file "* TODO [#A] COMMENT foo :bar:"
  346. (let ((file (buffer-file-name)))
  347. (equal (format "[[file:%s::*foo][foo]]" file file)
  348. (org-store-link nil))))))
  349. (should
  350. (let ((org-stored-links nil)
  351. (org-context-in-file-links t))
  352. (org-test-with-temp-text-in-file "* foo[33%]bar"
  353. (let ((file (buffer-file-name)))
  354. (equal (format "[[file:%s::*foo bar][foo bar]]" file file)
  355. (org-store-link nil))))))
  356. (should
  357. (let ((org-stored-links nil)
  358. (org-context-in-file-links t))
  359. (org-test-with-temp-text-in-file "* [%][/] foo [35%] bar[3/5]"
  360. (let ((file (buffer-file-name)))
  361. (equal (format "[[file:%s::*foo bar][foo bar]]" file file)
  362. (org-store-link nil)))))))
  363. ;;; Radio Targets
  364. (ert-deftest test-org-link/update-radio-target-regexp ()
  365. "Test `org-update-radio-target-regexp' specifications."
  366. ;; Properly update cache with no previous radio target regexp.
  367. (should
  368. (eq 'link
  369. (org-test-with-temp-text "radio\n\nParagraph\n\nradio"
  370. (save-excursion (goto-char (point-max)) (org-element-context))
  371. (insert "<<<")
  372. (search-forward "o")
  373. (insert ">>>")
  374. (org-update-radio-target-regexp)
  375. (goto-char (point-max))
  376. (org-element-type (org-element-context)))))
  377. ;; Properly update cache with previous radio target regexp.
  378. (should
  379. (eq 'link
  380. (org-test-with-temp-text "radio\n\nParagraph\n\nradio"
  381. (save-excursion (goto-char (point-max)) (org-element-context))
  382. (insert "<<<")
  383. (search-forward "o")
  384. (insert ">>>")
  385. (org-update-radio-target-regexp)
  386. (search-backward "r")
  387. (delete-char 5)
  388. (insert "new")
  389. (org-update-radio-target-regexp)
  390. (goto-char (point-max))
  391. (delete-region (line-beginning-position) (point))
  392. (insert "new")
  393. (org-element-type (org-element-context))))))
  394. ;;; Navigation
  395. (ert-deftest test-org-link/next-link ()
  396. "Test `org-next-link' specifications."
  397. ;; Move to any type of link.
  398. (should
  399. (equal "[[link]]"
  400. (org-test-with-temp-text "foo [[link]]"
  401. (org-next-link)
  402. (buffer-substring (point) (line-end-position)))))
  403. (should
  404. (equal "http://link"
  405. (org-test-with-temp-text "foo http://link"
  406. (org-next-link)
  407. (buffer-substring (point) (line-end-position)))))
  408. (should
  409. (equal "<http://link>"
  410. (org-test-with-temp-text "foo <http://link>"
  411. (org-next-link)
  412. (buffer-substring (point) (line-end-position)))))
  413. ;; Ignore link at point.
  414. (should
  415. (equal "[[link2]]"
  416. (org-test-with-temp-text "[[link1]] [[link2]]"
  417. (org-next-link)
  418. (buffer-substring (point) (line-end-position)))))
  419. ;; Ignore fake links.
  420. (should
  421. (equal "[[truelink]]"
  422. (org-test-with-temp-text "foo\n: [[link]]\n[[truelink]]"
  423. (org-next-link)
  424. (buffer-substring (point) (line-end-position)))))
  425. ;; Do not move point when there is no link.
  426. (should
  427. (org-test-with-temp-text "foo bar"
  428. (org-next-link)
  429. (bobp)))
  430. ;; Wrap around after a failed search.
  431. (should
  432. (equal "[[link]]"
  433. (org-test-with-temp-text "[[link]]\n<point>foo"
  434. (org-next-link)
  435. (let* ((this-command 'org-next-link)
  436. (last-command this-command))
  437. (org-next-link))
  438. (buffer-substring (point) (line-end-position)))))
  439. ;; Find links with item tags.
  440. (should
  441. (equal "[[link1]]"
  442. (org-test-with-temp-text "- tag [[link1]] :: description"
  443. (org-next-link)
  444. (buffer-substring (point) (search-forward "]]" nil t))))))
  445. (ert-deftest test-org-link/previous-link ()
  446. "Test `org-previous-link' specifications."
  447. ;; Move to any type of link.
  448. (should
  449. (equal "[[link]]"
  450. (org-test-with-temp-text "[[link]]\nfoo<point>"
  451. (org-previous-link)
  452. (buffer-substring (point) (line-end-position)))))
  453. (should
  454. (equal "http://link"
  455. (org-test-with-temp-text "http://link\nfoo<point>"
  456. (org-previous-link)
  457. (buffer-substring (point) (line-end-position)))))
  458. (should
  459. (equal "<http://link>"
  460. (org-test-with-temp-text "<http://link>\nfoo<point>"
  461. (org-previous-link)
  462. (buffer-substring (point) (line-end-position)))))
  463. ;; Ignore link at point.
  464. (should
  465. (equal "[[link1]]"
  466. (org-test-with-temp-text "[[link1]]\n[[link2<point>]]"
  467. (org-previous-link)
  468. (buffer-substring (point) (line-end-position)))))
  469. (should
  470. (equal "[[link1]]"
  471. (org-test-with-temp-text "line\n[[link1]]\n[[link2<point>]]"
  472. (org-previous-link)
  473. (buffer-substring (point) (line-end-position)))))
  474. ;; Ignore fake links.
  475. (should
  476. (equal "[[truelink]]"
  477. (org-test-with-temp-text "[[truelink]]\n: [[link]]\n<point>"
  478. (org-previous-link)
  479. (buffer-substring (point) (line-end-position)))))
  480. ;; Do not move point when there is no link.
  481. (should
  482. (org-test-with-temp-text "foo bar<point>"
  483. (org-previous-link)
  484. (eobp)))
  485. ;; Wrap around after a failed search.
  486. (should
  487. (equal "[[link]]"
  488. (org-test-with-temp-text "foo\n[[link]]"
  489. (org-previous-link)
  490. (let* ((this-command 'org-previous-link)
  491. (last-command this-command))
  492. (org-previous-link))
  493. (buffer-substring (point) (line-end-position))))))
  494. ;;; Link regexps
  495. (defmacro test-ol-parse-link-in-text (text)
  496. "Return list of :type and :path of link parsed in TEXT.
  497. \"<point>\" string must be at the beginning of the link to be parsed."
  498. (declare (indent 1))
  499. `(org-test-with-temp-text ,text
  500. (list (org-element-property :type (org-element-link-parser))
  501. (org-element-property :path (org-element-link-parser)))))
  502. (ert-deftest test-org-link/plain-link-re ()
  503. "Test `org-link-plain-re'."
  504. (should
  505. (equal
  506. '("https" "//example.com")
  507. (test-ol-parse-link-in-text
  508. "(<point>https://example.com)")))
  509. (should
  510. (equal
  511. '("https" "//example.com/qwe()")
  512. (test-ol-parse-link-in-text
  513. "(Some text <point>https://example.com/qwe())")))
  514. (should
  515. (equal
  516. '("https" "//doi.org/10.1016/0160-791x(79)90023-x")
  517. (test-ol-parse-link-in-text
  518. "<point>https://doi.org/10.1016/0160-791x(79)90023-x")))
  519. (should
  520. (equal
  521. '("file" "aa")
  522. (test-ol-parse-link-in-text
  523. "The <point>file:aa link")))
  524. (should
  525. (equal
  526. '("file" "a(b)c")
  527. (test-ol-parse-link-in-text
  528. "The <point>file:a(b)c link")))
  529. (should
  530. (equal
  531. '("file" "a()")
  532. (test-ol-parse-link-in-text
  533. "The <point>file:a() link")))
  534. (should
  535. (equal
  536. '("file" "aa((a))")
  537. (test-ol-parse-link-in-text
  538. "The <point>file:aa((a)) link")))
  539. (should
  540. (equal
  541. '("file" "aa(())")
  542. (test-ol-parse-link-in-text
  543. "The <point>file:aa(()) link")))
  544. (should
  545. (equal
  546. '("file" "/a")
  547. (test-ol-parse-link-in-text
  548. "The <point>file:/a link")))
  549. (should
  550. (equal
  551. '("file" "/a/")
  552. (test-ol-parse-link-in-text
  553. "The <point>file:/a/ link")))
  554. (should
  555. (equal
  556. '("http" "//")
  557. (test-ol-parse-link-in-text
  558. "The <point>http:// link")))
  559. (should
  560. (equal
  561. '("file" "ab")
  562. (test-ol-parse-link-in-text
  563. "The (some <point>file:ab) link")))
  564. (should
  565. (equal
  566. '("file" "aa")
  567. (test-ol-parse-link-in-text
  568. "The <point>file:aa) link")))
  569. (should
  570. (equal
  571. '("file" "aa")
  572. (test-ol-parse-link-in-text
  573. "The <point>file:aa( link")))
  574. (should
  575. (equal
  576. '("http" "//foo.com/more_(than)_one_(parens)")
  577. (test-ol-parse-link-in-text
  578. "The <point>http://foo.com/more_(than)_one_(parens) link")))
  579. (should
  580. (equal
  581. '("http" "//foo.com/blah_(wikipedia)#cite-1")
  582. (test-ol-parse-link-in-text
  583. "The <point>http://foo.com/blah_(wikipedia)#cite-1 link")))
  584. (should
  585. (equal
  586. '("http" "//foo.com/blah_(wikipedia)_blah#cite-1")
  587. (test-ol-parse-link-in-text
  588. "The <point>http://foo.com/blah_(wikipedia)_blah#cite-1 link")))
  589. (should
  590. (equal
  591. '("http" "//foo.com/unicode_(✪)_in_parens")
  592. (test-ol-parse-link-in-text
  593. "The <point>http://foo.com/unicode_(✪)_in_parens link")))
  594. (should
  595. (equal
  596. '("http" "//foo.com/(something)?after=parens")
  597. (test-ol-parse-link-in-text
  598. "The <point>http://foo.com/(something)?after=parens link"))))
  599. ;;; Insert Links
  600. (defmacro test-ol-with-link-parameters-as (type parameters &rest body)
  601. "Pass TYPE/PARAMETERS to `org-link-parameters' and execute BODY.
  602. Save the original value of `org-link-parameters', execute
  603. `org-link-set-parameters' with the relevant args, execute BODY
  604. and restore `org-link-parameters'.
  605. TYPE is as in `org-link-set-parameters'. PARAMETERS is a plist to
  606. be passed to `org-link-set-parameters'."
  607. (declare (indent 2))
  608. (let (orig-parameters)
  609. ;; Copy all keys in `parameters' and their original values to
  610. ;; `orig-parameters'.
  611. (cl-loop for param in parameters by 'cddr
  612. do (setq orig-parameters
  613. (plist-put orig-parameters param (org-link-get-parameter type param))))
  614. `(unwind-protect
  615. ;; Set `parameters' values and execute body.
  616. (progn (org-link-set-parameters ,type ,@parameters) ,@body)
  617. ;; Restore original values.
  618. (apply 'org-link-set-parameters ,type ',orig-parameters))))
  619. (defun test-ol-insert-link-get-desc (&optional link-location description)
  620. "Insert link in temp buffer, return description.
  621. LINK-LOCATION and DESCRIPTION are passed to
  622. `org-insert-link' (COMPLETE-FILE is always nil)."
  623. (org-test-with-temp-text ""
  624. (org-insert-link nil link-location description)
  625. (save-match-data
  626. (when (and
  627. (org-in-regexp org-link-bracket-re 1)
  628. (match-end 2))
  629. (match-string-no-properties 2)))))
  630. (defun test-ol/return-foobar (_link-test _desc)
  631. "Return string \"foobar\".
  632. Take (and ignore) arguments conforming to `:insert-description'
  633. API in `org-link-parameters'. Used in test
  634. `test-ol/insert-link-insert-description', for the case where
  635. `:insert-description' is a function symbol."
  636. "foobar-from-function")
  637. (ert-deftest test-org-link/insert-link-insert-description ()
  638. "Test `:insert-description' parameter handling."
  639. ;; String case.
  640. (should
  641. (string=
  642. "foobar-string"
  643. (test-ol-with-link-parameters-as
  644. "id" (:insert-description "foobar-string")
  645. (test-ol-insert-link-get-desc "id:foo-bar"))))
  646. ;; Lambda case.
  647. (should
  648. (string=
  649. "foobar-lambda"
  650. (test-ol-with-link-parameters-as
  651. "id" (:insert-description (lambda (_link-test _desc) "foobar-lambda"))
  652. (test-ol-insert-link-get-desc "id:foo-bar"))))
  653. ;; Function symbol case.
  654. (should
  655. (string=
  656. "foobar-from-function"
  657. (test-ol-with-link-parameters-as
  658. "id" (:insert-description #'test-ol/return-foobar)
  659. (test-ol-insert-link-get-desc "id:foo-bar"))))
  660. ;; `:insert-description' parameter is defined, but doesn't return a
  661. ;; string.
  662. (should
  663. (null
  664. (test-ol-with-link-parameters-as
  665. "id" (:insert-description #'ignore)
  666. (test-ol-insert-link-get-desc "id:foo-bar"))))
  667. ;; Description argument should override `:insert-description'.
  668. (should
  669. (string=
  670. "foobar-desc-arg"
  671. (test-ol-with-link-parameters-as
  672. "id" (:insert-description "foobar")
  673. (test-ol-insert-link-get-desc "id:foo-bar" "foobar-desc-arg"))))
  674. ;; When neither `:insert-description' nor
  675. ;; `org-link-make-description-function' is defined, there should be
  676. ;; no description
  677. (should
  678. (null
  679. (let ((org-link-make-description-function nil))
  680. (test-ol-insert-link-get-desc "fake-link-type:foo-bar")))))
  681. (provide 'test-ol)
  682. ;;; test-ol.el ends here