test-org-capture.el 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. ;;; test-org-capture.el --- Tests for org-capture.el -*- lexical-binding: t; -*-
  2. ;; Copyright (C) 2015, 2017 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 <http://www.gnu.org/licenses/>.
  14. ;;; Commentary:
  15. ;; Unit tests for Org Capture library.
  16. ;;; Code:
  17. (require 'org-capture)
  18. (ert-deftest test-org-capture/fill-template ()
  19. "Test `org-capture-fill-template' specifications."
  20. ;; When working on these tests consider to also change
  21. ;; `test-org-feed/fill-template'.
  22. ;; %(sexp) placeholder.
  23. (should
  24. (equal "success!\n"
  25. (org-capture-fill-template "%(concat \"success\" \"!\")")))
  26. ;; It is possible to include other place holders in %(sexp). In
  27. ;; that case properly escape \ and " characters.
  28. (should
  29. (equal "Nested string \"\\\"\\\"\"\n"
  30. (let ((org-store-link-plist nil))
  31. (org-capture-fill-template "%(concat \"%i\")"
  32. "Nested string \"\\\"\\\"\""))))
  33. ;; %<...> placeholder.
  34. (should
  35. (equal (concat (format-time-string "%Y") "\n")
  36. (org-capture-fill-template "%<%Y>")))
  37. ;; %t and %T placeholders.
  38. (should
  39. (equal (concat (format-time-string (org-time-stamp-format nil nil)) "\n")
  40. (org-capture-fill-template "%t")))
  41. (should
  42. (equal (concat (format-time-string (org-time-stamp-format t nil)) "\n")
  43. (org-capture-fill-template "%T")))
  44. ;; %u and %U placeholders.
  45. (should
  46. (equal
  47. (concat (format-time-string (org-time-stamp-format nil t)) "\n")
  48. (org-capture-fill-template "%u")))
  49. (should
  50. (equal
  51. (concat (format-time-string (org-time-stamp-format t t)) "\n")
  52. (org-capture-fill-template "%U")))
  53. ;; %i placeholder. Make sure sexp placeholders are not expanded
  54. ;; when they are inserted through this one.
  55. (should
  56. (equal "success!\n"
  57. (let ((org-store-link-plist nil))
  58. (org-capture-fill-template "%i" "success!"))))
  59. (should
  60. (equal "%(concat \"no \" \"evaluation\")\n"
  61. (let ((org-store-link-plist nil))
  62. (org-capture-fill-template
  63. "%i" "%(concat \"no \" \"evaluation\")"))))
  64. ;; When %i contents span over multiple line, repeat initial leading
  65. ;; characters over each line.
  66. (should
  67. (equal "> line 1\n> line 2\n"
  68. (let ((org-store-link-plist nil))
  69. (org-capture-fill-template "> %i" "line 1\nline 2"))))
  70. ;; Test %-escaping with \ character.
  71. (should
  72. (equal "%i\n"
  73. (let ((org-store-link-plist nil))
  74. (org-capture-fill-template "\\%i" "success!"))))
  75. (should
  76. (equal "\\success!\n"
  77. (let ((org-store-link-plist nil))
  78. (org-capture-fill-template "\\\\%i" "success!"))))
  79. (should
  80. (equal "\\%i\n"
  81. (let ((org-store-link-plist nil))
  82. (org-capture-fill-template "\\\\\\%i" "success!"))))
  83. ;; More than one placeholder in the same template.
  84. (should
  85. (equal "success! success! success! success!\n"
  86. (let ((org-store-link-plist nil))
  87. (org-capture-fill-template "%i %i %i %i" "success!"))))
  88. ;; %(sexp) placeholder with an input containing the traps %, " and )
  89. ;; all at once which is complicated to parse.
  90. (should
  91. (equal "5 % Less (See Item \"3)\" Somewhere)\n"
  92. (let ((org-store-link-plist nil))
  93. (org-capture-fill-template
  94. "%(capitalize \"%i\")"
  95. "5 % less (see item \"3)\" somewhere)")))))
  96. (ert-deftest test-org-capture/refile ()
  97. "Test `org-capture-refile' specifications."
  98. ;; When refiling, make sure the headline being refiled is the one
  99. ;; being captured. In particular, empty lines after the entry may
  100. ;; be removed, and we don't want to shift onto the next heading.
  101. (should
  102. (string-prefix-p
  103. "** H1"
  104. (org-test-with-temp-text-in-file "* A\n* B\n"
  105. (let* ((file (buffer-file-name))
  106. (org-capture-templates
  107. `(("t" "Todo" entry (file+headline ,file "A") "** H1 %?"))))
  108. (org-capture nil "t")
  109. (insert "\n")
  110. (cl-letf (((symbol-function 'org-refile)
  111. (lambda ()
  112. (interactive)
  113. (throw :return
  114. (buffer-substring-no-properties
  115. (line-beginning-position)
  116. (line-end-position))))))
  117. (catch :return (org-capture-refile)))))))
  118. ;; When the entry is refiled, `:jump-to-captured' moves point to the
  119. ;; refile location, not the initial capture target.
  120. (should
  121. (org-test-with-temp-text-in-file "* Refile target"
  122. (let ((file1 (buffer-file-name)))
  123. (org-test-with-temp-text-in-file "* A"
  124. (let* ((file2 (buffer-file-name))
  125. (org-capture-templates
  126. `(("t" "Todo" entry (file+headline ,file2 "A")
  127. "** H1 %?" :jump-to-captured t))))
  128. (org-capture nil "t")
  129. (cl-letf (((symbol-function 'org-refile-get-location)
  130. (lambda (&rest args)
  131. (list (file-name-nondirectory file1) file1 nil nil))))
  132. (org-capture-refile)
  133. (list file1 file2 (buffer-file-name)))))))))
  134. (ert-deftest test-org-capture/abort ()
  135. "Test that capture can be aborted after inserting at end of capture buffer."
  136. (should
  137. (equal
  138. "* A\n* B\n"
  139. (org-test-with-temp-text-in-file "* A\n* B\n"
  140. (let* ((file (buffer-file-name))
  141. (org-capture-templates
  142. `(("t" "Todo" entry (file+headline ,file "A") "** H1 %?"))))
  143. (org-capture nil "t")
  144. (goto-char (point-max))
  145. (insert "Capture text")
  146. (org-capture-kill))
  147. (buffer-string)))))
  148. (ert-deftest test-org-caputre/entry ()
  149. "Test `entry' type in capture template."
  150. ;; Do not break next headline.
  151. (should
  152. (equal
  153. "* A\n** H1 Capture text\n* B\n"
  154. (org-test-with-temp-text-in-file "* A\n* B\n"
  155. (let* ((file (buffer-file-name))
  156. (org-capture-templates
  157. `(("t" "Todo" entry (file+headline ,file "A") "** H1 %?"))))
  158. (org-capture nil "t")
  159. (goto-char (point-max))
  160. (insert "Capture text")
  161. (org-capture-finalize))
  162. (buffer-string)))))
  163. (ert-deftest test-org-capture/table-line ()
  164. "Test `table-line' type in capture template."
  165. ;; When a only file is specified, use the first table available.
  166. (should
  167. (equal "Text
  168. | a |
  169. | x |
  170. | b |"
  171. (org-test-with-temp-text-in-file "Text\n\n| a |\n\n| b |"
  172. (let* ((file (buffer-file-name))
  173. (org-capture-templates
  174. `(("t" "Table" table-line (file ,file) "| x |"
  175. :immediate-finish t))))
  176. (org-capture nil "t"))
  177. (buffer-string))))
  178. ;; When an entry is specified, find the first table in the
  179. ;; corresponding section.
  180. (should
  181. (equal "* Foo
  182. | a |
  183. * Inbox
  184. | b |
  185. | x |
  186. "
  187. (org-test-with-temp-text-in-file "* Foo\n| a |\n* Inbox\n| b |\n"
  188. (let* ((file (buffer-file-name))
  189. (org-capture-templates
  190. `(("t" "Table" table-line (file+headline ,file "Inbox")
  191. "| x |" :immediate-finish t))))
  192. (org-capture nil "t"))
  193. (buffer-string))))
  194. (should
  195. (equal "* Inbox
  196. | a |
  197. | x |
  198. | b |
  199. "
  200. (org-test-with-temp-text-in-file "* Inbox\n| a |\n\n| b |\n"
  201. (let* ((file (buffer-file-name))
  202. (org-capture-templates
  203. `(("t" "Table" table-line (file+headline ,file "Inbox")
  204. "| x |" :immediate-finish t))))
  205. (org-capture nil "t"))
  206. (buffer-string))))
  207. ;; When a precise location is specified, find the first table after
  208. ;; point, down to the end of the section.
  209. (should
  210. (equal "| a |
  211. | b |
  212. | x |
  213. "
  214. (org-test-with-temp-text-in-file "| a |\n\n\n| b |\n"
  215. (let* ((file (buffer-file-name))
  216. (org-capture-templates
  217. `(("t" "Table" table-line (file+function ,file forward-line)
  218. "| x |" :immediate-finish t))))
  219. (org-capture nil "t"))
  220. (buffer-string))))
  221. ;; Create a new table with an empty header when none can be found.
  222. (should
  223. (equal "| | |\n|---+---|\n| a | b |\n"
  224. (org-test-with-temp-text-in-file ""
  225. (let* ((file (buffer-file-name))
  226. (org-capture-templates
  227. `(("t" "Table" table-line (file ,file) "| a | b |"
  228. :immediate-finish t))))
  229. (org-capture nil "t"))
  230. (buffer-string))))
  231. ;; Properly insert row with formulas.
  232. (should
  233. (equal "| 1 |\n| 2 |\n#+TBLFM: "
  234. (org-test-with-temp-text-in-file "| 1 |\n#+TBLFM: "
  235. (let* ((file (buffer-file-name))
  236. (org-capture-templates
  237. `(("t" "Table" table-line (file ,file)
  238. "| 2 |" :immediate-finish t))))
  239. (org-capture nil "t"))
  240. (buffer-string))))
  241. ;; When `:prepend' is nil, add the row at the end of the table.
  242. (should
  243. (equal "| a |\n| x |\n"
  244. (org-test-with-temp-text-in-file "| a |"
  245. (let* ((file (buffer-file-name))
  246. (org-capture-templates
  247. `(("t" "Table" table-line (file ,file)
  248. "| x |" :immediate-finish t))))
  249. (org-capture nil "t"))
  250. (buffer-string))))
  251. ;; When `:prepend' is non-nil, add it as the first row after the
  252. ;; header, if there is one, or the first row otherwise.
  253. (should
  254. (equal "| a |\n|---|\n| x |\n| b |"
  255. (org-test-with-temp-text-in-file "| a |\n|---|\n| b |"
  256. (let* ((file (buffer-file-name))
  257. (org-capture-templates
  258. `(("t" "Table" table-line (file ,file)
  259. "| x |" :immediate-finish t :prepend t))))
  260. (org-capture nil "t"))
  261. (buffer-string))))
  262. (should
  263. (equal "| x |\n| a |"
  264. (org-test-with-temp-text-in-file "| a |"
  265. (let* ((file (buffer-file-name))
  266. (org-capture-templates
  267. `(("t" "Table" table-line (file ,file)
  268. "| x |" :immediate-finish t :prepend t))))
  269. (org-capture nil "t"))
  270. (buffer-string))))
  271. ;; When `:table-line-pos' is set and is meaningful, obey it.
  272. (should
  273. (equal "| a |\n|---|\n| b |\n| x |\n|---|\n| c |"
  274. (org-test-with-temp-text-in-file "| a |\n|---|\n| b |\n|---|\n| c |"
  275. (let* ((file (buffer-file-name))
  276. (org-capture-templates
  277. `(("t" "Table" table-line (file ,file)
  278. "| x |" :immediate-finish t :table-line-pos "II-1"))))
  279. (org-capture nil "t"))
  280. (buffer-string))))
  281. (should
  282. (equal "| a |\n|---|\n| x |\n| b |\n|---|\n| c |"
  283. (org-test-with-temp-text-in-file "| a |\n|---|\n| b |\n|---|\n| c |"
  284. (let* ((file (buffer-file-name))
  285. (org-capture-templates
  286. `(("t" "Table" table-line (file ,file)
  287. "| x |" :immediate-finish t :table-line-pos "I+1"))))
  288. (org-capture nil "t"))
  289. (buffer-string))))
  290. ;; Throw an error on invalid `:table-line-pos' specifications.
  291. (should-error
  292. (org-test-with-temp-text-in-file "| a |"
  293. (let* ((file (buffer-file-name))
  294. (org-capture-templates
  295. `(("t" "Table" table-line (file ,file)
  296. "| x |" :immediate-finish t :table-line-pos "II+99"))))
  297. (org-capture nil "t")
  298. t)))
  299. ;; Update formula when capturing one or more rows.
  300. (should
  301. (equal
  302. '(("@3$1" . "9"))
  303. (org-test-with-temp-text-in-file "| 1 |\n|---|\n| 9 |\n#+tblfm: @2$1=9"
  304. (let* ((file (buffer-file-name))
  305. (org-capture-templates
  306. `(("t" "Table" table-line (file ,file)
  307. "| 2 |" :immediate-finish t :table-line-pos "I-1"))))
  308. (org-capture nil "t")
  309. (org-table-get-stored-formulas)))))
  310. (should
  311. (equal
  312. '(("@4$1" . "9"))
  313. (org-test-with-temp-text-in-file "| 1 |\n|---|\n| 9 |\n#+tblfm: @2$1=9"
  314. (let* ((file (buffer-file-name))
  315. (org-capture-templates
  316. `(("t" "Table" table-line (file ,file)
  317. "| 2 |\n| 3 |" :immediate-finish t :table-line-pos "I-1"))))
  318. (org-capture nil "t")
  319. (org-table-get-stored-formulas)))))
  320. ;; Do not update formula when cell in inserted below affected row.
  321. (should-not
  322. (equal
  323. '(("@3$1" . "9"))
  324. (org-test-with-temp-text-in-file "| 1 |\n|---|\n| 9 |\n#+tblfm: @2$1=9"
  325. (let* ((file (buffer-file-name))
  326. (org-capture-templates
  327. `(("t" "Table" table-line (file ,file)
  328. "| 2 |" :immediate-finish t))))
  329. (org-capture nil "t")
  330. (org-table-get-stored-formulas))))))
  331. (provide 'test-org-capture)
  332. ;;; test-org-capture.el ends here