|
@@ -0,0 +1,609 @@
|
|
|
+;;; test-org.el --- tests for org.el
|
|
|
+
|
|
|
+;; Authors: Ihor Radchenko
|
|
|
+
|
|
|
+;; This file is not part of GNU Emacs.
|
|
|
+
|
|
|
+;; 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/>.
|
|
|
+
|
|
|
+;; Org folding tests.
|
|
|
+
|
|
|
+;;; Code:
|
|
|
+
|
|
|
+(eval-and-compile (require 'cl-lib))
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+(ert-deftest test-org-fold/hide-drawer-toggle ()
|
|
|
+ "Test `org-fold-hide-drawer-toggle' specifications."
|
|
|
+ ;; Error when not at a drawer.
|
|
|
+ (should-error
|
|
|
+ (org-test-with-temp-text ":fake-drawer:\ncontents"
|
|
|
+ (org-fold-hide-drawer-toggle 'off)
|
|
|
+ (get-char-property (line-end-position) 'invisible)))
|
|
|
+ (should-error
|
|
|
+ (org-test-with-temp-text
|
|
|
+ "#+begin_example\n<point>:D:\nc\n:END:\n#+end_example"
|
|
|
+ (org-fold-hide-drawer-toggle t)))
|
|
|
+ ;; Hide drawer.
|
|
|
+ (should
|
|
|
+ (org-test-with-temp-text ":drawer:\ncontents\n:end:"
|
|
|
+ (org-fold-show-all)
|
|
|
+ (org-fold-hide-drawer-toggle)
|
|
|
+ (get-char-property (line-end-position) 'invisible)))
|
|
|
+ ;; Show drawer unconditionally when optional argument is `off'.
|
|
|
+ (should-not
|
|
|
+ (org-test-with-temp-text ":drawer:\ncontents\n:end:"
|
|
|
+ (org-fold-hide-drawer-toggle)
|
|
|
+ (org-fold-hide-drawer-toggle 'off)
|
|
|
+ (get-char-property (line-end-position) 'invisible)))
|
|
|
+ ;; Hide drawer unconditionally when optional argument is non-nil.
|
|
|
+ (should
|
|
|
+ (org-test-with-temp-text ":drawer:\ncontents\n:end:"
|
|
|
+ (org-fold-hide-drawer-toggle t)
|
|
|
+ (get-char-property (line-end-position) 'invisible)))
|
|
|
+ ;; Do not hide drawer when called from final blank lines.
|
|
|
+ (should-not
|
|
|
+ (org-test-with-temp-text ":drawer:\ncontents\n:end:\n\n<point>"
|
|
|
+ (org-fold-show-all)
|
|
|
+ (org-fold-hide-drawer-toggle)
|
|
|
+ (goto-char (point-min))
|
|
|
+ (get-char-property (line-end-position) 'invisible)))
|
|
|
+ ;; Don't leave point in an invisible part of the buffer when hiding
|
|
|
+ ;; a drawer away.
|
|
|
+ (should-not
|
|
|
+ (org-test-with-temp-text ":drawer:\ncontents\n<point>:end:"
|
|
|
+ (org-fold-hide-drawer-toggle)
|
|
|
+ (get-char-property (point) 'invisible))))
|
|
|
+
|
|
|
+(ert-deftest test-org/hide-block-toggle ()
|
|
|
+ "Test `org-fold-hide-block-toggle' specifications."
|
|
|
+ ;; Error when not at a block.
|
|
|
+ (should-error
|
|
|
+ (org-test-with-temp-text "#+BEGIN_QUOTE\ncontents"
|
|
|
+ (org-fold-hide-block-toggle 'off)
|
|
|
+ (get-char-property (line-end-position) 'invisible)))
|
|
|
+ ;; Hide block.
|
|
|
+ (should
|
|
|
+ (org-test-with-temp-text "#+BEGIN_CENTER\ncontents\n#+END_CENTER"
|
|
|
+ (org-fold-hide-block-toggle)
|
|
|
+ (get-char-property (line-end-position) 'invisible)))
|
|
|
+ (should
|
|
|
+ (org-test-with-temp-text "#+BEGIN_EXAMPLE\ncontents\n#+END_EXAMPLE"
|
|
|
+ (org-fold-hide-block-toggle)
|
|
|
+ (get-char-property (line-end-position) 'invisible)))
|
|
|
+ ;; Show block unconditionally when optional argument is `off'.
|
|
|
+ (should-not
|
|
|
+ (org-test-with-temp-text "#+BEGIN_QUOTE\ncontents\n#+END_QUOTE"
|
|
|
+ (org-fold-hide-block-toggle)
|
|
|
+ (org-fold-hide-block-toggle 'off)
|
|
|
+ (get-char-property (line-end-position) 'invisible)))
|
|
|
+ (should-not
|
|
|
+ (org-test-with-temp-text "#+BEGIN_QUOTE\ncontents\n#+END_QUOTE"
|
|
|
+ (org-fold-hide-block-toggle 'off)
|
|
|
+ (get-char-property (line-end-position) 'invisible)))
|
|
|
+ ;; Hide block unconditionally when optional argument is non-nil.
|
|
|
+ (should
|
|
|
+ (org-test-with-temp-text "#+BEGIN_QUOTE\ncontents\n#+END_QUOTE"
|
|
|
+ (org-fold-hide-block-toggle t)
|
|
|
+ (get-char-property (line-end-position) 'invisible)))
|
|
|
+ (should
|
|
|
+ (org-test-with-temp-text "#+BEGIN_QUOTE\ncontents\n#+END_QUOTE"
|
|
|
+ (org-fold-hide-block-toggle)
|
|
|
+ (org-fold-hide-block-toggle t)
|
|
|
+ (get-char-property (line-end-position) 'invisible)))
|
|
|
+ ;; Do not hide block when called from final blank lines.
|
|
|
+ (should-not
|
|
|
+ (org-test-with-temp-text "#+BEGIN_QUOTE\ncontents\n#+END_QUOTE\n\n<point>"
|
|
|
+ (org-fold-hide-block-toggle)
|
|
|
+ (goto-char (point-min))
|
|
|
+ (get-char-property (line-end-position) 'invisible)))
|
|
|
+ ;; Don't leave point in an invisible part of the buffer when hiding
|
|
|
+ ;; a block away.
|
|
|
+ (should-not
|
|
|
+ (org-test-with-temp-text "#+BEGIN_QUOTE\ncontents\n<point>#+END_QUOTE"
|
|
|
+ (org-fold-hide-block-toggle)
|
|
|
+ (get-char-property (point) 'invisible))))
|
|
|
+
|
|
|
+(ert-deftest test-org-fold/hide-block-toggle-maybe ()
|
|
|
+ "Test `org-fold-hide-block-toggle' specifications."
|
|
|
+ (should
|
|
|
+ (org-test-with-temp-text "#+BEGIN: dynamic\nContents\n#+END:"
|
|
|
+ (org-hide-block-toggle)))
|
|
|
+ (should-error
|
|
|
+ (org-test-with-temp-text "Paragraph" (org-hide-block-toggle))))
|
|
|
+
|
|
|
+(ert-deftest test-org-fold/show-set-visibility ()
|
|
|
+ "Test `org-fold-show-set-visibility' specifications."
|
|
|
+ ;; Do not throw an error before first heading.
|
|
|
+ (should
|
|
|
+ (org-test-with-temp-text "Preamble\n* Headline"
|
|
|
+ (org-fold-show-set-visibility 'tree)
|
|
|
+ t))
|
|
|
+ ;; Test all visibility spans, both on headline and in entry.
|
|
|
+ (let ((list-visible-lines
|
|
|
+ (lambda (state headerp)
|
|
|
+ (org-test-with-temp-text "* Grandmother (0)
|
|
|
+** Uncle (1)
|
|
|
+*** Heir (2)
|
|
|
+** Father (3)
|
|
|
+ Ancestor text (4)
|
|
|
+*** Sister (5)
|
|
|
+ Sibling text (6)
|
|
|
+*** Self (7)
|
|
|
+ Match (8)
|
|
|
+**** First born (9)
|
|
|
+ Child text (10)
|
|
|
+**** The other child (11)
|
|
|
+*** Brother (12)
|
|
|
+** Aunt (13)
|
|
|
+"
|
|
|
+ (org-cycle t)
|
|
|
+ (search-forward (if headerp "Self" "Match"))
|
|
|
+ (org-fold-show-set-visibility state)
|
|
|
+ (goto-char (point-min))
|
|
|
+ (let (result (line 0))
|
|
|
+ (while (not (eobp))
|
|
|
+ (unless (org-invisible-p2) (push line result))
|
|
|
+ (cl-incf line)
|
|
|
+ (forward-line))
|
|
|
+ (nreverse result))))))
|
|
|
+ (should (equal '(0 7) (funcall list-visible-lines 'minimal t)))
|
|
|
+ (should (equal '(0 7 8) (funcall list-visible-lines 'minimal nil)))
|
|
|
+ (should (equal '(0 7 8 9) (funcall list-visible-lines 'local t)))
|
|
|
+ (should (equal '(0 7 8 9) (funcall list-visible-lines 'local nil)))
|
|
|
+ (should (equal '(0 3 7) (funcall list-visible-lines 'ancestors t)))
|
|
|
+ (should (equal '(0 3 7 8) (funcall list-visible-lines 'ancestors nil)))
|
|
|
+ (should (equal '(0 3 7 8 9 10 11)
|
|
|
+ (funcall list-visible-lines 'ancestors-full t)))
|
|
|
+ (should (equal '(0 3 7 8 9 10 11)
|
|
|
+ (funcall list-visible-lines 'ancestors-full nil)))
|
|
|
+ (should (equal '(0 3 5 7 12) (funcall list-visible-lines 'lineage t)))
|
|
|
+ (should (equal '(0 3 5 7 8 9 12) (funcall list-visible-lines 'lineage nil)))
|
|
|
+ (should (equal '(0 1 3 5 7 12 13) (funcall list-visible-lines 'tree t)))
|
|
|
+ (should (equal '(0 1 3 5 7 8 9 11 12 13)
|
|
|
+ (funcall list-visible-lines 'tree nil)))
|
|
|
+ (should (equal '(0 1 3 4 5 7 12 13)
|
|
|
+ (funcall list-visible-lines 'canonical t)))
|
|
|
+ (should (equal '(0 1 3 4 5 7 8 9 11 12 13)
|
|
|
+ (funcall list-visible-lines 'canonical nil))))
|
|
|
+ ;; When point is hidden in a drawer or a block, make sure to make it
|
|
|
+ ;; visible.
|
|
|
+ (should-not
|
|
|
+ (org-test-with-temp-text "#+BEGIN_QUOTE\nText\n#+END_QUOTE"
|
|
|
+ (org-fold-hide-block-toggle)
|
|
|
+ (search-forward "Text")
|
|
|
+ (org-fold-show-set-visibility 'minimal)
|
|
|
+ (org-invisible-p2)))
|
|
|
+ (should-not
|
|
|
+ (org-test-with-temp-text ":DRAWER:\nText\n:END:"
|
|
|
+ (org-fold-hide-drawer-toggle)
|
|
|
+ (search-forward "Text")
|
|
|
+ (org-fold-show-set-visibility 'minimal)
|
|
|
+ (org-invisible-p2)))
|
|
|
+ (should-not
|
|
|
+ (org-test-with-temp-text
|
|
|
+ "#+BEGIN_QUOTE\n<point>:DRAWER:\nText\n:END:\n#+END_QUOTE"
|
|
|
+ (org-fold-hide-drawer-toggle)
|
|
|
+ (forward-line -1)
|
|
|
+ (org-fold-hide-block-toggle)
|
|
|
+ (search-forward "Text")
|
|
|
+ (org-fold-show-set-visibility 'minimal)
|
|
|
+ (org-invisible-p2))))
|
|
|
+
|
|
|
+(ert-deftest test-org-fold/copy-visible ()
|
|
|
+ "Test `org-copy-visible' specifications."
|
|
|
+ ;;`org-unfontify-region', which is wired up to
|
|
|
+ ;; `font-lock-unfontify-region-function', removes the invisible text
|
|
|
+ ;; property, among other things.
|
|
|
+ (cl-letf (((symbol-function 'org-unfontify-region) #'ignore))
|
|
|
+ (should
|
|
|
+ (equal "Foo"
|
|
|
+ (org-test-with-temp-text "Foo"
|
|
|
+ (let ((kill-ring nil))
|
|
|
+ (org-copy-visible (point-min) (point-max))
|
|
|
+ (current-kill 0 t)))))
|
|
|
+ ;; Skip invisible characters by text property.
|
|
|
+ (should
|
|
|
+ (equal "Foo"
|
|
|
+ (org-test-with-temp-text #("F<hidden>oo" 1 9 (invisible t))
|
|
|
+ (let ((kill-ring nil))
|
|
|
+ (org-copy-visible (point-min) (point-max))
|
|
|
+ (current-kill 0 t)))))
|
|
|
+ ;; Skip invisible characters by overlay.
|
|
|
+ (should
|
|
|
+ (equal "Foo"
|
|
|
+ (org-test-with-temp-text "F<hidden>oo"
|
|
|
+ (let ((o (make-overlay 2 10)))
|
|
|
+ (overlay-put o 'invisible t))
|
|
|
+ (let ((kill-ring nil))
|
|
|
+ (org-copy-visible (point-min) (point-max))
|
|
|
+ (current-kill 0 t)))))
|
|
|
+ ;; Handle invisible characters at the beginning and the end of the
|
|
|
+ ;; buffer.
|
|
|
+ (should
|
|
|
+ (equal "Foo"
|
|
|
+ (org-test-with-temp-text #("<hidden>Foo" 0 8 (invisible t))
|
|
|
+ (let ((kill-ring nil))
|
|
|
+ (org-copy-visible (point-min) (point-max))
|
|
|
+ (current-kill 0 t)))))
|
|
|
+ (should
|
|
|
+ (equal "Foo"
|
|
|
+ (org-test-with-temp-text #("Foo<hidden>" 3 11 (invisible t))
|
|
|
+ (let ((kill-ring nil))
|
|
|
+ (org-copy-visible (point-min) (point-max))
|
|
|
+ (current-kill 0 t)))))
|
|
|
+ ;; Handle multiple visible parts.
|
|
|
+ (should
|
|
|
+ (equal "abc"
|
|
|
+ (org-test-with-temp-text
|
|
|
+ #("aXbXc" 1 2 (invisible t) 3 4 (invisible t))
|
|
|
+ (let ((kill-ring nil))
|
|
|
+ (org-copy-visible (point-min) (point-max))
|
|
|
+ (current-kill 0 t)))))
|
|
|
+ ;; Handle adjacent invisible parts.
|
|
|
+ (should
|
|
|
+ (equal "ab"
|
|
|
+ (org-test-with-temp-text
|
|
|
+ #("aXXb" 1 2 (invisible t) 2 3 (invisible org-link))
|
|
|
+ (let ((kill-ring nil))
|
|
|
+ (org-copy-visible (point-min) (point-max))
|
|
|
+ (current-kill 0 t)))))
|
|
|
+ ;; Copies text based on what's actually visible, as defined by
|
|
|
+ ;; `buffer-invisibility-spec'.
|
|
|
+ (should
|
|
|
+ (equal "aYb"
|
|
|
+ (org-test-with-temp-text
|
|
|
+ #("aXYb"
|
|
|
+ 1 2 (invisible t)
|
|
|
+ 2 3 (invisible org-test-copy-visible))
|
|
|
+ (let ((kill-ring nil))
|
|
|
+ (org-copy-visible (point-min) (point-max))
|
|
|
+ (current-kill 0 t)))))))
|
|
|
+
|
|
|
+(ert-deftest test-org-fold/set-visibility-according-to-property ()
|
|
|
+ "Test `org-set-visibility-according-to-property' specifications."
|
|
|
+ ;; "folded" state.
|
|
|
+ (should
|
|
|
+ (org-test-with-temp-text
|
|
|
+ "
|
|
|
+* a
|
|
|
+:PROPERTIES:
|
|
|
+:VISIBILITY: folded
|
|
|
+:END:
|
|
|
+** <point>b"
|
|
|
+ (org-set-visibility-according-to-property)
|
|
|
+ (invisible-p (point))))
|
|
|
+ ;; "children" state.
|
|
|
+ (should
|
|
|
+ (org-test-with-temp-text
|
|
|
+ "
|
|
|
+* a
|
|
|
+:PROPERTIES:
|
|
|
+:VISIBILITY: children
|
|
|
+:END:
|
|
|
+** b
|
|
|
+<point>Contents
|
|
|
+** c"
|
|
|
+ (org-set-visibility-according-to-property)
|
|
|
+ (invisible-p (point))))
|
|
|
+ (should
|
|
|
+ (org-test-with-temp-text
|
|
|
+ "
|
|
|
+* a
|
|
|
+:PROPERTIES:
|
|
|
+:VISIBILITY: children
|
|
|
+:END:
|
|
|
+** b
|
|
|
+Contents
|
|
|
+*** <point>c"
|
|
|
+ (org-set-visibility-according-to-property)
|
|
|
+ (invisible-p (point))))
|
|
|
+ ;; "content" state.
|
|
|
+ (should
|
|
|
+ (org-test-with-temp-text
|
|
|
+ "
|
|
|
+* a
|
|
|
+:PROPERTIES:
|
|
|
+:VISIBILITY: content
|
|
|
+:END:
|
|
|
+** b
|
|
|
+<point>Contents
|
|
|
+*** c"
|
|
|
+ (org-set-visibility-according-to-property)
|
|
|
+ (invisible-p (point))))
|
|
|
+ (should
|
|
|
+ (org-test-with-temp-text
|
|
|
+ "
|
|
|
+* a
|
|
|
+:PROPERTIES:
|
|
|
+:VISIBILITY: content
|
|
|
+:END:
|
|
|
+** b
|
|
|
+Contents
|
|
|
+*** <point>c"
|
|
|
+ (org-set-visibility-according-to-property)
|
|
|
+ (not (invisible-p (point)))))
|
|
|
+ ;; "showall" state.
|
|
|
+ (should
|
|
|
+ (org-test-with-temp-text
|
|
|
+ "
|
|
|
+* a
|
|
|
+:PROPERTIES:
|
|
|
+:VISIBILITY: showall
|
|
|
+:END:
|
|
|
+** b
|
|
|
+<point>Contents
|
|
|
+*** c"
|
|
|
+ (org-set-visibility-according-to-property)
|
|
|
+ (not (invisible-p (point)))))
|
|
|
+ (should
|
|
|
+ (org-test-with-temp-text
|
|
|
+ "
|
|
|
+* a
|
|
|
+:PROPERTIES:
|
|
|
+:VISIBILITY: showall
|
|
|
+:END:
|
|
|
+** b
|
|
|
+Contents
|
|
|
+*** <point>c"
|
|
|
+ (org-set-visibility-according-to-property)
|
|
|
+ (not (invisible-p (point)))))
|
|
|
+ ;; When VISIBILITY properties are nested, ignore inner ones.
|
|
|
+ (should
|
|
|
+ (org-test-with-temp-text
|
|
|
+ "
|
|
|
+* A
|
|
|
+:PROPERTIES:
|
|
|
+:VISIBILITY: folded
|
|
|
+:END:
|
|
|
+** <point>B
|
|
|
+:PROPERTIES:
|
|
|
+:VISIBILITY: folded
|
|
|
+:END:"
|
|
|
+ (org-set-visibility-according-to-property)
|
|
|
+ (invisible-p (point)))))
|
|
|
+
|
|
|
+(ert-deftest test-org-fold/visibility-show-branches ()
|
|
|
+ "Test visibility of inline archived subtrees."
|
|
|
+ (org-test-with-temp-text
|
|
|
+ "* Foo<point>
|
|
|
+** Bar :ARCHIVE:
|
|
|
+*** Baz
|
|
|
+"
|
|
|
+ (org-kill-note-or-show-branches)
|
|
|
+ (should (org-invisible-p (- (point-max) 2)))))
|
|
|
+
|
|
|
+(ert-deftest test-org-fold/org-cycle-narrowed-subtree ()
|
|
|
+ "Test cycling in narrowed buffer."
|
|
|
+ (org-test-with-temp-text
|
|
|
+ "* Heading 1<point>
|
|
|
+** Child 1.1
|
|
|
+** Child 1.2
|
|
|
+some text
|
|
|
+*** Sub-child 1.2.1
|
|
|
+* Heading 2"
|
|
|
+ (org-overview)
|
|
|
+ (org-narrow-to-subtree)
|
|
|
+ (org-cycle)
|
|
|
+ (re-search-forward "Sub-child")
|
|
|
+ (should (org-invisible-p))))
|
|
|
+
|
|
|
+(ert-deftest test-org-fold/org-fold-reveal-broken-structure ()
|
|
|
+ "Test unfolding broken elements."
|
|
|
+ (let ((org-fold-core-style 'text-properties))
|
|
|
+ (org-test-with-temp-text
|
|
|
+ "<point>* Heading 1
|
|
|
+Text here"
|
|
|
+ (org-overview)
|
|
|
+ (re-search-forward "Text")
|
|
|
+ (should (org-invisible-p))
|
|
|
+ (goto-char 1)
|
|
|
+ (delete-char 1)
|
|
|
+ (re-search-forward "Text")
|
|
|
+ (should-not (org-invisible-p)))
|
|
|
+ (org-test-with-temp-text
|
|
|
+ "* Heading 1
|
|
|
+<point>:PROPERTIES:
|
|
|
+:ID: something
|
|
|
+:END:
|
|
|
+Text here"
|
|
|
+ (org-cycle)
|
|
|
+ (org-fold-hide-drawer-all)
|
|
|
+ (re-search-forward "ID")
|
|
|
+ (should (org-invisible-p))
|
|
|
+ (re-search-backward ":PROPERTIES:")
|
|
|
+ (delete-char 1)
|
|
|
+ (re-search-forward "ID")
|
|
|
+ (should-not (org-invisible-p)))
|
|
|
+ (org-test-with-temp-text
|
|
|
+ "* Heading 1
|
|
|
+<point>:PROPERTIES:
|
|
|
+:ID: something
|
|
|
+:END:
|
|
|
+Text here"
|
|
|
+ (org-cycle)
|
|
|
+ (org-fold-hide-drawer-all)
|
|
|
+ (re-search-forward "ID")
|
|
|
+ (should (org-invisible-p))
|
|
|
+ (re-search-forward ":END:")
|
|
|
+ (delete-char -1)
|
|
|
+ (re-search-backward "ID")
|
|
|
+ (should-not (org-invisible-p)))
|
|
|
+ (org-test-with-temp-text
|
|
|
+ "* Heading 1
|
|
|
+<point>#+begin_src emacs-lisp
|
|
|
+(+ 1 2)
|
|
|
+#+end_src
|
|
|
+Text here"
|
|
|
+ (org-cycle)
|
|
|
+ (org-fold-hide-drawer-all)
|
|
|
+ (re-search-forward "end")
|
|
|
+ (should (org-invisible-p))
|
|
|
+ (delete-char -1)
|
|
|
+ (re-search-backward "2")
|
|
|
+ (should-not (org-invisible-p)))))
|
|
|
+
|
|
|
+(ert-deftest test-org-fold/re-hide-edits-inside-fold ()
|
|
|
+ "Test edits inside folded regions."
|
|
|
+ (org-test-with-temp-text
|
|
|
+ "<point>* Heading 1
|
|
|
+Text here"
|
|
|
+ (org-overview)
|
|
|
+ (org-set-property "TEST" "1")
|
|
|
+ (re-search-forward "TEST")
|
|
|
+ (should (org-invisible-p)))
|
|
|
+ (org-test-with-temp-text
|
|
|
+ "* Heading 1<point>
|
|
|
+Text here"
|
|
|
+ (org-overview)
|
|
|
+ (insert " and extra heading text")
|
|
|
+ (re-search-backward "heading")
|
|
|
+ (should-not (org-invisible-p)))
|
|
|
+ (org-test-with-temp-text
|
|
|
+ "* Heading 1
|
|
|
+Text<point> here"
|
|
|
+ (org-overview)
|
|
|
+ (insert " and extra text")
|
|
|
+ (re-search-backward "extra")
|
|
|
+ (should (org-invisible-p))))
|
|
|
+
|
|
|
+
|
|
|
+(defmacro test-org-fold-with-default-template (&rest body)
|
|
|
+ "Run `org-test-with-temp-text' using default folded template."
|
|
|
+ (declare (indent 0))
|
|
|
+ `(let ((org-link-descriptive t))
|
|
|
+ (org-test-with-temp-text
|
|
|
+ "#+STARTUP: showeverything
|
|
|
+* <point>Folded heading
|
|
|
+Folded Paragraph inside heading.
|
|
|
+* Unfolded heading
|
|
|
+:FOLDED-DRAWER:
|
|
|
+Folded Paragraph inside drawer.
|
|
|
+:END:
|
|
|
+Unfolded Paragraph.
|
|
|
+#+begin_src emacs-lisp
|
|
|
+(message \"Folded block\")
|
|
|
+#+end_src
|
|
|
+[[hiddenlink][link]]
|
|
|
+"
|
|
|
+ (org-cycle)
|
|
|
+ (search-forward "FOLDED-DRAWER")
|
|
|
+ (org-hide-drawer-toggle t)
|
|
|
+ (search-forward "begin_src")
|
|
|
+ (org-hide-block-toggle t)
|
|
|
+ (goto-char 1)
|
|
|
+ ,@body)))
|
|
|
+
|
|
|
+(ert-deftest test-org-fold/org-catch-invisible-edits ()
|
|
|
+ "Test invisible edits handling."
|
|
|
+ ;; Disable delay in `org-fold-check-before-invisible-edit'.
|
|
|
+ (cl-letf (((symbol-function 'sit-for) #'ignore))
|
|
|
+ (dolist (org-fold-core-style '(text-properties overlays))
|
|
|
+ (dolist (org-fold-catch-invisible-edits
|
|
|
+ '(nil error smart show show-and-error))
|
|
|
+ (dolist (kind '(insert delete-backward delete nil))
|
|
|
+ (message "Testing invisible edits: %S:%S:%S"
|
|
|
+ org-fold-core-style
|
|
|
+ org-fold-catch-invisible-edits
|
|
|
+ kind)
|
|
|
+ ;; Edits outside invisible.
|
|
|
+ (test-org-fold-with-default-template
|
|
|
+ (search-forward "Unfolded Paragraph")
|
|
|
+ (message "Outside invisible")
|
|
|
+ (org-fold-check-before-invisible-edit kind)
|
|
|
+ (should-not (org-invisible-p)))
|
|
|
+ ;; Edits inside invisible region.
|
|
|
+ (test-org-fold-with-default-template
|
|
|
+ (dolist (txt '("Folded Paragraph inside heading"
|
|
|
+ "Folded Paragraph inside drawer"
|
|
|
+ "Folded block"))
|
|
|
+ (search-forward txt)
|
|
|
+ (message "Inside invisible %S" txt)
|
|
|
+ (pcase org-fold-catch-invisible-edits
|
|
|
+ (`nil
|
|
|
+ (org-fold-check-before-invisible-edit kind)
|
|
|
+ (should (org-invisible-p)))
|
|
|
+ (`show
|
|
|
+ (org-fold-check-before-invisible-edit kind)
|
|
|
+ (should-not (org-invisible-p)))
|
|
|
+ ((or `smart `show-and-error)
|
|
|
+ (should-error (org-fold-check-before-invisible-edit kind))
|
|
|
+ (should-not (org-invisible-p)))
|
|
|
+ (`error
|
|
|
+ (should-error (org-fold-check-before-invisible-edit kind))
|
|
|
+ (should (org-invisible-p)))))
|
|
|
+ (search-forward "hiddenlink")
|
|
|
+ (message "Inside hidden link")
|
|
|
+ (org-fold-check-before-invisible-edit kind)
|
|
|
+ (should (org-invisible-p)))
|
|
|
+ ;; Edits at the left border.
|
|
|
+ (test-org-fold-with-default-template
|
|
|
+ (dolist (txt '("Folded heading"
|
|
|
+ ":FOLDED-DRAWER:"
|
|
|
+ "#+begin_src emacs-lisp"))
|
|
|
+ (search-forward txt)
|
|
|
+ (message "Left of folded %S" txt)
|
|
|
+ (pcase org-fold-catch-invisible-edits
|
|
|
+ (`nil
|
|
|
+ (org-fold-check-before-invisible-edit kind)
|
|
|
+ (should (org-invisible-p (1+ (point)))))
|
|
|
+ (`show
|
|
|
+ (org-fold-check-before-invisible-edit kind)
|
|
|
+ (should-not (org-invisible-p (1+ (point)))))
|
|
|
+ (`smart
|
|
|
+ (if (memq kind '(insert delete-backward))
|
|
|
+ (org-fold-check-before-invisible-edit kind)
|
|
|
+ (should-error (org-fold-check-before-invisible-edit kind)))
|
|
|
+ (should-not (org-invisible-p (1+ (point)))))
|
|
|
+ (`show-and-error
|
|
|
+ (should-error (org-fold-check-before-invisible-edit kind))
|
|
|
+ (should-not (org-invisible-p (1+ (point)))))
|
|
|
+ (`error
|
|
|
+ (should-error (org-fold-check-before-invisible-edit kind))
|
|
|
+ (should (org-invisible-p (1+ (point)))))))
|
|
|
+ (search-forward "hiddenlink")
|
|
|
+ (search-forward "lin")
|
|
|
+ (message "Left border of ]] in link")
|
|
|
+ (org-fold-check-before-invisible-edit kind)
|
|
|
+ (should (org-invisible-p (1+ (point)))))
|
|
|
+ ;; Edits at the right border.
|
|
|
+ (test-org-fold-with-default-template
|
|
|
+ (dolist (txt '("Folded Paragraph inside heading."
|
|
|
+ ":END:"
|
|
|
+ "#+end_src"))
|
|
|
+ (search-forward txt)
|
|
|
+ (message "After %S" txt)
|
|
|
+ (pcase org-fold-catch-invisible-edits
|
|
|
+ (`nil
|
|
|
+ (org-fold-check-before-invisible-edit kind)
|
|
|
+ (should (org-invisible-p (1- (point)))))
|
|
|
+ (`show
|
|
|
+ (org-fold-check-before-invisible-edit kind)
|
|
|
+ (should-not (org-invisible-p (1- (point)))))
|
|
|
+ ((or `smart `show-and-error)
|
|
|
+ (should-error (org-fold-check-before-invisible-edit kind))
|
|
|
+ (should-not (org-invisible-p (1- (point)))))
|
|
|
+ (`error
|
|
|
+ (should-error (org-fold-check-before-invisible-edit kind))
|
|
|
+ (should (org-invisible-p (1- (point)))))))
|
|
|
+ (search-forward "hiddenlink")
|
|
|
+ (search-forward "link]]")
|
|
|
+ (message "Right border of ]] in link")
|
|
|
+ (org-fold-check-before-invisible-edit kind)
|
|
|
+ (should (org-invisible-p (1- (point))))))))))
|
|
|
+
|
|
|
+(provide 'test-org-fold)
|
|
|
+
|
|
|
+;;; test-org-fold.el ends here
|