test-org-capture.el 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  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/insert-at-end-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-capture/table-line ()
  149. "Test `table-line' type in capture template."
  150. ;; When a only file is specified, use the first table available.
  151. (should
  152. (equal "Text
  153. | a |
  154. | x |
  155. | b |"
  156. (org-test-with-temp-text-in-file "Text\n\n| a |\n\n| b |"
  157. (let* ((file (buffer-file-name))
  158. (org-capture-templates
  159. `(("t" "Table" table-line (file ,file) "| x |"
  160. :immediate-finish t))))
  161. (org-capture nil "t"))
  162. (buffer-string))))
  163. ;; When an entry is specified, find the first table in the
  164. ;; corresponding section.
  165. (should
  166. (equal "* Foo
  167. | a |
  168. * Inbox
  169. | b |
  170. | x |
  171. "
  172. (org-test-with-temp-text-in-file "* Foo\n| a |\n* Inbox\n| b |\n"
  173. (let* ((file (buffer-file-name))
  174. (org-capture-templates
  175. `(("t" "Table" table-line (file+headline ,file "Inbox")
  176. "| x |" :immediate-finish t))))
  177. (org-capture nil "t"))
  178. (buffer-string))))
  179. (should
  180. (equal "* Inbox
  181. | a |
  182. | x |
  183. | b |
  184. "
  185. (org-test-with-temp-text-in-file "* Inbox\n| a |\n\n| b |\n"
  186. (let* ((file (buffer-file-name))
  187. (org-capture-templates
  188. `(("t" "Table" table-line (file+headline ,file "Inbox")
  189. "| x |" :immediate-finish t))))
  190. (org-capture nil "t"))
  191. (buffer-string))))
  192. ;; When a precise location is specified, find the first table after
  193. ;; point, down to the end of the section.
  194. (should
  195. (equal "| a |
  196. | b |
  197. | x |
  198. "
  199. (org-test-with-temp-text-in-file "| a |\n\n\n| b |\n"
  200. (let* ((file (buffer-file-name))
  201. (org-capture-templates
  202. `(("t" "Table" table-line (file+function ,file forward-line)
  203. "| x |" :immediate-finish t))))
  204. (org-capture nil "t"))
  205. (buffer-string))))
  206. ;; Create a new table with an empty header when none can be found.
  207. (should
  208. (equal "| | |\n|---+---|\n| a | b |\n"
  209. (org-test-with-temp-text-in-file ""
  210. (let* ((file (buffer-file-name))
  211. (org-capture-templates
  212. `(("t" "Table" table-line (file ,file) "| a | b |"
  213. :immediate-finish t))))
  214. (org-capture nil "t"))
  215. (buffer-string))))
  216. ;; Properly insert row with formulas.
  217. (should
  218. (equal "| 1 |\n| 2 |\n#+TBLFM: "
  219. (org-test-with-temp-text-in-file "| 1 |\n#+TBLFM: "
  220. (let* ((file (buffer-file-name))
  221. (org-capture-templates
  222. `(("t" "Table" table-line (file ,file)
  223. "| 2 |" :immediate-finish t))))
  224. (org-capture nil "t"))
  225. (buffer-string))))
  226. ;; When `:prepend' is nil, add the row at the end of the table.
  227. (should
  228. (equal "| a |\n| x |\n"
  229. (org-test-with-temp-text-in-file "| a |"
  230. (let* ((file (buffer-file-name))
  231. (org-capture-templates
  232. `(("t" "Table" table-line (file ,file)
  233. "| x |" :immediate-finish t))))
  234. (org-capture nil "t"))
  235. (buffer-string))))
  236. ;; When `:prepend' is non-nil, add it as the first row after the
  237. ;; header, if there is one, or the first row otherwise.
  238. (should
  239. (equal "| a |\n|---|\n| x |\n| b |"
  240. (org-test-with-temp-text-in-file "| a |\n|---|\n| b |"
  241. (let* ((file (buffer-file-name))
  242. (org-capture-templates
  243. `(("t" "Table" table-line (file ,file)
  244. "| x |" :immediate-finish t :prepend t))))
  245. (org-capture nil "t"))
  246. (buffer-string))))
  247. (should
  248. (equal "| x |\n| a |"
  249. (org-test-with-temp-text-in-file "| a |"
  250. (let* ((file (buffer-file-name))
  251. (org-capture-templates
  252. `(("t" "Table" table-line (file ,file)
  253. "| x |" :immediate-finish t :prepend t))))
  254. (org-capture nil "t"))
  255. (buffer-string))))
  256. ;; When `:table-line-pos' is set and is meaningful, obey it.
  257. (should
  258. (equal "| a |\n|---|\n| b |\n| x |\n|---|\n| c |"
  259. (org-test-with-temp-text-in-file "| a |\n|---|\n| b |\n|---|\n| c |"
  260. (let* ((file (buffer-file-name))
  261. (org-capture-templates
  262. `(("t" "Table" table-line (file ,file)
  263. "| x |" :immediate-finish t :table-line-pos "II-1"))))
  264. (org-capture nil "t"))
  265. (buffer-string))))
  266. (should
  267. (equal "| a |\n|---|\n| x |\n| b |\n|---|\n| c |"
  268. (org-test-with-temp-text-in-file "| a |\n|---|\n| b |\n|---|\n| c |"
  269. (let* ((file (buffer-file-name))
  270. (org-capture-templates
  271. `(("t" "Table" table-line (file ,file)
  272. "| x |" :immediate-finish t :table-line-pos "I+1"))))
  273. (org-capture nil "t"))
  274. (buffer-string))))
  275. ;; Throw an error on invalid `:table-line-pos' specifications.
  276. (should-error
  277. (org-test-with-temp-text-in-file "| a |"
  278. (let* ((file (buffer-file-name))
  279. (org-capture-templates
  280. `(("t" "Table" table-line (file ,file)
  281. "| x |" :immediate-finish t :table-line-pos "II+99"))))
  282. (org-capture nil "t")
  283. t)))
  284. ;; Update formula when capturing one or more rows.
  285. (should
  286. (equal
  287. '(("@3$1" . "9"))
  288. (org-test-with-temp-text-in-file "| 1 |\n|---|\n| 9 |\n#+tblfm: @2$1=9"
  289. (let* ((file (buffer-file-name))
  290. (org-capture-templates
  291. `(("t" "Table" table-line (file ,file)
  292. "| 2 |" :immediate-finish t :table-line-pos "I-1"))))
  293. (org-capture nil "t")
  294. (org-table-get-stored-formulas)))))
  295. (should
  296. (equal
  297. '(("@4$1" . "9"))
  298. (org-test-with-temp-text-in-file "| 1 |\n|---|\n| 9 |\n#+tblfm: @2$1=9"
  299. (let* ((file (buffer-file-name))
  300. (org-capture-templates
  301. `(("t" "Table" table-line (file ,file)
  302. "| 2 |\n| 3 |" :immediate-finish t :table-line-pos "I-1"))))
  303. (org-capture nil "t")
  304. (org-table-get-stored-formulas)))))
  305. ;; Do not update formula when cell in inserted below affected row.
  306. (should-not
  307. (equal
  308. '(("@3$1" . "9"))
  309. (org-test-with-temp-text-in-file "| 1 |\n|---|\n| 9 |\n#+tblfm: @2$1=9"
  310. (let* ((file (buffer-file-name))
  311. (org-capture-templates
  312. `(("t" "Table" table-line (file ,file)
  313. "| 2 |" :immediate-finish t))))
  314. (org-capture nil "t")
  315. (org-table-get-stored-formulas))))))
  316. (provide 'test-org-capture)
  317. ;;; test-org-capture.el ends here