mirror of
https://github.com/org-roam/org-roam
synced 2025-09-24 16:30:55 -05:00
Compare commits
5 Commits
doc-build
...
test-captu
Author | SHA1 | Date | |
---|---|---|---|
|
8a61cf35f8 | ||
|
b7483a1df5 | ||
|
2ac1760620 | ||
|
ed94524964 | ||
|
89dfaef38b |
@@ -1,5 +1,8 @@
|
||||
# Changelog
|
||||
|
||||
## 2.3.2
|
||||
- [#2056](https://github.com/org-roam/org-roam/pull/2056) capture: IDs are now created for entries in capture templates
|
||||
|
||||
## 2.3.1 (2025-06-26)
|
||||
|
||||
* (fix): Use correct type specifications to suppress warnings by @okomestudio in https://github.com/org-roam/org-roam/pull/2522
|
||||
|
@@ -339,11 +339,12 @@ In this case, interactive selection will be bypassed."
|
||||
(when goto (run-hooks 'org-roam-dailies-find-file-hook)))
|
||||
|
||||
(add-hook 'org-roam-capture-preface-hook #'org-roam-dailies--override-capture-time-h)
|
||||
|
||||
(defun org-roam-dailies--override-capture-time-h ()
|
||||
"Override the `:default-time' with the time from `:override-default-time'."
|
||||
(prog1 nil
|
||||
(when (org-roam-capture--get :override-default-time)
|
||||
(org-capture-put :default-time (org-roam-capture--get :override-default-time)))))
|
||||
(when (org-roam-capture--get :override-default-time)
|
||||
(org-capture-put :default-time (org-roam-capture--get :override-default-time)))
|
||||
nil)
|
||||
|
||||
;;; Bindings
|
||||
(defvar org-roam-dailies-map (make-sparse-keymap)
|
||||
|
@@ -466,22 +466,23 @@ processing by `org-capture'.
|
||||
Note: During the capture process this function is run by
|
||||
`org-capture-set-target-location', as a (function ...) based
|
||||
capture target."
|
||||
(let ((id (cond ((run-hook-with-args-until-success 'org-roam-capture-preface-hook))
|
||||
(t (org-roam-capture--setup-target-location)))))
|
||||
(org-roam-capture--adjust-point-for-capture-type)
|
||||
(let ((template (org-capture-get :template)))
|
||||
(when (stringp template)
|
||||
(org-capture-put
|
||||
:template
|
||||
(org-roam-capture--fill-template template))))
|
||||
(org-roam-capture--put :id id)
|
||||
(org-roam-capture--put :finalize (or (org-capture-get :finalize)
|
||||
(org-roam-capture--get :finalize)))))
|
||||
(if-let ((id (run-hook-with-args-until-success 'org-roam-capture-preface-hook)))
|
||||
(org-roam-capture--put :id id)
|
||||
(org-roam-capture--setup-target-location)
|
||||
;; Adjust point for plain captures to skip past metadata (e.g. properties drawer)
|
||||
(org-roam-capture--adjust-point-for-capture-type))
|
||||
(let ((template (org-capture-get :template)))
|
||||
(when (stringp template)
|
||||
(org-capture-put
|
||||
:template
|
||||
(org-roam-capture--fill-template template))))
|
||||
(org-roam-capture--put :finalize (or (org-capture-get :finalize)
|
||||
(org-roam-capture--get :finalize))))
|
||||
|
||||
(defun org-roam-capture--setup-target-location ()
|
||||
"Initialize the buffer, and goto the location of the new capture.
|
||||
Return the ID of the location."
|
||||
(let (p new-file-p)
|
||||
"Initialize the buffer, and goto the location of the new capture."
|
||||
(let ((target-entry-p t)
|
||||
p new-file-p id)
|
||||
(pcase (org-roam-capture--get-target)
|
||||
(`(file ,path)
|
||||
(setq path (org-roam-capture--target-truepath path)
|
||||
@@ -489,7 +490,8 @@ Return the ID of the location."
|
||||
(when new-file-p (org-roam-capture--put :new-file path))
|
||||
(set-buffer (org-capture-target-buffer path))
|
||||
(widen)
|
||||
(setq p (goto-char (point-min))))
|
||||
(setq p (goto-char (point-min))
|
||||
target-entry-p nil))
|
||||
(`(file+olp ,path ,olp)
|
||||
(setq path (org-roam-capture--target-truepath path)
|
||||
new-file-p (org-roam-capture--new-file-p path))
|
||||
@@ -505,9 +507,12 @@ Return the ID of the location."
|
||||
(set-buffer (org-capture-target-buffer path))
|
||||
(when new-file-p
|
||||
(org-roam-capture--put :new-file path)
|
||||
(insert (org-roam-capture--fill-template head 'ensure-newline)))
|
||||
(insert (org-roam-capture--fill-template head 'ensure-newline))
|
||||
(setq p (point-max)))
|
||||
(widen)
|
||||
(setq p (goto-char (point-min))))
|
||||
(unless new-file-p
|
||||
(setq p (goto-char (point-min))))
|
||||
(setq target-entry-p nil))
|
||||
(`(file+head+olp ,path ,head ,olp)
|
||||
(setq path (org-roam-capture--target-truepath path)
|
||||
new-file-p (org-roam-capture--new-file-p path))
|
||||
@@ -569,17 +574,45 @@ Return the ID of the location."
|
||||
(user-error "No node with title or id \"%s\"" title-or-id))))
|
||||
(set-buffer (org-capture-target-buffer (org-roam-node-file node)))
|
||||
(goto-char (org-roam-node-point node))
|
||||
(setq p (org-roam-node-point node)))))
|
||||
(setq p (org-roam-node-point node)
|
||||
target-entry-p (and (derived-mode-p 'org-mode) (org-at-heading-p))))))
|
||||
;; Setup `org-id' for the current capture target and return it back to the
|
||||
;; caller.
|
||||
(save-excursion
|
||||
(goto-char p)
|
||||
(if-let ((id (org-entry-get p "ID")))
|
||||
(setf (org-roam-node-id org-roam-capture--node) id)
|
||||
(org-entry-put p "ID" (org-roam-node-id org-roam-capture--node)))
|
||||
(prog1
|
||||
(org-id-get)
|
||||
(run-hooks 'org-roam-capture-new-node-hook)))))
|
||||
;; Unless it's an entry type, then we want to create an ID for the entry instead
|
||||
(pcase (org-capture-get :type)
|
||||
('entry
|
||||
(advice-add #'org-capture-place-entry :after #'org-roam-capture--create-id-for-entry)
|
||||
(org-roam-capture--put :new-node-p t)
|
||||
(setq id (org-roam-node-id org-roam-capture--node)))
|
||||
(_
|
||||
(save-excursion
|
||||
(goto-char p)
|
||||
(unless (org-entry-get p "ID")
|
||||
(org-roam-capture--put :new-node-p t))
|
||||
(setq id (or (org-entry-get p "ID")
|
||||
(org-roam-node-id org-roam-capture--node)))
|
||||
(setf (org-roam-node-id org-roam-capture--node) id)
|
||||
(org-entry-put p "ID" id))))
|
||||
(org-roam-capture--put :id id)
|
||||
(org-roam-capture--put :target-entry-p target-entry-p)
|
||||
(advice-add #'org-capture-place-template :before #'org-roam-capture--set-target-entry-p-a)
|
||||
(advice-add #'org-capture-place-template :after #'org-roam-capture-run-new-node-hook-a)))
|
||||
|
||||
(defun org-roam-capture--set-target-entry-p-a (_)
|
||||
"Correct `:target-entry-p' in Org-capture template based on `:target.'."
|
||||
(org-capture-put :target-entry-p (org-roam-capture--get :target-entry-p))
|
||||
(advice-remove #'org-capture-place-template #'org-roam-capture--set-target-entry-p-a))
|
||||
|
||||
(defun org-roam-capture-run-new-node-hook-a (_)
|
||||
"Advice to run after the Org-capture template is placed."
|
||||
(when (org-roam-capture--get :new-node-p)
|
||||
(run-hooks 'org-roam-capture-new-node-hook))
|
||||
(advice-remove #'org-capture-place-template #'org-roam-capture--place-template-a))
|
||||
|
||||
(defun org-roam-capture--create-id-for-entry ()
|
||||
"Create the ID for the new entry."
|
||||
(org-entry-put (point) "ID" (org-roam-capture--get :id))
|
||||
(advice-remove #'org-capture-place-entry #'org-roam-capture--create-id-for-entry))
|
||||
|
||||
(defun org-roam-capture--get-target ()
|
||||
"Get the current capture :target for the capture template in use."
|
||||
@@ -657,27 +690,17 @@ POS is the current position of point (an integer) inside the
|
||||
currently active capture buffer, where the adjustment should
|
||||
start to begin from. If it's nil, then it will default to
|
||||
the current value of `point'."
|
||||
(or pos (setq pos (point)))
|
||||
(goto-char pos)
|
||||
(let ((location-type (if (= pos 1) 'beginning-of-file 'heading-at-point)))
|
||||
(and (eq location-type 'heading-at-point)
|
||||
(cl-assert (org-at-heading-p)))
|
||||
(pcase (org-capture-get :type)
|
||||
(`plain
|
||||
(cl-case location-type
|
||||
(beginning-of-file
|
||||
(if (org-capture-get :prepend)
|
||||
(let ((el (org-element-at-point)))
|
||||
(while (and (not (eobp))
|
||||
(memq (org-element-type el)
|
||||
'(drawer property-drawer keyword comment comment-block horizontal-rule)))
|
||||
(goto-char (org-element-property :end el))
|
||||
(setq el (org-element-at-point))))
|
||||
(goto-char (org-entry-end-position))))
|
||||
(heading-at-point
|
||||
(if (org-capture-get :prepend)
|
||||
(org-end-of-meta-data t)
|
||||
(goto-char (org-entry-end-position))))))))
|
||||
(goto-char (or pos (point)))
|
||||
(pcase (org-capture-get :type)
|
||||
(`plain
|
||||
(if (org-capture-get :prepend)
|
||||
(let ((el (org-element-at-point)))
|
||||
(while (and (not (eobp))
|
||||
(memq (org-element-type el)
|
||||
'(drawer property-drawer keyword comment comment-block horizontal-rule)))
|
||||
(goto-char (org-element-property :end el))
|
||||
(setq el (org-element-at-point))))
|
||||
(goto-char (org-entry-end-position)))))
|
||||
(point))
|
||||
|
||||
;;; Capture implementation
|
||||
|
@@ -810,10 +810,9 @@ Assumes that the cursor was put where the link is."
|
||||
(defun org-roam-link-replace-all ()
|
||||
"Replace all \"roam:\" links in buffer with \"id:\" links."
|
||||
(interactive)
|
||||
(let ((org-roam-link-prefix (concat "[[" org-roam-link-type ":")))
|
||||
(org-with-point-at 1
|
||||
(while (re-search-forward org-roam-link-prefix nil t)
|
||||
(org-roam-link-replace-at-point)))))
|
||||
(org-with-point-at 1
|
||||
(while (search-forward (concat "[[" org-roam-link-type ":") nil t)
|
||||
(org-roam-link-replace-at-point))))
|
||||
|
||||
(add-hook 'org-roam-find-file-hook #'org-roam--replace-roam-links-on-save-h)
|
||||
(defun org-roam--replace-roam-links-on-save-h ()
|
||||
|
@@ -58,6 +58,330 @@
|
||||
(org-roam-capture--fill-template (lambda () "foo"))
|
||||
:to-equal "foo")))
|
||||
|
||||
(describe "org-roam-capture entry-type ID creation"
|
||||
(it "creates ID for entry-type captures"
|
||||
(let* ((temp-dir (make-temp-file "org-roam-test" t))
|
||||
(test-file (expand-file-name "test.org" temp-dir))
|
||||
(org-roam-directory temp-dir)
|
||||
(org-roam-capture--node (org-roam-node-create :id (org-id-new)))
|
||||
(org-roam-capture--info (make-hash-table :test 'equal))
|
||||
capture-id)
|
||||
(unwind-protect
|
||||
(progn
|
||||
;; Create initial file content
|
||||
(with-temp-file test-file
|
||||
(insert "#+TITLE: Test File\n\n* Parent Heading\n:PROPERTIES:\n:ID: parent-id\n:END:\n"))
|
||||
|
||||
;; Mock org-capture context and get-target
|
||||
(cl-letf* (((symbol-function 'org-capture-get)
|
||||
(lambda (prop)
|
||||
(pcase prop
|
||||
(:type 'entry)
|
||||
(_ nil))))
|
||||
((symbol-function 'org-roam-capture--get-target)
|
||||
(lambda () `(file ,test-file))))
|
||||
|
||||
;; Call the setup function
|
||||
(with-current-buffer (find-file-noselect test-file)
|
||||
(org-roam-capture--setup-target-location)
|
||||
(setq capture-id (org-roam-capture--get :id)))
|
||||
|
||||
;; Verify ID was created and stored for entry type
|
||||
(expect capture-id :not :to-be nil)
|
||||
(expect (org-roam-capture--get :new-node-p) :to-be t)))
|
||||
(delete-directory temp-dir t))))
|
||||
|
||||
(it "creates ID at target for non-entry-type captures"
|
||||
(let* ((temp-dir (make-temp-file "org-roam-test" t))
|
||||
(test-file (expand-file-name "test-plain.org" temp-dir))
|
||||
(org-roam-directory temp-dir)
|
||||
(org-roam-capture--node (org-roam-node-create :id (org-id-new)))
|
||||
(org-roam-capture--info (make-hash-table :test 'equal))
|
||||
capture-id)
|
||||
(unwind-protect
|
||||
(progn
|
||||
;; Create initial empty file
|
||||
(with-temp-file test-file
|
||||
(insert "#+TITLE: Test\n"))
|
||||
|
||||
;; Mock org-capture context for plain type
|
||||
(cl-letf* (((symbol-function 'org-capture-get)
|
||||
(lambda (prop)
|
||||
(pcase prop
|
||||
(:type 'plain)
|
||||
(_ nil))))
|
||||
((symbol-function 'org-roam-capture--get-target)
|
||||
(lambda () `(file ,test-file))))
|
||||
|
||||
;; Call the setup function
|
||||
(with-current-buffer (find-file-noselect test-file)
|
||||
(org-roam-capture--setup-target-location)
|
||||
(setq capture-id (org-roam-capture--get :id)))
|
||||
|
||||
;; For non-entry types, ID should be created at the target location
|
||||
(expect capture-id :not :to-be nil)
|
||||
(expect (org-roam-capture--get :new-node-p) :to-be t)))
|
||||
(delete-directory temp-dir t)))))
|
||||
|
||||
(describe "org-roam-capture advice functions"
|
||||
:var ((org-roam-capture--info))
|
||||
|
||||
(before-each
|
||||
(setq org-roam-capture--info (make-hash-table :test 'equal)))
|
||||
|
||||
(it "org-roam-capture--create-id-for-entry creates and removes advice"
|
||||
(cl-letf* ((entry-id nil)
|
||||
((symbol-function 'org-entry-put)
|
||||
(lambda (pom prop val)
|
||||
(when (string= prop "ID")
|
||||
(setq entry-id val))))
|
||||
((symbol-function 'org-roam-capture--get)
|
||||
(lambda (prop)
|
||||
(if (eq prop :id)
|
||||
"test-id-123"
|
||||
nil))))
|
||||
|
||||
;; Add the advice
|
||||
(advice-add #'org-capture-place-entry :after #'org-roam-capture--create-id-for-entry)
|
||||
|
||||
;; Call the function
|
||||
(org-roam-capture--create-id-for-entry)
|
||||
|
||||
;; Verify ID was set and advice removed
|
||||
(expect entry-id :to-equal "test-id-123")
|
||||
(expect (advice-member-p #'org-roam-capture--create-id-for-entry
|
||||
#'org-capture-place-entry)
|
||||
:to-be nil)))
|
||||
|
||||
(it "org-roam-capture--set-target-entry-p-a sets and removes advice"
|
||||
(cl-letf* ((captured-value nil)
|
||||
((symbol-function 'org-capture-put)
|
||||
(lambda (prop val)
|
||||
(when (eq prop :target-entry-p)
|
||||
(setq captured-value val))))
|
||||
((symbol-function 'org-roam-capture--get)
|
||||
(lambda (prop)
|
||||
(if (eq prop :target-entry-p)
|
||||
t
|
||||
nil))))
|
||||
|
||||
;; Add the advice
|
||||
(advice-add #'org-capture-place-template :before #'org-roam-capture--set-target-entry-p-a)
|
||||
|
||||
;; Call the function
|
||||
(org-roam-capture--set-target-entry-p-a nil)
|
||||
|
||||
;; Verify value was set and advice removed
|
||||
(expect captured-value :to-be t)
|
||||
(expect (advice-member-p #'org-roam-capture--set-target-entry-p-a
|
||||
#'org-capture-place-template)
|
||||
:to-be nil)))
|
||||
|
||||
(it "org-roam-capture-run-new-node-hook-a runs hook when new node"
|
||||
(let ((hook-ran nil))
|
||||
(cl-letf* (((symbol-function 'org-roam-capture--get)
|
||||
(lambda (prop)
|
||||
(if (eq prop :new-node-p)
|
||||
t
|
||||
nil))))
|
||||
|
||||
;; Add test hook
|
||||
(add-hook 'org-roam-capture-new-node-hook
|
||||
(lambda () (setq hook-ran t)))
|
||||
|
||||
;; Add the advice
|
||||
(advice-add #'org-capture-place-template :after #'org-roam-capture-run-new-node-hook-a)
|
||||
|
||||
;; Call the function
|
||||
(org-roam-capture-run-new-node-hook-a nil)
|
||||
|
||||
;; Verify hook ran
|
||||
(expect hook-ran :to-be t)
|
||||
|
||||
;; Clean up
|
||||
(remove-hook 'org-roam-capture-new-node-hook
|
||||
(lambda () (setq hook-ran t)))))))
|
||||
|
||||
(describe "org-roam-capture target-entry-p detection"
|
||||
(it "detects entry target for file+olp"
|
||||
(let* ((temp-dir (make-temp-file "org-roam-test" t))
|
||||
(test-file (expand-file-name "test-olp.org" temp-dir))
|
||||
(org-roam-directory temp-dir)
|
||||
(org-roam-capture--node (org-roam-node-create :id (org-id-new)))
|
||||
(org-roam-capture--info (make-hash-table :test 'equal)))
|
||||
(unwind-protect
|
||||
(progn
|
||||
(with-temp-file test-file
|
||||
(insert "* Level 1\n** Level 2\n"))
|
||||
|
||||
(cl-letf* (((symbol-function 'org-roam-capture--get-target)
|
||||
(lambda () `(file+olp ,test-file ("Level 1" "Level 2"))))
|
||||
((symbol-function 'org-capture-get)
|
||||
(lambda (prop) nil)))
|
||||
|
||||
(with-current-buffer (find-file-noselect test-file)
|
||||
(org-roam-capture--setup-target-location)
|
||||
(expect (org-roam-capture--get :target-entry-p) :to-be t))))
|
||||
(delete-directory temp-dir t))))
|
||||
|
||||
(it "detects non-entry target for file"
|
||||
(let* ((temp-dir (make-temp-file "org-roam-test" t))
|
||||
(test-file (expand-file-name "test-file.org" temp-dir))
|
||||
(org-roam-directory temp-dir)
|
||||
(org-roam-capture--node (org-roam-node-create :id (org-id-new)))
|
||||
(org-roam-capture--info (make-hash-table :test 'equal)))
|
||||
(unwind-protect
|
||||
(progn
|
||||
(with-temp-file test-file
|
||||
(insert "#+TITLE: Test\n"))
|
||||
|
||||
(cl-letf* (((symbol-function 'org-roam-capture--get-target)
|
||||
(lambda () `(file ,test-file)))
|
||||
((symbol-function 'org-capture-get)
|
||||
(lambda (prop) nil)))
|
||||
|
||||
(with-current-buffer (find-file-noselect test-file)
|
||||
(org-roam-capture--setup-target-location)
|
||||
(expect (org-roam-capture--get :target-entry-p) :to-be nil))))
|
||||
(delete-directory temp-dir t)))))
|
||||
|
||||
(describe "org-roam-capture plain type ordering"
|
||||
:var ((temp-dir) (org-roam-directory) (org-roam-db-location))
|
||||
|
||||
(before-each
|
||||
(setq temp-dir (make-temp-file "org-roam-test" t))
|
||||
(setq org-roam-directory temp-dir)
|
||||
(setq org-roam-db-location (expand-file-name "org-roam.db" temp-dir))
|
||||
(org-roam-db-sync))
|
||||
|
||||
(after-each
|
||||
(delete-directory temp-dir t))
|
||||
|
||||
(it "places properties drawer before captured content for plain type with file target"
|
||||
(let* ((test-file (expand-file-name "test-plain-file.org" temp-dir))
|
||||
(test-content "Test plain :target file")
|
||||
(node (org-roam-node-create :title "Test Plain"))
|
||||
(org-roam-capture--node node)
|
||||
(org-roam-capture--info (make-hash-table :test 'equal)))
|
||||
|
||||
;; Call the setup directly to simulate capture without user interaction
|
||||
(cl-letf* (((symbol-function 'org-capture-get)
|
||||
(lambda (prop)
|
||||
(pcase prop
|
||||
(:type 'plain)
|
||||
(:target-file test-file)
|
||||
(_ nil))))
|
||||
((symbol-function 'org-roam-capture--get-target)
|
||||
(lambda () `(file ,test-file))))
|
||||
|
||||
;; Run the setup and insert content
|
||||
(with-current-buffer (find-file-noselect test-file)
|
||||
(org-roam-capture--setup-target-location)
|
||||
(org-roam-capture--adjust-point-for-capture-type)
|
||||
(insert test-content)
|
||||
(save-buffer)))
|
||||
|
||||
;; Read the created file and check its structure
|
||||
(with-temp-buffer
|
||||
(insert-file-contents test-file)
|
||||
(let ((buffer-content (buffer-string)))
|
||||
|
||||
;; The expected format is:
|
||||
;; :PROPERTIES:
|
||||
;; :ID: some-id
|
||||
;; :END:
|
||||
;; Test plain :target file
|
||||
|
||||
;; Check that properties come first
|
||||
(expect buffer-content
|
||||
:to-match
|
||||
(rx bol ":PROPERTIES:"))
|
||||
|
||||
;; Verify ordering: properties, then content
|
||||
(let ((props-pos (string-match ":PROPERTIES:" buffer-content))
|
||||
(end-pos (string-match ":END:" buffer-content))
|
||||
(content-pos (string-match (regexp-quote test-content) buffer-content)))
|
||||
|
||||
(expect props-pos :to-be 0)
|
||||
(expect end-pos :not :to-be nil)
|
||||
(expect end-pos :to-be-greater-than props-pos)
|
||||
(expect content-pos :not :to-be nil)
|
||||
(expect content-pos :to-be-greater-than end-pos))))))
|
||||
|
||||
(it "correctly orders buffer elements for plain type with file+head target"
|
||||
(let* ((test-file (expand-file-name "test-plain-file-head.org" temp-dir))
|
||||
(test-content "Test plain :target file+head")
|
||||
(node (org-roam-node-create :title "plain file+head"))
|
||||
(org-roam-capture--node node)
|
||||
(org-roam-capture--info (make-hash-table :test 'equal)))
|
||||
|
||||
;; Populate capture info with title for template expansion
|
||||
(puthash :title "plain file+head" org-roam-capture--info)
|
||||
|
||||
;; Call the setup directly to simulate capture without user interaction
|
||||
(cl-letf* (((symbol-function 'org-capture-get)
|
||||
(lambda (prop)
|
||||
(pcase prop
|
||||
(:type 'plain)
|
||||
(:target-file test-file)
|
||||
(_ nil))))
|
||||
((symbol-function 'org-roam-capture--get-target)
|
||||
(lambda () `(file+head ,test-file "#+title: ${title}\n"))))
|
||||
|
||||
;; Run the setup and insert content
|
||||
(with-current-buffer (find-file-noselect test-file)
|
||||
(org-roam-capture--setup-target-location)
|
||||
(org-roam-capture--adjust-point-for-capture-type)
|
||||
(insert test-content)
|
||||
(save-buffer)))
|
||||
|
||||
;; Read the created file and check its structure
|
||||
(with-temp-buffer
|
||||
(insert-file-contents test-file)
|
||||
(let ((buffer-content (buffer-string)))
|
||||
|
||||
;; The actual format according to org-mode property syntax is:
|
||||
;; :PROPERTIES:
|
||||
;; :ID: some-id
|
||||
;; :END:
|
||||
;; #+title: plain file+head
|
||||
;; Test plain :target file+head
|
||||
;;
|
||||
;; This is correct - buffer-level properties must be at the top
|
||||
|
||||
;; Check that properties come first
|
||||
(expect buffer-content
|
||||
:to-match
|
||||
(rx bol ":PROPERTIES:"))
|
||||
|
||||
;; Verify ordering: properties are at the top
|
||||
(let ((props-pos (string-match ":PROPERTIES:" buffer-content))
|
||||
(end-pos (string-match ":END:" buffer-content)))
|
||||
|
||||
;; Properties drawer should be first
|
||||
(expect props-pos :to-be 0)
|
||||
(expect end-pos :not :to-be nil)
|
||||
(expect end-pos :to-be-greater-than props-pos))))))
|
||||
|
||||
(it "tests org-roam-capture--adjust-point-for-capture-type behavior"
|
||||
;; Simple test to verify the fix for assertion error
|
||||
(with-temp-buffer
|
||||
(org-mode)
|
||||
(insert "#+title: Test\n")
|
||||
(goto-char (point-max))
|
||||
|
||||
;; Mock org-capture-get to return plain type
|
||||
(cl-letf (((symbol-function 'org-capture-get)
|
||||
(lambda (prop) (when (eq prop :type) 'plain))))
|
||||
|
||||
;; Document current state that previously caused assertion error
|
||||
(let ((point-before (point))
|
||||
(at-heading-before (org-at-heading-p)))
|
||||
;; This should no longer trigger assertion error with our fix
|
||||
(org-roam-capture--adjust-point-for-capture-type)
|
||||
(expect point-before :to-be-greater-than 1)
|
||||
(expect at-heading-before :to-be nil))))))
|
||||
|
||||
(provide 'test-org-roam-capture)
|
||||
|
||||
;;; test-org-roam-capture.el ends here
|
||||
|
56
tests/test-org-roam-link-replace.el
Normal file
56
tests/test-org-roam-link-replace.el
Normal file
@@ -0,0 +1,56 @@
|
||||
;;; test-org-roam-link-replace.el --- Tests for Org-roam link replacement -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2025
|
||||
|
||||
;; Package-Requires: ((buttercup))
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
;; Tests for commits fc86387 and 89dfaef - link replacement optimization
|
||||
;;; Code:
|
||||
|
||||
(require 'buttercup)
|
||||
(require 'org-roam)
|
||||
(require 'org-roam-node)
|
||||
|
||||
(describe "org-roam-link-replace-all optimization"
|
||||
(before-all
|
||||
(setq org-roam-directory (expand-file-name "tests/roam-files")
|
||||
org-roam-db-location (expand-file-name "org-roam.db" temporary-file-directory))
|
||||
(org-roam-db-sync))
|
||||
|
||||
(after-all
|
||||
(org-roam-db--close)
|
||||
(delete-file org-roam-db-location))
|
||||
|
||||
(it "only processes roam: links, not other bracket links"
|
||||
(with-temp-buffer
|
||||
(org-mode)
|
||||
(insert "[[file:test.org][File]]\n[[roam:Foo]]\n[[https://example.com][Web]]")
|
||||
(let ((replace-count 0)
|
||||
(original-fn (symbol-function 'org-roam-link-replace-at-point)))
|
||||
;; Wrap the original function to count calls
|
||||
(cl-letf (((symbol-function 'org-roam-link-replace-at-point)
|
||||
(lambda ()
|
||||
(cl-incf replace-count)
|
||||
(funcall original-fn))))
|
||||
(org-roam-link-replace-all)
|
||||
;; Should only be called once, for the roam: link
|
||||
(expect replace-count :to-equal 1)
|
||||
(expect (buffer-string) :to-match "\\[\\[id:.*\\]\\[Foo\\]\\]"))))))
|
||||
|
||||
(provide 'test-org-roam-link-replace)
|
||||
|
||||
;;; test-org-roam-link-replace.el ends here
|
@@ -77,10 +77,22 @@
|
||||
(cd root-directory))
|
||||
|
||||
(it "demotes an entire org buffer"
|
||||
(find-file "tests/roam-files/demoteable.org" nil)
|
||||
(org-roam-demote-entire-buffer)
|
||||
(expect (buffer-substring-no-properties (point) (point-max))
|
||||
:to-equal "* Demoteable\n:PROPERTIES:\n:ID: 97bf31cf-dfee-45d8-87a5-2ae0dabc4734\n:END:\n\n** Demoteable h1\n\n*** Demoteable child\n")))
|
||||
(let* ((test-file "tests/roam-files/demoteable.org")
|
||||
(buf (find-file-noselect test-file))
|
||||
;; Store the original content before any modifications
|
||||
(original-content (with-current-buffer buf
|
||||
(buffer-substring-no-properties (point-min) (point-max)))))
|
||||
(unwind-protect
|
||||
(with-current-buffer buf
|
||||
(org-roam-demote-entire-buffer)
|
||||
(expect (buffer-substring-no-properties (point) (point-max))
|
||||
:to-equal "* Demoteable\n:PROPERTIES:\n:ID: 97bf31cf-dfee-45d8-87a5-2ae0dabc4734\n:END:\n\n** Demoteable h1\n\n*** Demoteable child\n"))
|
||||
;; Always restore the original content
|
||||
(with-current-buffer buf
|
||||
(erase-buffer)
|
||||
(insert original-content)
|
||||
(save-buffer)
|
||||
(kill-buffer buf))))))
|
||||
|
||||
(describe "org-roam--h1-count"
|
||||
(after-each
|
||||
|
Reference in New Issue
Block a user