|
|
(require 'ert)
|
|
|
(require 'edebug)
|
|
|
(require 'helpful)
|
|
|
(require 'python)
|
|
|
|
|
|
(when noninteractive
|
|
|
(unless find-function-C-source-directory
|
|
|
(let* ((emacs-src-path (f-join default-directory "emacs-25.3" "src")))
|
|
|
(if (f-exists-p emacs-src-path)
|
|
|
(setq find-function-C-source-directory emacs-src-path)
|
|
|
(message "No Emacs source code found at %S, some tests will be skipped. Run ./download_emacs_src.sh"
|
|
|
emacs-src-path))))
|
|
|
|
|
|
(setq jka-compr-verbose nil))
|
|
|
|
|
|
(defvar helpful-test-var nil)
|
|
|
(define-obsolete-variable-alias 'helpful-test-var-obsolete
|
|
|
'helpful-test-var "23.1")
|
|
|
|
|
|
(defun helpful-test-fun-obsolete ()
|
|
|
(declare (obsolete helpful "1.2.3"))
|
|
|
nil)
|
|
|
|
|
|
(defun test-foo ()
|
|
|
"Docstring here."
|
|
|
nil)
|
|
|
|
|
|
(defun test-foo-advised ()
|
|
|
"Docstring here too."
|
|
|
nil)
|
|
|
|
|
|
(autoload 'some-unused-function "somelib.el")
|
|
|
|
|
|
(defadvice test-foo-advised (before test-advice1 activate)
|
|
|
"Placeholder advice 1."
|
|
|
nil)
|
|
|
|
|
|
(defadvice test-foo-advised (after test-advice2 activate)
|
|
|
"Placeholder advice 2."
|
|
|
nil)
|
|
|
|
|
|
(ert-deftest helpful--docstring ()
|
|
|
"Basic docstring fetching."
|
|
|
(should
|
|
|
(equal
|
|
|
(helpful--docstring #'test-foo t)
|
|
|
"Docstring here.")))
|
|
|
|
|
|
(ert-deftest helpful--docstring-symbol ()
|
|
|
"Correctly handle quotes around symbols."
|
|
|
;; We should replace quoted symbols with links, so the punctuation
|
|
|
;; should not be in the output.
|
|
|
(let* ((formatted-docstring (helpful--format-docstring "`message'")))
|
|
|
(should
|
|
|
(equal formatted-docstring "message")))
|
|
|
;; We should handle stray backquotes.
|
|
|
(let* ((formatted-docstring (helpful--format-docstring "`foo `message'")))
|
|
|
(should
|
|
|
(equal formatted-docstring "`foo message")))
|
|
|
;; Handle a missing closing '.
|
|
|
(let* ((formatted-docstring (helpful--format-docstring "`foo")))
|
|
|
(should
|
|
|
(equal formatted-docstring "`foo"))))
|
|
|
|
|
|
(ert-deftest helpful--docstring-unescape ()
|
|
|
"Discard \\=\\= in docstrings."
|
|
|
(let* ((docstring (helpful--docstring #'apply t))
|
|
|
(formatted-docstring (helpful--format-docstring docstring)))
|
|
|
(should
|
|
|
(not (s-contains-p "\\=" formatted-docstring)))))
|
|
|
|
|
|
(ert-deftest helpful--docstring-strings ()
|
|
|
"Double-quoted strings should be treated literally."
|
|
|
;; Ensure backslashes are shown escaped, so the output is a valid string literal.
|
|
|
(let* ((formatted-docstring
|
|
|
(helpful--format-docstring
|
|
|
"hello \"x\\y\" world")))
|
|
|
;; This test will fail in a local Emacs instance that has modified
|
|
|
;; minibuffer keybindings.
|
|
|
(should
|
|
|
(string-equal formatted-docstring "hello \"x\\\\y\" world")))
|
|
|
;; Don't crash on unbalanced doublequotes.
|
|
|
(helpful--format-docstring "hello \" world")
|
|
|
;; Command sequences \\[foo] should be ignored inside doublequotes.
|
|
|
(let* ((formatted-docstring
|
|
|
(helpful--format-docstring
|
|
|
"hello \"\\[foo]\" world")))
|
|
|
;; This test will fail in a local Emacs instance that has modified
|
|
|
;; minibuffer keybindings.
|
|
|
(should
|
|
|
(string-equal formatted-docstring
|
|
|
"hello \"\\\\[foo]\" world"))))
|
|
|
|
|
|
(ert-deftest helpful--docstring-keymap ()
|
|
|
"Handle keymap references in docstrings."
|
|
|
(let* ((formatted-docstring
|
|
|
(helpful--format-docstring
|
|
|
"\\<minibuffer-local-map>\\[next-history-element]")))
|
|
|
;; This test will fail in a local Emacs instance that has modified
|
|
|
;; minibuffer keybindings.
|
|
|
(should
|
|
|
(string-equal formatted-docstring "M-n"))))
|
|
|
|
|
|
(ert-deftest helpful--docstring-keymap-newline ()
|
|
|
"If a keymap reference is on its own line, remove the entire line."
|
|
|
(should
|
|
|
(string-equal
|
|
|
(helpful--format-docstring "Foo.
|
|
|
\\<minibuffer-local-map>
|
|
|
bar")
|
|
|
"Foo.
|
|
|
|
|
|
bar")))
|
|
|
|
|
|
(ert-deftest helpful--docstring-advice ()
|
|
|
"Get the docstring on advised functions."
|
|
|
(should
|
|
|
(equal
|
|
|
(helpful--docstring #'test-foo-advised t)
|
|
|
"Docstring here too.")))
|
|
|
|
|
|
(defun test-foo-no-docstring ()
|
|
|
nil)
|
|
|
|
|
|
(ert-deftest helpful--no-docstring ()
|
|
|
"We should not crash on a function without a docstring."
|
|
|
(should (null (helpful--docstring #'test-foo-no-docstring t))))
|
|
|
|
|
|
(ert-deftest helpful--interactively-defined-fn ()
|
|
|
"We should not crash on a function without source code."
|
|
|
(eval '(defun test-foo-defined-interactively () 42))
|
|
|
(with-temp-buffer
|
|
|
(helpful-function #'test-foo-defined-interactively)
|
|
|
(should (equal (buffer-name) "*helpful function: test-foo-defined-interactively*"))))
|
|
|
|
|
|
(ert-deftest helpful--edebug-fn ()
|
|
|
"We should not crash on a function with edebug enabled."
|
|
|
(let ((edebug-all-forms t)
|
|
|
(edebug-all-defs t))
|
|
|
(with-temp-buffer
|
|
|
(insert "(defun test-foo-edebug () 44)")
|
|
|
(goto-char (point-min))
|
|
|
(cl-letf (((symbol-function #'message)
|
|
|
(lambda (_format-string &rest _args))))
|
|
|
(eval (eval-sexp-add-defvars (edebug-read-top-level-form)) t))))
|
|
|
(helpful-function #'test-foo-edebug))
|
|
|
|
|
|
(defun test-foo-return-arg (s)
|
|
|
"blah blah."
|
|
|
s)
|
|
|
|
|
|
(ert-deftest helpful--edebug-p ()
|
|
|
"Ensure that we don't crash on a function whose body ends with
|
|
|
symbol (not a form)."
|
|
|
(should
|
|
|
(not (helpful--edebug-p #'test-foo-return-arg))))
|
|
|
|
|
|
(defun test-foo-usage-docstring ()
|
|
|
"\n\n(fn &rest ARGS)"
|
|
|
nil)
|
|
|
|
|
|
(ert-deftest helpful--usage-docstring ()
|
|
|
"If a function docstring only has usage, do not return it."
|
|
|
(should (null (helpful--docstring #'test-foo-usage-docstring t))))
|
|
|
|
|
|
(defun test-foo-no-properties ()
|
|
|
nil)
|
|
|
|
|
|
(ert-deftest helpful--primitive-p ()
|
|
|
;; Defined in C.
|
|
|
(should (helpful--primitive-p 'message t))
|
|
|
;; Defined in C, but an alias.
|
|
|
(should (helpful--primitive-p 'not t))
|
|
|
;; Defined in elisp.
|
|
|
(should (not (helpful--primitive-p 'when t))))
|
|
|
|
|
|
(ert-deftest helpful--primitive-p--advised ()
|
|
|
"Ensure we handly advised primitive functions correctly."
|
|
|
;; `rename-buffer' is primitive, but it's advised by uniquify.
|
|
|
(should (helpful--primitive-p 'rename-buffer t)))
|
|
|
|
|
|
(ert-deftest helpful--without-advice ()
|
|
|
"Ensure we remove advice to get the underlying function."
|
|
|
;; Removing the advice on an unadvised function should give us the
|
|
|
;; same function.
|
|
|
(should
|
|
|
(eq (helpful--without-advice #'test-foo)
|
|
|
(indirect-function #'test-foo)))
|
|
|
;; Removing the advice should give us an unadvised function.
|
|
|
(should
|
|
|
(not (helpful--advised-p
|
|
|
(helpful--without-advice #'test-foo-advised)))))
|
|
|
|
|
|
(ert-deftest helpful-callable ()
|
|
|
;; Functions. Also a regression test for #170.
|
|
|
(helpful-callable 'face-attribute)
|
|
|
;; We should not crash when looking at macros.
|
|
|
(helpful-callable 'when)
|
|
|
;; Special forms should work too.
|
|
|
(helpful-callable 'if)
|
|
|
;; Named keyboard macros (strings and vectors).
|
|
|
(fset 'aaa "aaa")
|
|
|
(helpful-callable 'aaa)
|
|
|
(fset 'backspace-return [backspace return])
|
|
|
(helpful-callable 'backspace-return))
|
|
|
|
|
|
(ert-deftest helpful-callable--with-C-source ()
|
|
|
"Smoke test for special forms when we have the Emacs C source loaded."
|
|
|
(skip-unless find-function-C-source-directory)
|
|
|
(helpful-callable 'if))
|
|
|
|
|
|
(ert-deftest helpful--no-symbol-properties ()
|
|
|
"Helpful should handle functions without any symbol properties."
|
|
|
;; Interactively evaluating this file will set edebug properties on
|
|
|
;; test-foo-no-properties, so remove all properties.
|
|
|
(setplist #'test-foo-no-properties nil)
|
|
|
|
|
|
;; This shouldn't throw any errors.
|
|
|
(helpful-function #'test-foo-no-properties))
|
|
|
|
|
|
(ert-deftest helpful--split-first-line ()
|
|
|
;; Don't modify a single line string.
|
|
|
(should
|
|
|
(equal (helpful--split-first-line "foo") "foo"))
|
|
|
;; Don't modify a two-line string if we don't end with .
|
|
|
(should
|
|
|
(equal (helpful--split-first-line "foo\nbar") "foo\nbar"))
|
|
|
;; If the second line is already empty, do nothing.
|
|
|
(should
|
|
|
(equal (helpful--split-first-line "foo.\n\nbar") "foo.\n\nbar"))
|
|
|
;; But if we have a single sentence and no empty line, insert one.
|
|
|
(should
|
|
|
(equal (helpful--split-first-line "foo.\nbar") "foo.\n\nbar")))
|
|
|
|
|
|
(ert-deftest helpful--format-reference ()
|
|
|
(should
|
|
|
(equal
|
|
|
(helpful--format-reference '(def foo) 10 1 123 "/foo/bar.el")
|
|
|
"(def foo ...) 1 reference"))
|
|
|
(should
|
|
|
(equal
|
|
|
(helpful--format-reference '(advice-add 'bar) 10 1 123 "/foo/bar.el")
|
|
|
"(advice-add 'bar ...) 1 reference")))
|
|
|
|
|
|
(ert-deftest helpful--format-docstring ()
|
|
|
"Ensure we handle `foo' formatting correctly."
|
|
|
;; If it's bound, we should link it.
|
|
|
(let* ((formatted (helpful--format-docstring "foo `message'."))
|
|
|
(m-position (s-index-of "m" formatted)))
|
|
|
(should (get-text-property m-position 'button formatted)))
|
|
|
;; If it's not bound, we should not.
|
|
|
(let* ((formatted (helpful--format-docstring "foo `messagexxx'."))
|
|
|
(m-position (s-index-of "m" formatted)))
|
|
|
(should (not (get-text-property m-position 'button formatted)))
|
|
|
;; But we should always remove the backticks.
|
|
|
(should (equal formatted "foo messagexxx.")))
|
|
|
;; Don't require the text between the quotes to be a valid symbol, e.g.
|
|
|
;; support `C-M-\' (found in `vhdl-mode').
|
|
|
(let* ((formatted (helpful--format-docstring "foo `C-M-\\'")))
|
|
|
(should (equal formatted "foo C-M-\\"))))
|
|
|
|
|
|
(ert-deftest helpful--format-docstring-escapes ()
|
|
|
"Ensure we handle escaped quotes correctly."
|
|
|
(let* ((formatted (helpful--format-docstring "foo \\=`message\\='."))
|
|
|
(m-position (s-index-of "m" formatted)))
|
|
|
(should (equal formatted "foo `message'."))
|
|
|
(should (not (get-text-property m-position 'button formatted)))))
|
|
|
|
|
|
(ert-deftest helpful--format-docstring-command-keys ()
|
|
|
"Ensure we propertize references to command key sequences."
|
|
|
;; This test will fail in your current Emacs instance if you've
|
|
|
;; overridden the `set-mark-command' keybinding.
|
|
|
(-let [formatted (helpful--format-docstring "\\[set-mark-command]")]
|
|
|
(should
|
|
|
(string-equal formatted "C-SPC"))
|
|
|
(should
|
|
|
(get-text-property 0 'button formatted)))
|
|
|
;; If we have quotes around a key sequence, we should not propertize
|
|
|
;; it as the button styling will no longer be visible.
|
|
|
(-let [formatted (helpful--format-docstring "`\\[set-mark-command]'")]
|
|
|
(should
|
|
|
(string-equal formatted "C-SPC"))
|
|
|
(should
|
|
|
(eq
|
|
|
(get-text-property 0 'face formatted)
|
|
|
'button))))
|
|
|
|
|
|
(ert-deftest helpful--format-docstring-mode-maps ()
|
|
|
"Ensure we propertize references to keymaps."
|
|
|
(-let [formatted (helpful--format-docstring "\\{python-mode-map}")]
|
|
|
(should
|
|
|
(s-contains-p "run-python" formatted)))
|
|
|
;; Handle non-existent mode maps gracefully.
|
|
|
(-let [formatted (helpful--format-docstring "\\{no-such-mode-map}")]
|
|
|
(should
|
|
|
(s-contains-p "not currently defined" formatted))))
|
|
|
|
|
|
(ert-deftest helpful--format-docstring--info ()
|
|
|
"Ensure we propertize references to the info manual."
|
|
|
;; This is the typical format.
|
|
|
(let* ((formatted (helpful--format-docstring "Info node `(elisp)foo'"))
|
|
|
(paren-position (s-index-of "(" formatted)))
|
|
|
(should
|
|
|
(string-equal formatted "Info node (elisp)foo"))
|
|
|
(should
|
|
|
(get-text-property paren-position 'button formatted)))
|
|
|
;; Some functions, such as `signal', use 'anchor'.
|
|
|
(let* ((formatted (helpful--format-docstring "Info anchor `(elisp)foo'"))
|
|
|
(paren-position (s-index-of "(" formatted)))
|
|
|
(should
|
|
|
(string-equal formatted "Info anchor (elisp)foo"))
|
|
|
(should
|
|
|
(get-text-property paren-position 'button formatted)))
|
|
|
;; Ensure we handle wrapped lines too, e.g. in `org-odt-pixels-per-inch'.
|
|
|
(let* ((formatted (helpful--format-docstring "Info node `(elisp)foo \nbar'"))
|
|
|
(paren-position (s-index-of "(" formatted)))
|
|
|
(should
|
|
|
(string-equal formatted "Info node (elisp)foo \nbar"))
|
|
|
(should
|
|
|
(get-text-property paren-position 'button formatted)))
|
|
|
;; Some docstrings use "info" (lowercase).
|
|
|
(let* ((formatted (helpful--format-docstring "info node `(elisp)foo'"))
|
|
|
(paren-position (s-index-of "(" formatted)))
|
|
|
(should
|
|
|
(string-equal formatted "info node (elisp)foo"))
|
|
|
(should
|
|
|
(get-text-property paren-position 'button formatted)))
|
|
|
;; Some docstrings use angular quotation marks.
|
|
|
(let* ((formatted (helpful--format-docstring "Info node ‘(elisp)foo’"))
|
|
|
(paren-position (s-index-of "(" formatted)))
|
|
|
(should
|
|
|
(string-equal formatted "Info node (elisp)foo"))
|
|
|
(should
|
|
|
(get-text-property paren-position 'button formatted)))
|
|
|
;; If there's no manual information, assume it is part of the Emacs manual.
|
|
|
(let* ((formatted (helpful--format-docstring "Info node ‘foo’"))
|
|
|
(paren-position (s-index-of "(" formatted)))
|
|
|
(should
|
|
|
(string-equal formatted "Info node (emacs)foo"))
|
|
|
(should
|
|
|
(get-text-property paren-position 'button formatted))))
|
|
|
|
|
|
(ert-deftest helpful--format-docstring--url ()
|
|
|
"Ensure we propertize URLs with backticks."
|
|
|
(let* ((formatted (helpful--format-docstring "URL `http://example.com'"))
|
|
|
(url-position (s-index-of "h" formatted)))
|
|
|
(should
|
|
|
(string-equal formatted "URL http://example.com"))
|
|
|
(should
|
|
|
(get-text-property url-position 'button formatted))))
|
|
|
|
|
|
(ert-deftest helpful--format-docstring--bare-url ()
|
|
|
"Ensure we propertize URLs without backticks."
|
|
|
(let* ((formatted (helpful--format-docstring "http://example.com\nbar"))
|
|
|
(url-position (s-index-of "h" formatted)))
|
|
|
(should
|
|
|
(string-equal formatted "http://example.com\nbar"))
|
|
|
(should
|
|
|
(get-text-property url-position 'button formatted))
|
|
|
(should
|
|
|
(equal
|
|
|
(get-text-property url-position 'url formatted)
|
|
|
"http://example.com")))
|
|
|
;; Don't consider trailing punctuation to be part of the URL.
|
|
|
(let* ((formatted (helpful--format-docstring "See http://example.com."))
|
|
|
(url-position (s-index-of "h" formatted)))
|
|
|
(should
|
|
|
(string-equal formatted "See http://example.com."))
|
|
|
(should
|
|
|
(equal
|
|
|
(get-text-property url-position 'url formatted)
|
|
|
"http://example.com")))
|
|
|
;; Format markdown-style links.
|
|
|
(let* ((formatted (helpful--format-docstring "See <http://example.com>."))
|
|
|
(url-position (s-index-of "h" formatted)))
|
|
|
(should
|
|
|
(equal
|
|
|
(get-text-property url-position 'url formatted)
|
|
|
"http://example.com"))))
|
|
|
|
|
|
(ert-deftest helpful--definition-c-vars ()
|
|
|
"Handle definitions of variables in C source code."
|
|
|
(skip-unless find-function-C-source-directory)
|
|
|
(helpful--definition 'default-directory nil))
|
|
|
|
|
|
(ert-deftest helpful--definition-special-form ()
|
|
|
"Ensure we find the position of special forms."
|
|
|
(skip-unless find-function-C-source-directory)
|
|
|
(-let [(buf pos _)
|
|
|
(helpful--definition 'if t)]
|
|
|
(should buf)
|
|
|
(should pos)))
|
|
|
|
|
|
(setq helpful-var-without-defvar 'foo)
|
|
|
|
|
|
(ert-deftest helpful--definition-no-defvar ()
|
|
|
"Ensure we don't crash on calling `helpful--definition' on
|
|
|
variables defined without `defvar'."
|
|
|
(helpful--definition 'helpful-var-without-defvar nil))
|
|
|
|
|
|
(ert-deftest helpful--definition-buffer-opened ()
|
|
|
"Ensure we mark buffers as opened for variables."
|
|
|
(require 'python)
|
|
|
;; This test will fail if you already have python.el.gz open in your
|
|
|
;; Emacs instance.
|
|
|
(skip-unless (null (get-buffer "python.el.gz")))
|
|
|
|
|
|
(-let [(buf pos opened) (helpful--definition 'python-indent-offset nil)]
|
|
|
(should (bufferp buf))
|
|
|
(should opened)))
|
|
|
|
|
|
(ert-deftest helpful--definition-edebug-fn ()
|
|
|
"Ensure we use the position information set by edebug, if present."
|
|
|
;; Test with both edebug enabled and disabled. The edebug property
|
|
|
;; on the symbol varies based on this.
|
|
|
(dolist (edebug-on (list nil t))
|
|
|
(let ((edebug-all-forms edebug-on)
|
|
|
(edebug-all-defs edebug-on))
|
|
|
(with-temp-buffer
|
|
|
(insert "(defun test-foo-edebug-defn () 44)")
|
|
|
(goto-char (point-min))
|
|
|
(cl-letf (((symbol-function #'message)
|
|
|
(lambda (_format-string &rest _args))))
|
|
|
(eval (eval-sexp-add-defvars (edebug-read-top-level-form)) t))
|
|
|
|
|
|
(-let [(buf pos opened) (helpful--definition 'test-foo-edebug-defn t)]
|
|
|
(should buf))))))
|
|
|
|
|
|
(ert-deftest helpful--definition-defstruct ()
|
|
|
"Ensure we find the position of struct functions."
|
|
|
(-let [(buf pos _)
|
|
|
(helpful--definition #'make-ert-test t)]
|
|
|
(should buf)
|
|
|
(should pos)))
|
|
|
|
|
|
(ert-deftest helpful-variable ()
|
|
|
"Smoke test for `helpful-variable'."
|
|
|
(helpful-variable 'tab-width))
|
|
|
|
|
|
(ert-deftest helpful-visit-reference ()
|
|
|
"Smoke test for `helpful-visit-reference'."
|
|
|
(helpful-function 'replace-regexp-in-string)
|
|
|
(goto-char (point-min))
|
|
|
;; Move forward to the first reference.
|
|
|
(while (not (get-text-property (point) 'helpful-pos))
|
|
|
(forward-char 1))
|
|
|
(helpful-visit-reference))
|
|
|
|
|
|
(ert-deftest helpful--signature ()
|
|
|
"Ensure that autoloaded functions are handled gracefully"
|
|
|
(should
|
|
|
(equal (helpful--signature 'some-unused-function)
|
|
|
"(some-unused-function [Arg list not available until function definition is loaded.])")))
|
|
|
|
|
|
(ert-deftest helpful--signature-space ()
|
|
|
"Ensure that symbols with spaces are handled correctly."
|
|
|
(should
|
|
|
(equal (helpful--signature 'helpful-test-fn-with\ space)
|
|
|
"(helpful-test-fn-with\\ space)")))
|
|
|
|
|
|
(ert-deftest helpful--signature--advertised ()
|
|
|
"Ensure that we respect functions that declare `advertised-calling-convention'."
|
|
|
(should
|
|
|
(equal (helpful--signature 'start-process-shell-command)
|
|
|
"(start-process-shell-command NAME BUFFER COMMAND)")))
|
|
|
|
|
|
(ert-deftest helpful-function--single-buffer ()
|
|
|
"Ensure that calling `helpful-buffer' does not leave any extra
|
|
|
buffers lying around."
|
|
|
(let ((initial-buffers (buffer-list))
|
|
|
expected-buffers results-buffer)
|
|
|
(helpful-function #'enable-theme)
|
|
|
(setq results-buffer (get-buffer "*helpful command: enable-theme*"))
|
|
|
(setq expected-buffers
|
|
|
(cons results-buffer
|
|
|
initial-buffers))
|
|
|
(should
|
|
|
(null
|
|
|
(-difference (buffer-list) expected-buffers)))))
|
|
|
|
|
|
(ert-deftest helpful--kind-name ()
|
|
|
(should
|
|
|
(equal
|
|
|
(helpful--kind-name 'message nil)
|
|
|
"variable"))
|
|
|
(should
|
|
|
(equal
|
|
|
(helpful--kind-name 'message t)
|
|
|
"function"))
|
|
|
(should
|
|
|
(equal
|
|
|
(helpful--kind-name 'save-excursion t)
|
|
|
"special form")))
|
|
|
|
|
|
(ert-deftest helpful--pretty-print ()
|
|
|
;; Strings should be formatted with double-quotes.
|
|
|
(should (equal "\"foo\"" (helpful--pretty-print "foo")))
|
|
|
;; Don't crash on large plists using keywords.
|
|
|
(helpful--pretty-print
|
|
|
'(:foo foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo :bar bar)))
|
|
|
|
|
|
(ert-deftest helpful-update-after-killing-buf ()
|
|
|
"If we originally looked at a variable in a specific buffer,
|
|
|
and that buffer has been killed, handle it gracefully."
|
|
|
;; Don't crash if the underlying buffer has been killed.
|
|
|
(let (helpful-buf)
|
|
|
(with-temp-buffer
|
|
|
(helpful-variable 'tab-width)
|
|
|
(setq helpful-buf (current-buffer)))
|
|
|
(with-current-buffer helpful-buf
|
|
|
(helpful-update))))
|
|
|
|
|
|
(ert-deftest helpful--canonical-symbol ()
|
|
|
(should
|
|
|
(eq (helpful--canonical-symbol 'not t)
|
|
|
'null))
|
|
|
(should
|
|
|
(eq (helpful--canonical-symbol 'search-forward-regexp t)
|
|
|
're-search-forward))
|
|
|
(should
|
|
|
(eq (helpful--canonical-symbol 'emacs-bzr-version nil)
|
|
|
'emacs-repository-version)))
|
|
|
|
|
|
(ert-deftest helpful--aliases ()
|
|
|
(should
|
|
|
(equal (helpful--aliases 'null t)
|
|
|
(list 'not)))
|
|
|
(should
|
|
|
(equal (helpful--aliases 'emacs-repository-version nil)
|
|
|
(list 'emacs-bzr-version))))
|
|
|
|
|
|
(defun helpful-fn-in-elc ())
|
|
|
|
|
|
(ert-deftest helpful--elc-only ()
|
|
|
"Ensure we handle functions where we have the .elc but no .el
|
|
|
file."
|
|
|
;; Pretend that we've loaded `helpful-fn-in-elc' from /tmp/foo.elc.
|
|
|
(let ((load-history (cons '("/tmp/foo.elc" (defun . helpful-fn-in-elc))
|
|
|
load-history)))
|
|
|
;; This should not error.
|
|
|
(helpful-function 'helpful-fn-in-elc)))
|
|
|
|
|
|
(ert-deftest helpful--unnamed-func ()
|
|
|
"Ensure we handle unnamed functions too.
|
|
|
|
|
|
This is important for `helpful-key', where a user may have
|
|
|
associated a lambda with a keybinding."
|
|
|
(let* ((fun (lambda (x) x))
|
|
|
(buf (helpful--buffer fun t)))
|
|
|
;; There's no name, so just show lambda in the buffer name.
|
|
|
(should
|
|
|
(equal (buffer-name buf) "*helpful lambda*"))
|
|
|
;; Don't crash when we show the buffer.
|
|
|
(with-current-buffer buf
|
|
|
(helpful-update))))
|
|
|
|
|
|
(ert-deftest helpful--unnamed-compiled-func ()
|
|
|
"Ensure we handle unnamed byte-compiled functions.
|
|
|
|
|
|
This is important for `helpful-key', where a user may have
|
|
|
associated a lambda with a keybinding."
|
|
|
(let* ((fun (byte-compile (lambda (x) x)))
|
|
|
(buf (helpful--buffer fun t)))
|
|
|
;; There's no name, so just show lambda in the buffer name.
|
|
|
(should
|
|
|
(equal (buffer-name buf) "*helpful lambda*"))
|
|
|
;; Don't crash when we show the buffer.
|
|
|
(with-current-buffer buf
|
|
|
(helpful-update))))
|
|
|
|
|
|
(ert-deftest helpful--obsolete-variable ()
|
|
|
"Test display of obsolete variable."
|
|
|
(let* ((var 'helpful-test-var-obsolete)
|
|
|
(info (helpful--format-obsolete-info var nil)))
|
|
|
(should
|
|
|
(equal info "This variable is obsolete since 23.1; use helpful-test-var instead."))))
|
|
|
|
|
|
(ert-deftest helpful--obsolete-function ()
|
|
|
"Test display of obsolete function."
|
|
|
(let* ((fun 'helpful-test-fun-obsolete)
|
|
|
(info (helpful--format-obsolete-info fun t)))
|
|
|
(should
|
|
|
(equal info "This function is obsolete since 1.2.3; use helpful instead."))))
|
|
|
|
|
|
(ert-deftest helpful--keymap-keys--sparse ()
|
|
|
(let* ((parent-keymap (make-sparse-keymap))
|
|
|
(keymap (make-sparse-keymap)))
|
|
|
(set-keymap-parent keymap parent-keymap)
|
|
|
(define-key parent-keymap (kbd "a") #'forward-char)
|
|
|
(define-key keymap (kbd "C-c C-M-a") #'backward-char)
|
|
|
(define-key keymap [remap quoted-insert] #'forward-line)
|
|
|
(should
|
|
|
(equal
|
|
|
(helpful--keymap-keys keymap)
|
|
|
'(([17] forward-line)
|
|
|
([3 27 1] backward-char)
|
|
|
([97] forward-char))))))
|
|
|
|
|
|
(defvar helpful--dummy-keymap
|
|
|
(let ((keymap (make-sparse-keymap)))
|
|
|
(define-key keymap (kbd "a") #'forward-char)
|
|
|
keymap))
|
|
|
|
|
|
;; `fset' is necessary for keymaps as prefixes. This is a quirky Emacs
|
|
|
;; API: https://emacs.stackexchange.com/q/28576/304
|
|
|
(fset 'helpful--dummy-keymap helpful--dummy-keymap)
|
|
|
|
|
|
(ert-deftest helpful--keymap-keys--prefix ()
|
|
|
"Test we flatten keymaps with prefix keys."
|
|
|
(let* ((keymap (make-sparse-keymap)))
|
|
|
(define-key keymap (kbd "C-c") 'helpful--dummy-keymap)
|
|
|
(should
|
|
|
(equal
|
|
|
(helpful--keymap-keys keymap)
|
|
|
'(([3 97] forward-char))))))
|
|
|
|
|
|
(ert-deftest helpful--keymap-keys ()
|
|
|
(let* ((parent-keymap (make-keymap))
|
|
|
(keymap (make-keymap)))
|
|
|
(set-keymap-parent keymap parent-keymap)
|
|
|
(define-key parent-keymap (kbd "a") #'forward-char)
|
|
|
(define-key keymap (kbd "C-c C-M-a") #'backward-char)
|
|
|
(define-key keymap [remap quoted-insert] #'forward-line)
|
|
|
(should
|
|
|
(equal
|
|
|
;; This order differs from a sparse keymap. We should fix that
|
|
|
;; if it makes any difference.
|
|
|
(helpful--keymap-keys keymap)
|
|
|
'(([3 27 1] backward-char)
|
|
|
([17] forward-line)
|
|
|
([97] forward-char))))))
|
|
|
|
|
|
(ert-deftest helpful--keymap-keys--strings ()
|
|
|
"Test that we handle maps with format (TYPE ITEM-NAME . BINDING)."
|
|
|
;; This is an actual piece of smerge-mode-map.
|
|
|
(let ((keymap '(keymap (3 keymap
|
|
|
(94 keymap
|
|
|
(61 keymap
|
|
|
(61 "upper-lower" . smerge-diff-upper-lower)
|
|
|
(62 "base-lower" . smerge-diff-base-lower)
|
|
|
(60 "base-upper" . smerge-diff-base-upper)
|
|
|
"Diff"))))))
|
|
|
(should
|
|
|
(equal
|
|
|
(helpful--keymap-keys keymap)
|
|
|
'(([3 94 61 61] smerge-diff-upper-lower)
|
|
|
([3 94 61 62] smerge-diff-base-lower)
|
|
|
([3 94 61 60] smerge-diff-base-upper))))))
|
|
|
|
|
|
(ert-deftest helpful--keymap-keys--anonymous-fns ()
|
|
|
(let* ((keymap (make-keymap)))
|
|
|
(define-key keymap (kbd "a")
|
|
|
(lambda () (message)))
|
|
|
(define-key keymap (kbd "a")
|
|
|
(byte-compile-sexp (lambda () (message))))
|
|
|
|
|
|
;; Don't crash on anonymous functions in a keymap.
|
|
|
(helpful--keymap-keys keymap)))
|
|
|
|
|
|
(ert-deftest helpful--format-keymap--keyboard-macros ()
|
|
|
(let* ((keymap (make-keymap)))
|
|
|
;; A keyboard macro can be a string or a vector.
|
|
|
(define-key keymap "a" "ABC")
|
|
|
(define-key keymap "b" [TAB])
|
|
|
|
|
|
(should
|
|
|
(equal
|
|
|
(helpful--format-keymap keymap)
|
|
|
"a Keyboard Macro\nb Keyboard Macro"))))
|
|
|
|
|
|
(defun helpful--dummy-command ()
|
|
|
(interactive))
|
|
|
|
|
|
(ert-deftest helpful--keymaps-containing ()
|
|
|
"Ensure that we find keymaps for variables with bindings."
|
|
|
;; This is defined in the global map.
|
|
|
(should
|
|
|
(helpful--keymaps-containing #'where-is))
|
|
|
|
|
|
;; Only defined in `minor-mode-map-alist'.
|
|
|
(let ((keymap (make-sparse-keymap)))
|
|
|
(define-key keymap (kbd "a") #'helpful--dummy-command)
|
|
|
(let ((minor-mode-map-alist
|
|
|
(cons (cons 'foo-mode keymap) minor-mode-map-alist)))
|
|
|
(should
|
|
|
(helpful--keymaps-containing #'helpful--dummy-command))))
|
|
|
|
|
|
;; Don't crash if there are dodgy values in `minor-mode-map-alist'.
|
|
|
(let ((minor-mode-map-alist
|
|
|
;; I'm not convinced this is legal, but
|
|
|
;; pdf-cache-prefetch-minor-mode in pdf-tools has t as a
|
|
|
;; keymap.
|
|
|
(cons (cons 'foo-mode t) minor-mode-map-alist)))
|
|
|
(helpful--keymaps-containing #'helpful--dummy-command))
|
|
|
|
|
|
;; Create a keybinding that is very unlikely to clobber actually
|
|
|
;; defined keybindings in the current emacs instance.
|
|
|
(global-set-key (kbd "C-c M-S-c") #'helpful--dummy-command)
|
|
|
|
|
|
;; This command should only be in `global-map' and
|
|
|
;; `mode-specific-map'.
|
|
|
(should
|
|
|
(equal
|
|
|
(length (helpful--keymaps-containing #'helpful--dummy-command))
|
|
|
2))
|
|
|
|
|
|
;; Undo keybinding.
|
|
|
(global-set-key (kbd "C-c M-S-c") nil)
|
|
|
|
|
|
;; Check for ido command remapping.
|
|
|
(ido-mode 1)
|
|
|
(should
|
|
|
(equal
|
|
|
(helpful--keymaps-containing 'ido-find-file)
|
|
|
'(("minor-mode-map-alist (ido-mode)" "<open>" "C-x C-f"))))
|
|
|
(ido-mode 0))
|
|
|
|
|
|
(defalias 'helpful--dummy-command-alias #'helpful--dummy-command)
|
|
|
|
|
|
(ert-deftest helpful--keymaps-containing-aliases ()
|
|
|
"Ensure that we find keymaps that we've bound command aliases
|
|
|
in."
|
|
|
;; Create keybindings that are very unlikely to clobber actually
|
|
|
;; defined keybindings in the current emacs instance.
|
|
|
(global-set-key (kbd "C-c M-S-c") #'helpful--dummy-command)
|
|
|
(global-set-key (kbd "C-c M-S-d") #'helpful--dummy-command-alias)
|
|
|
|
|
|
(unwind-protect
|
|
|
(let* ((keymaps (helpful--keymaps-containing-aliases #'helpful--dummy-command (helpful--aliases 'helpful--dummy-command t)))
|
|
|
(global-keybindings (cdr (assoc "global-map" keymaps))))
|
|
|
(should
|
|
|
(equal global-keybindings (list "C-c M-S-c" "C-c M-S-d"))))
|
|
|
|
|
|
;; Undo keybindings.
|
|
|
(global-set-key (kbd "C-c M-S-c") nil)
|
|
|
(global-set-key (kbd "C-c M-S-d") nil)))
|
|
|
|
|
|
(ert-deftest helpful--merge-alists ()
|
|
|
(should
|
|
|
(equal
|
|
|
(helpful--merge-alists '((a . (1 2 3)) (b . (4)))
|
|
|
'((a . (10)) (c . (11))))
|
|
|
'((a . (1 2 3 10))
|
|
|
(b . (4))
|
|
|
(c . (11))))))
|
|
|
|
|
|
(ert-deftest helpful--source ()
|
|
|
(-let* (((buf pos opened) (helpful--definition #'helpful--source t))
|
|
|
(source (helpful--source #'helpful--source t buf pos)))
|
|
|
(should
|
|
|
(s-starts-with-p "(defun " source))))
|
|
|
|
|
|
(ert-deftest helpful--source-autoloaded ()
|
|
|
"We should include the autoload cookie."
|
|
|
(-let* (((buf pos opened) (helpful--definition #'helpful-at-point t))
|
|
|
(source (helpful--source #'helpful-at-point t buf pos)))
|
|
|
(should
|
|
|
(s-starts-with-p ";;;###autoload" source))))
|
|
|
|
|
|
(ert-deftest helpful--source--interactively-defined-fn ()
|
|
|
"We should return the raw sexp for functions where we can't
|
|
|
find the source code."
|
|
|
(eval '(defun test-foo-defined-interactively () 42))
|
|
|
(-let* (((buf pos opened) (helpful--definition #'test-foo-defined-interactively t)))
|
|
|
(should
|
|
|
(not
|
|
|
(null
|
|
|
(helpful--source #'test-foo-defined-interactively t buf pos))))))
|
|
|
|
|
|
(ert-deftest helpful--outer-sexp ()
|
|
|
;; If point is in the middle of a form, we should return its position.
|
|
|
(with-temp-buffer
|
|
|
(insert "(foo bar baz)")
|
|
|
(goto-char (point-min))
|
|
|
(search-forward "b")
|
|
|
|
|
|
(-let [(pos subforms)
|
|
|
(helpful--outer-sexp (current-buffer) (point))]
|
|
|
(should
|
|
|
(equal pos (point-min)))
|
|
|
(should
|
|
|
(equal subforms '(foo bar)))))
|
|
|
;; If point is at the beginning of a form, we should still return its position.
|
|
|
(with-temp-buffer
|
|
|
(insert "(foo) (bar)")
|
|
|
(goto-char (point-min))
|
|
|
(search-forward "b")
|
|
|
(backward-char 2)
|
|
|
|
|
|
(-let [(pos subforms)
|
|
|
(save-excursion
|
|
|
(helpful--outer-sexp (current-buffer) (point)))]
|
|
|
(should
|
|
|
(equal pos (point)))
|
|
|
(should
|
|
|
(equal subforms '(bar))))))
|
|
|
|
|
|
(ert-deftest helpful--summary--aliases ()
|
|
|
;; exclude the sym itself
|
|
|
"Ensure we mention that a symbol is an alias."
|
|
|
(-let* (((buf pos opened) (helpful--definition '-select t))
|
|
|
(summary (helpful--summary '-select t buf pos)))
|
|
|
(when opened
|
|
|
(kill-buffer buf))
|
|
|
;; Strip properties to make assertion messages more readable.
|
|
|
(set-text-properties 0 (1- (length summary)) nil summary)
|
|
|
(should
|
|
|
(equal
|
|
|
summary
|
|
|
"-select is a function alias for -filter, defined in dash.el."))))
|
|
|
|
|
|
(ert-deftest helpful--summary--special-form ()
|
|
|
"Ensure we describe special forms correctly"
|
|
|
(-let* ((summary (helpful--summary 'if t nil nil)))
|
|
|
;; Strip properties to make assertion messages more readable.
|
|
|
(set-text-properties 0 (1- (length summary)) nil summary)
|
|
|
(should
|
|
|
(s-starts-with-p "if is a special form defined in" summary))))
|
|
|
|
|
|
(defun helpful-test-fn-interactive ()
|
|
|
(interactive))
|
|
|
|
|
|
(ert-deftest helpful--summary--interactive-fn ()
|
|
|
"Ensure we use \"an\" for interactive functions."
|
|
|
(let* ((summary (helpful--summary 'helpful-test-fn-interactive t nil nil)))
|
|
|
;; Strip properties to make assertion messages more readable.
|
|
|
(set-text-properties 0 (1- (length summary)) nil summary)
|
|
|
(should
|
|
|
(s-starts-with-p "helpful-test-fn-interactive is an interactive function" summary))))
|
|
|
|
|
|
(defun helpful-test-fn? ()
|
|
|
(interactive))
|
|
|
|
|
|
(ert-deftest helpful--summary--fn-with-? ()
|
|
|
"Ensure we use don't needlessly escape ? in function names."
|
|
|
(let* ((summary (helpful--summary 'helpful-test-fn? t nil nil)))
|
|
|
;; Strip properties to make assertion messages more readable.
|
|
|
(set-text-properties 0 (1- (length summary)) nil summary)
|
|
|
(should
|
|
|
(s-starts-with-p "helpful-test-fn? is" summary))))
|
|
|
|
|
|
(ert-deftest helpful--signature-fn-with? ()
|
|
|
"Ensure that symbols with question marks are handled correctly."
|
|
|
(should
|
|
|
(equal (helpful--signature 'helpful-test-fn?)
|
|
|
"(helpful-test-fn?)")))
|
|
|
|
|
|
(defun helpful-test-fn-with\ space ()
|
|
|
42)
|
|
|
|
|
|
(ert-deftest helpful--summary--symbol-with-space ()
|
|
|
"Ensure we correctly format symbols containing spaces."
|
|
|
(let* ((summary (helpful--summary 'helpful-test-fn-with\ space t nil nil)))
|
|
|
;; Strip properties to make assertion messages more readable.
|
|
|
(set-text-properties 0 (1- (length summary)) nil summary)
|
|
|
(should
|
|
|
(s-starts-with-p "helpful-test-fn-with\\ space is a function" summary))))
|
|
|
|
|
|
(ert-deftest helpful--bound-p ()
|
|
|
;; Functions.
|
|
|
(should (helpful--bound-p 'message))
|
|
|
;; Variables
|
|
|
(should (helpful--bound-p 'tab-width))
|
|
|
;; Unbound.
|
|
|
(should (not (helpful--bound-p 'this-variable-does-not-exist)))
|
|
|
;; For our purposes, we don't consider nil or t to be bound.
|
|
|
(should (not (helpful--bound-p 'nil)))
|
|
|
(should (not (helpful--bound-p 't))))
|
|
|
|
|
|
(ert-deftest helpful--callees ()
|
|
|
(should
|
|
|
(equal
|
|
|
(helpful--callees '(quote (foo)))
|
|
|
nil))
|
|
|
;; Simple function calls.
|
|
|
(should
|
|
|
(equal
|
|
|
(helpful--callees '(foo (bar 1) 2))
|
|
|
'(foo bar))))
|
|
|
|
|
|
(ert-deftest helpful--callees-let ()
|
|
|
(should
|
|
|
(equal
|
|
|
(helpful--callees
|
|
|
'(progn
|
|
|
(let ((x (foo))
|
|
|
(y t))
|
|
|
(bar x y))
|
|
|
(let (y)
|
|
|
(baz))
|
|
|
(let* ((z (quux))))))
|
|
|
'(foo bar baz quux))))
|
|
|
|
|
|
(ert-deftest helpful--callees--lambda ()
|
|
|
(should
|
|
|
(equal
|
|
|
(helpful--callees '(lambda (x) (foo x)))
|
|
|
'(foo))))
|
|
|
|
|
|
(ert-deftest helpful--callees--closure ()
|
|
|
(should
|
|
|
(equal
|
|
|
(helpful--callees '(closure (t) (x) (foo x)))
|
|
|
'(foo))))
|
|
|
|
|
|
(ert-deftest helpful--callees--function ()
|
|
|
(should
|
|
|
(equal
|
|
|
(helpful--callees '(function (lambda (x) (foo x))))
|
|
|
'(foo)))
|
|
|
(should
|
|
|
(equal
|
|
|
(helpful--callees '(function foo))
|
|
|
'(foo))))
|
|
|
|
|
|
(ert-deftest helpful--callees--cond ()
|
|
|
(should
|
|
|
(equal
|
|
|
(helpful--callees
|
|
|
'(cond
|
|
|
(x)
|
|
|
((foo))
|
|
|
((bar)
|
|
|
(baz))
|
|
|
(t
|
|
|
(quux))
|
|
|
))
|
|
|
'(foo bar baz quux))))
|
|
|
|
|
|
(ert-deftest helpful--callees--condition-case ()
|
|
|
(should
|
|
|
(equal
|
|
|
(helpful--callees
|
|
|
'(condition-case e
|
|
|
(foo)
|
|
|
(error (bar))
|
|
|
((arith-error file-error) (baz))))
|
|
|
'(foo bar baz))))
|
|
|
|
|
|
(ert-deftest helpful--callees--funcall ()
|
|
|
(let ((result (helpful--callees
|
|
|
'(progn
|
|
|
(funcall 'foo 1)
|
|
|
(apply 'bar 2)
|
|
|
(apply (baz) 3)
|
|
|
(apply unknown-var 3)))))
|
|
|
(should (memq 'foo result))
|
|
|
(should (memq 'bar result))
|
|
|
(should (memq 'baz result))
|
|
|
(should (not (memq 'unknown-var result))))
|
|
|
(let ((result (helpful--callees
|
|
|
'(progn
|
|
|
(funcall #'foo 1)
|
|
|
(apply #'bar 2)))))
|
|
|
(should (memq 'foo result))
|
|
|
(should (memq 'bar result))))
|
|
|
|
|
|
(ert-deftest helpful--callees-button--smoke ()
|
|
|
(with-temp-buffer
|
|
|
(let ((button (helpful--make-callees-button
|
|
|
'whatever
|
|
|
'(defun whatever () (something) (test 5)))))
|
|
|
(insert button)
|
|
|
(goto-char (point-min))
|
|
|
(push-button)))
|
|
|
(with-temp-buffer
|
|
|
(let ((button (helpful--make-callees-button
|
|
|
'(lambda () (interactive) (other-window -1))
|
|
|
'(lambda () (interactive) (other-window -1)))))
|
|
|
(insert button)
|
|
|
(goto-char (point-min))
|
|
|
(push-button))))
|
|
|
|
|
|
;; TODO: broken when byte-compiling helpful.el.
|
|
|
;; (ert-deftest helpful--autoloaded-p ()
|
|
|
;; (-let [(buf pos opened) (helpful--definition 'rx-to-string t)]
|
|
|
;; (should (helpful--autoloaded-p 'rx-to-string buf))
|
|
|
;; (when opened
|
|
|
;; (kill-buffer buf))))
|
|
|
|
|
|
(ert-deftest helpful--inhibit-read-only ()
|
|
|
(helpful-variable 'inhibit-read-only)
|
|
|
(should
|
|
|
(s-contains-p "Value\nnil" (buffer-string))))
|
|
|
|
|
|
(ert-deftest helpful--convert-c-name ()
|
|
|
(should
|
|
|
(equal
|
|
|
'make-string
|
|
|
(helpful--convert-c-name 'Fmake_string nil)))
|
|
|
(should
|
|
|
(equal
|
|
|
'gc-cons-percentage
|
|
|
(helpful--convert-c-name 'Vgc_cons_percentage t)))
|
|
|
(should-not
|
|
|
(helpful--convert-c-name 'Fmake_string t))
|
|
|
(should-not
|
|
|
(helpful--convert-c-name 'Vgc_cons_percentage nil)))
|
|
|
|
|
|
(ert-deftest helpful-symbol-c-style ()
|
|
|
(helpful-symbol 'Fget_char_property)
|
|
|
(helpful-symbol 'Vinhibit_field_text_motion))
|
|
|
|
|
|
(ert-deftest helpful-symbol-unbound ()
|
|
|
"Ensure we inform the user if we're given an unbound symbol."
|
|
|
(should
|
|
|
(condition-case _
|
|
|
(helpful-symbol 'notboundtoanything)
|
|
|
('user-error t))))
|
|
|
|
|
|
(ert-deftest helpful--loads-autoload-symbol ()
|
|
|
"When asked to describe an autoloaded symbol, just load it."
|
|
|
;; This test assumes that you haven't loaded tetris.el.gz in your
|
|
|
;; current instance.
|
|
|
(skip-unless (autoloadp (symbol-function 'tetris)))
|
|
|
;; This is a regression test: `tetris' has `tetris-mode-map' in its
|
|
|
;; docstring, so we can't display the mode map unless tetris.el.gz is
|
|
|
;; loaded.
|
|
|
;;
|
|
|
(helpful-function #'tetris))
|
|
|
|
|
|
(defcustom helpful-test-custom-var 123
|
|
|
"I am an example custom variable."
|
|
|
:type 'number
|
|
|
:group 'helpful
|
|
|
:package-version '(helpful . "1.2.3"))
|
|
|
|
|
|
;; Ensure the current value differs from the original value.
|
|
|
(setq helpful-test-custom-var 456)
|
|
|
|
|
|
(ert-deftest helpful--original-value ()
|
|
|
"Show the original value for defcustom variables."
|
|
|
(helpful-variable 'helpful-test-custom-var)
|
|
|
(should
|
|
|
(s-contains-p "Original Value\n123" (buffer-string))))
|
|
|
|
|
|
(ert-deftest helpful--package-version ()
|
|
|
"Report when a variable was added"
|
|
|
(helpful-variable 'helpful-test-custom-var)
|
|
|
(should
|
|
|
(s-contains-p
|
|
|
(s-word-wrap
|
|
|
70
|
|
|
"This variable was added, or its default value changed, in helpful version 1.2.3.")
|
|
|
(buffer-string))))
|
|
|
|
|
|
(ert-deftest helpful--display-implementations ()
|
|
|
(require 'xref)
|
|
|
(helpful-function 'xref-location-marker)
|
|
|
(should (s-contains-p "Implementations" (buffer-string)))
|
|
|
(should (s-contains-p "((l xref-file-location))" (buffer-string)))
|
|
|
(should (s-contains-p "((l xref-buffer-location))" (buffer-string))))
|