| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609 | ;;; 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:** bContents*** <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:** bContents*** <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:** bContents*** <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.2some 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 1Text 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_srcText 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 1Text 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 1Text<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 headingFolded 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
 |