Move unit tests from ert to buttercup
Easier to organize and write. Now I can hopefully strive for better coverage!
This commit is contained in:
parent
98d2f1de3f
commit
eaca8c58fa
41 changed files with 1371 additions and 1101 deletions
|
@ -1,169 +0,0 @@
|
||||||
;;; core/autoload/test.el -*- lexical-binding: t; no-byte-compile: t; -*-
|
|
||||||
|
|
||||||
(defun doom//run-tests (&optional modules)
|
|
||||||
"Run all loaded tests, specified by MODULES (a list of module cons cells) or
|
|
||||||
command line args following a double dash (each arg should be in the
|
|
||||||
'module/submodule' format).
|
|
||||||
|
|
||||||
If neither is available, run all tests in all enabled modules."
|
|
||||||
(interactive)
|
|
||||||
(require 'core-packages)
|
|
||||||
(doom//reload-autoloads)
|
|
||||||
(let (noninteractive)
|
|
||||||
;; Core libraries aren't fully loaded in a noninteractive session, so we
|
|
||||||
;; reload it with `noninteractive' set to nil to force them to.
|
|
||||||
(doom-initialize t)
|
|
||||||
(doom-initialize-modules t))
|
|
||||||
(condition-case-unless-debug ex
|
|
||||||
(let ((target-paths
|
|
||||||
;; Convert targets (either from MODULES or `argv') into a list of
|
|
||||||
;; string paths, pointing to the root directory of modules
|
|
||||||
(cond ((stringp (car modules)) ; command line
|
|
||||||
(save-match-data
|
|
||||||
(cl-loop for arg in modules
|
|
||||||
if (string= arg ":core") collect doom-core-dir
|
|
||||||
else if (string-match-p "/" arg)
|
|
||||||
nconc (cl-loop for dir in doom-modules-dirs
|
|
||||||
collect (expand-file-name arg dir))
|
|
||||||
else
|
|
||||||
nconc (cl-loop for dir in doom-modules-dirs
|
|
||||||
for path = (expand-file-name arg dir)
|
|
||||||
if (file-directory-p path)
|
|
||||||
nconc
|
|
||||||
(cl-remove-if-not
|
|
||||||
#'file-directory-p
|
|
||||||
(directory-files path t "^[^.]" t)))
|
|
||||||
finally do (setq argv nil))))
|
|
||||||
|
|
||||||
(modules ; cons-cells given to MODULES
|
|
||||||
(cl-loop for (module . submodule) in modules
|
|
||||||
if (doom-module-locate-path module submodule)
|
|
||||||
collect it))
|
|
||||||
|
|
||||||
((append (list doom-core-dir)
|
|
||||||
(doom-module-load-path))))))
|
|
||||||
;; Load all the unit test files...
|
|
||||||
(dolist (path target-paths)
|
|
||||||
(let ((test-path (expand-file-name "test/" path)))
|
|
||||||
(when (file-directory-p test-path)
|
|
||||||
(dolist (test-file (reverse (doom-files-in test-path :match "\\.el$" :full t)))
|
|
||||||
(load test-file nil :noerror)))))
|
|
||||||
;; ... then run them
|
|
||||||
(switch-to-buffer (get-buffer-create "*blank*"))
|
|
||||||
(if noninteractive
|
|
||||||
(ert-run-tests-batch-and-exit)
|
|
||||||
(call-interactively #'ert-run-tests-interactively)))
|
|
||||||
('error
|
|
||||||
(lwarn 'doom-test :error
|
|
||||||
"%s -> %s"
|
|
||||||
(car ex) (error-message-string ex)))))
|
|
||||||
|
|
||||||
|
|
||||||
;; --- Test helpers -----------------------
|
|
||||||
|
|
||||||
(defmacro def-test! (name &rest body)
|
|
||||||
"Define a namespaced ERT test."
|
|
||||||
(declare (indent defun) (doc-string 2))
|
|
||||||
(let (plist)
|
|
||||||
(while (keywordp (car body))
|
|
||||||
(push (pop body) plist)
|
|
||||||
(push (pop body) plist))
|
|
||||||
(setq plist (reverse plist))
|
|
||||||
(when-let* ((modes (doom-enlist (plist-get plist :minor-mode))))
|
|
||||||
(dolist (mode modes)
|
|
||||||
(setq body `((with-minor-mode! ,mode ,@body)))))
|
|
||||||
(when-let* ((before (plist-get plist :before)))
|
|
||||||
(setq body `(,@before ,@body)))
|
|
||||||
(when-let* ((after (plist-get plist :after)))
|
|
||||||
(setq body `(,@body @after)))
|
|
||||||
`(ert-deftest
|
|
||||||
,(intern (format "%s::%s"
|
|
||||||
(if (file-in-directory-p load-file-name doom-core-dir)
|
|
||||||
(format "core/%s" (file-name-base load-file-name))
|
|
||||||
(replace-regexp-in-string "^.*/modules/\\([^/]+\\)/\\([^/]+\\)/test/" "\\1/\\2:"
|
|
||||||
(file-name-sans-extension load-file-name)))
|
|
||||||
name))
|
|
||||||
()
|
|
||||||
,(if (plist-get plist :skip)
|
|
||||||
`(ert-skip ,(plist-get plist :skip))
|
|
||||||
`(with-temp-buffer
|
|
||||||
(save-mark-and-excursion
|
|
||||||
(save-window-excursion
|
|
||||||
,@body)))))))
|
|
||||||
|
|
||||||
(defmacro should-buffer! (initial expected &rest body)
|
|
||||||
"Test that a buffer with INITIAL text, run BODY, then test it against EXPECTED.
|
|
||||||
|
|
||||||
INITIAL will recognize cursor markers in the form {[0-9]}. A {0} marker marks
|
|
||||||
where the cursor should be after setup. Otherwise, the cursor will be placed at
|
|
||||||
`point-min'.
|
|
||||||
|
|
||||||
EXPECTED will recognize one (optional) cursor marker: {|}, this is the
|
|
||||||
'expected' location of the cursor after BODY is finished, and will be tested
|
|
||||||
against."
|
|
||||||
(declare (indent 2))
|
|
||||||
`(with-temp-buffer
|
|
||||||
(cl-loop for line in ',initial
|
|
||||||
do (insert line "\n"))
|
|
||||||
(goto-char (point-min))
|
|
||||||
(let (marker-list)
|
|
||||||
(save-excursion
|
|
||||||
(while (re-search-forward "{\\([0-9]\\)}" nil t)
|
|
||||||
(push (cons (match-string 1)
|
|
||||||
(set-marker (make-marker) (match-beginning 0)))
|
|
||||||
marker-list)
|
|
||||||
(replace-match "" t t))
|
|
||||||
(if (not marker-list)
|
|
||||||
(goto-char (point-min))
|
|
||||||
(sort marker-list
|
|
||||||
(lambda (m1 m2) (< (marker-position m1)
|
|
||||||
(marker-position m2))))
|
|
||||||
(when (equal (caar marker-list) "0")
|
|
||||||
(goto-char! 0)))
|
|
||||||
,@body
|
|
||||||
(let ((result-text (buffer-string))
|
|
||||||
(point (point))
|
|
||||||
expected-text)
|
|
||||||
(with-temp-buffer
|
|
||||||
(cl-loop for line in ',expected
|
|
||||||
do (insert line "\n"))
|
|
||||||
(save-excursion
|
|
||||||
(goto-char (point-min))
|
|
||||||
(when (re-search-forward "{|}" nil t)
|
|
||||||
(replace-match "" t t)
|
|
||||||
(should (equal (point) point))))
|
|
||||||
(setq expected-text (buffer-string))
|
|
||||||
(should (equal expected-text result-text))))))))
|
|
||||||
|
|
||||||
(defmacro goto-char! (index)
|
|
||||||
"Meant to be used with `should-buffer!'. Will move the cursor to one of the
|
|
||||||
cursor markers. e.g. Go to marker {2} with (goto-char! 2)."
|
|
||||||
`(goto-char (point! ,index)))
|
|
||||||
|
|
||||||
(defmacro point! (index)
|
|
||||||
"Meant to be used with `should-buffer!'. Returns the position of a cursor
|
|
||||||
marker. e.g. {2} can be retrieved with (point! 2)."
|
|
||||||
`(cdr (assoc ,(cond ((numberp index) (number-to-string index))
|
|
||||||
((symbolp index) (symbol-name index))
|
|
||||||
((stringp index) index))
|
|
||||||
marker-list)))
|
|
||||||
|
|
||||||
(defmacro with-minor-mode! (mode &rest body)
|
|
||||||
"Activate a minor mode while in BODY, deactivating it after."
|
|
||||||
(declare (indent defun))
|
|
||||||
`(progn (,mode +1)
|
|
||||||
,@body
|
|
||||||
(,mode -1)))
|
|
||||||
|
|
||||||
(defmacro let-advice! (binds &rest body)
|
|
||||||
"Temporarily bind advice in BINDS while in BODY.
|
|
||||||
|
|
||||||
e.g. (old-fn :before advice-fn)
|
|
||||||
(old-fn :around advice-fn)"
|
|
||||||
(declare (indent defun))
|
|
||||||
`(progn
|
|
||||||
,@(cl-loop for (target type advice) in binds
|
|
||||||
collect `(advice-add #',target ,type #',advice))
|
|
||||||
,@body
|
|
||||||
,@(cl-loop for (target type advice) in binds
|
|
||||||
collect `(advice-remove #',target #',advice))))
|
|
|
@ -172,7 +172,7 @@ respectively."
|
||||||
|
|
||||||
(def-dispatcher! test
|
(def-dispatcher! test
|
||||||
"Run Doom unit tests."
|
"Run Doom unit tests."
|
||||||
(load! "autoload/test")
|
(require 'core-tests)
|
||||||
(doom//run-tests args))
|
(doom//run-tests args))
|
||||||
|
|
||||||
(def-dispatcher! info
|
(def-dispatcher! info
|
||||||
|
|
68
core/core-tests.el
Normal file
68
core/core-tests.el
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
;;; core/core-tests.el -*- lexical-binding: t; -*-
|
||||||
|
|
||||||
|
(defun doom//run-tests (&optional modules)
|
||||||
|
"Run all loaded tests, specified by MODULES (a list of module cons cells) or
|
||||||
|
command line args following a double dash (each arg should be in the
|
||||||
|
'module/submodule' format).
|
||||||
|
|
||||||
|
If neither is available, run all tests in all enabled modules."
|
||||||
|
(interactive)
|
||||||
|
(let (noninteractive)
|
||||||
|
;; Core libraries aren't fully loaded in a noninteractive session, so we
|
||||||
|
;; reload it with `noninteractive' set to nil to force them to.
|
||||||
|
(quiet! (doom//reload-autoloads))
|
||||||
|
(doom-initialize t))
|
||||||
|
(let ((target-paths
|
||||||
|
;; Convert targets into a list of string paths, pointing to the root
|
||||||
|
;; directory of modules
|
||||||
|
(cond ((stringp (car modules)) ; command line
|
||||||
|
(save-match-data
|
||||||
|
(cl-loop for arg in modules
|
||||||
|
if (string= arg ":core") collect doom-core-dir
|
||||||
|
else if (string-match-p "/" arg)
|
||||||
|
nconc (mapcar (apply-partially #'expand-file-name arg)
|
||||||
|
doom-modules-dirs)
|
||||||
|
else
|
||||||
|
nconc (cl-loop for dir in doom-modules-dirs
|
||||||
|
for path = (expand-file-name arg dir)
|
||||||
|
if (file-directory-p path)
|
||||||
|
nconc
|
||||||
|
(doom-files-in
|
||||||
|
path :type 'dirs :depth 1 :full t))
|
||||||
|
finally do (setq argv nil))))
|
||||||
|
|
||||||
|
(modules ; cons-cells given to MODULES
|
||||||
|
(cl-loop for (module . submodule) in modules
|
||||||
|
if (doom-module-locate-path module submodule)
|
||||||
|
collect it))
|
||||||
|
|
||||||
|
((append (list doom-core-dir)
|
||||||
|
(doom-module-load-path))))))
|
||||||
|
;; Load all the unit test files...
|
||||||
|
(require 'buttercup)
|
||||||
|
(mapc (lambda (file) (load file :noerror (not doom-debug-mode)))
|
||||||
|
(doom-files-in (mapcar (apply-partially #'expand-file-name "test/")
|
||||||
|
target-paths)
|
||||||
|
:match "\\.el$" :full t))
|
||||||
|
;; ... then run them
|
||||||
|
(when doom-debug-mode
|
||||||
|
(setq buttercup-stack-frame-style 'pretty))
|
||||||
|
(let ((split-width-threshold 0)
|
||||||
|
(split-height-threshold 0)
|
||||||
|
(window-min-width 0)
|
||||||
|
(window-min-height 0))
|
||||||
|
(buttercup-run))))
|
||||||
|
|
||||||
|
|
||||||
|
;;
|
||||||
|
(defmacro def-test! (_name &rest _body))
|
||||||
|
|
||||||
|
(defmacro insert! (&rest text)
|
||||||
|
"Insert TEXT in buffer, then move cursor to last {0} marker."
|
||||||
|
`(progn
|
||||||
|
(insert ,@text)
|
||||||
|
(when (search-backward "{0}" nil t)
|
||||||
|
(replace-match "" t t))))
|
||||||
|
|
||||||
|
(provide 'core-tests)
|
||||||
|
;;; core-tests.el ends here
|
|
@ -39,3 +39,6 @@
|
||||||
|
|
||||||
;; autoload/debug.el
|
;; autoload/debug.el
|
||||||
(package! esup)
|
(package! esup)
|
||||||
|
|
||||||
|
;; autoload/test.el
|
||||||
|
(package! buttercup)
|
||||||
|
|
|
@ -1,130 +0,0 @@
|
||||||
;; -*- no-byte-compile: t; -*-
|
|
||||||
;;; core/test/autoload-buffers.el
|
|
||||||
|
|
||||||
(defmacro with-temp-buffers!! (buffer-args &rest body)
|
|
||||||
(declare (indent defun))
|
|
||||||
(let (buffers)
|
|
||||||
(dolist (bsym buffer-args)
|
|
||||||
(push `(,bsym (get-buffer-create ,(symbol-name bsym)))
|
|
||||||
buffers))
|
|
||||||
`(save-window-excursion
|
|
||||||
(cl-flet ((buffer-list
|
|
||||||
(lambda ()
|
|
||||||
(cl-remove-if-not #'buffer-live-p (list ,@(reverse (mapcar #'car buffers)))))))
|
|
||||||
(let* ((split-width-threshold 0)
|
|
||||||
(window-min-width 0)
|
|
||||||
persp-mode
|
|
||||||
,@buffers)
|
|
||||||
(delete-other-windows)
|
|
||||||
,@body
|
|
||||||
(let (kill-buffer-query-functions kill-buffer-hook)
|
|
||||||
(mapc #'kill-buffer (buffer-list))))))))
|
|
||||||
|
|
||||||
;;
|
|
||||||
(def-test! get-buffers
|
|
||||||
(with-temp-buffers!! (a b c)
|
|
||||||
(should (cl-every #'buffer-live-p (buffer-list)))
|
|
||||||
(should (equal (buffer-list) (list a b c)))
|
|
||||||
(dolist (buf (list (cons a doom-emacs-dir)
|
|
||||||
(cons b doom-emacs-dir)
|
|
||||||
(cons c "/tmp/")))
|
|
||||||
(with-current-buffer (car buf)
|
|
||||||
(setq-local default-directory (cdr buf))))
|
|
||||||
(projectile-mode +1)
|
|
||||||
(with-current-buffer a
|
|
||||||
;; should produce all buffers
|
|
||||||
(let ((buffers (doom-buffer-list)))
|
|
||||||
(should (cl-every (lambda (x) (memq x buffers)) (list a b c))))
|
|
||||||
;; should produce only project buffers
|
|
||||||
(let ((buffers (doom-project-buffer-list)))
|
|
||||||
(should (cl-every (lambda (x) (memq x buffers)) (list a b)))
|
|
||||||
(should-not (memq c buffers))))
|
|
||||||
;; If no project is available, just get all buffers
|
|
||||||
(with-current-buffer c
|
|
||||||
(let ((buffers (doom-project-buffer-list)))
|
|
||||||
(should (cl-every (lambda (x) (memq x buffers)) (list a b c)))))
|
|
||||||
(projectile-mode -1)))
|
|
||||||
|
|
||||||
(def-test! real-buffers
|
|
||||||
(let (doom-real-buffer-functions)
|
|
||||||
(with-temp-buffers!! (a b c d)
|
|
||||||
(with-current-buffer a
|
|
||||||
(setq-local buffer-file-name "x"))
|
|
||||||
(with-current-buffer b
|
|
||||||
(setq-local doom-real-buffer-p t))
|
|
||||||
(with-current-buffer c
|
|
||||||
(rename-buffer "*C*"))
|
|
||||||
(should (doom-real-buffer-p a))
|
|
||||||
(should (doom-real-buffer-p b))
|
|
||||||
(should-not (doom-real-buffer-p c))
|
|
||||||
(should-not (doom-real-buffer-p d))
|
|
||||||
(let ((buffers (doom-real-buffer-list)))
|
|
||||||
(should (= (length buffers) 2))
|
|
||||||
(should (cl-every (lambda (x) (memq x buffers)) (list a b)))
|
|
||||||
(should (cl-notany (lambda (x) (memq x buffers)) (list c d)))))))
|
|
||||||
|
|
||||||
;; `doom-visible-windows'
|
|
||||||
;; `doom-visible-buffers'
|
|
||||||
;; `doom-buried-buffers'
|
|
||||||
(def-test! visible-buffers-and-windows
|
|
||||||
(with-temp-buffers!! (a b c d)
|
|
||||||
(switch-to-buffer a)
|
|
||||||
(should (eq (current-buffer) a))
|
|
||||||
(should (eq (selected-window) (get-buffer-window a)))
|
|
||||||
(split-window nil 1)
|
|
||||||
(switch-to-buffer b)
|
|
||||||
(should (eq (current-buffer) b))
|
|
||||||
(should (eq (selected-window) (get-buffer-window b)))
|
|
||||||
(should (cl-intersection (list a b) (doom-visible-buffers)))
|
|
||||||
(should (cl-intersection (list c d) (doom-buried-buffers)))
|
|
||||||
(should (cl-intersection (mapcar #'get-buffer-window (list a b))
|
|
||||||
(doom-visible-windows)))))
|
|
||||||
|
|
||||||
;; `doom-matching-buffers'
|
|
||||||
(def-test! matching-buffers
|
|
||||||
(with-temp-buffers!! (a b c)
|
|
||||||
(let ((buffers (doom-matching-buffers "^[ac]$")))
|
|
||||||
(should (= 2 (length buffers)))
|
|
||||||
(should (cl-every #'bufferp buffers))
|
|
||||||
(should (cl-every (lambda (x) (memq x buffers)) (list a c)))
|
|
||||||
(should (equal buffers (doom-matching-buffers "^[ac]$"))))))
|
|
||||||
|
|
||||||
;; `doom-buffers-in-mode'
|
|
||||||
(def-test! buffers-in-mode
|
|
||||||
(with-temp-buffers!! (a b c d e)
|
|
||||||
(dolist (buf (list a b))
|
|
||||||
(with-current-buffer buf
|
|
||||||
(delay-mode-hooks (emacs-lisp-mode))))
|
|
||||||
(dolist (buf (list c d e))
|
|
||||||
(with-current-buffer buf
|
|
||||||
(text-mode)))
|
|
||||||
(let ((el-buffers (doom-buffers-in-mode 'emacs-lisp-mode))
|
|
||||||
(txt-buffers (doom-buffers-in-mode 'text-mode)))
|
|
||||||
(should (cl-every #'buffer-live-p (append el-buffers txt-buffers)))
|
|
||||||
(should (= 2 (length el-buffers)))
|
|
||||||
(should (= 3 (length txt-buffers))))))
|
|
||||||
|
|
||||||
;; `doom-fallback-buffer'
|
|
||||||
(def-test! fallback-buffer
|
|
||||||
(let ((fallback (doom-fallback-buffer)))
|
|
||||||
(should (buffer-live-p fallback))
|
|
||||||
(should (equal (buffer-name fallback) doom-fallback-buffer-name))))
|
|
||||||
|
|
||||||
;; `doom-kill-buffer-and-windows'
|
|
||||||
(def-test! kill-buffer-and-windows
|
|
||||||
(with-temp-buffers!! (a b)
|
|
||||||
(switch-to-buffer a) (split-window-horizontally)
|
|
||||||
(switch-to-buffer b) (split-window-horizontally)
|
|
||||||
(switch-to-buffer a)
|
|
||||||
|
|
||||||
(should (= (length (doom-visible-windows)) 3))
|
|
||||||
(should (= (length (doom-buffer-list)) 2))
|
|
||||||
|
|
||||||
(doom-kill-buffer-and-windows a)
|
|
||||||
(should-not (buffer-live-p a))
|
|
||||||
(should (= (length (doom-visible-windows)) 1))))
|
|
||||||
|
|
||||||
;; TODO doom/kill-all-buffers
|
|
||||||
;; TODO doom/kill-other-buffers
|
|
||||||
;; TODO doom/kill-matching-buffers
|
|
||||||
;; TODO doom/cleanup-session
|
|
|
@ -1,17 +0,0 @@
|
||||||
;; -*- no-byte-compile: t; -*-
|
|
||||||
;;; core/test/autoload-help.el
|
|
||||||
|
|
||||||
(def-test! what-face
|
|
||||||
(insert (propertize "Hello " 'face 'font-lock-keyword-face))
|
|
||||||
(insert "world")
|
|
||||||
|
|
||||||
(should (equal (doom/what-face (point-min)) '((font-lock-keyword-face) ())))
|
|
||||||
(should-not (doom/what-face (point-max))))
|
|
||||||
|
|
||||||
(def-test! what-face-overlays
|
|
||||||
(insert "Hello world")
|
|
||||||
(let ((ov (make-overlay 1 6)))
|
|
||||||
(overlay-put ov 'face 'font-lock-keyword-face))
|
|
||||||
|
|
||||||
(should (equal (doom/what-face (point-min)) '(() (font-lock-keyword-face))))
|
|
||||||
(should-not (doom/what-face (point-max))))
|
|
|
@ -1,41 +0,0 @@
|
||||||
;; -*- no-byte-compile: t; -*-
|
|
||||||
;;; core/test/autoload-message.el
|
|
||||||
|
|
||||||
;; ansi messages
|
|
||||||
(def-test! ansi-format
|
|
||||||
(let ((noninteractive t))
|
|
||||||
(should (equal (format! "Hello %s" "World")
|
|
||||||
"Hello World"))
|
|
||||||
(should (equal (format! (red "Hello %s" "World"))
|
|
||||||
"[31mHello World[0m"))
|
|
||||||
(should (equal (format! (green "Hello %s" "World"))
|
|
||||||
(format "\e[%dm%s\e[0m"
|
|
||||||
(cadr (assq 'green doom-message-fg))
|
|
||||||
"Hello World")))
|
|
||||||
(should (equal (format! (on-red "Hello %s" "World"))
|
|
||||||
(format "\e[%dm%s\e[0m"
|
|
||||||
(cadr (assq 'on-red doom-message-bg))
|
|
||||||
"Hello World")))
|
|
||||||
(should (equal (format! (bold "Hello %s" "World"))
|
|
||||||
(format "\e[%dm%s\e[0m"
|
|
||||||
(cadr (assq 'bold doom-message-fx))
|
|
||||||
"Hello World")))))
|
|
||||||
|
|
||||||
(def-test! ansi-format-nested
|
|
||||||
(let ((noninteractive t))
|
|
||||||
(should (equal (format! (bold (red "Hello %s" "World")))
|
|
||||||
(format "\e[%dm%s\e[0m" 1
|
|
||||||
(format "\e[%dm%s\e[0m" 31 "Hello World"))))
|
|
||||||
(should (equal (format! (on-red (bold "Hello %s" "World")))
|
|
||||||
(format "\e[%dm%s\e[0m" 41
|
|
||||||
(format "\e[%dm%s\e[0m" 1 "Hello World"))))
|
|
||||||
(should (equal (format! (dark (white "Hello %s" "World")))
|
|
||||||
(format "\e[%dm%s\e[0m" 2
|
|
||||||
(format "\e[%dm%s\e[0m" 37 "Hello World"))))))
|
|
||||||
|
|
||||||
(def-test! ansi-format-apply
|
|
||||||
(let ((noninteractive t))
|
|
||||||
(should (equal (format! (color 'red "Hello %s" "World"))
|
|
||||||
(format! (red "Hello %s" "World"))))
|
|
||||||
(should (equal (format! (color (if nil 'red 'blue) "Hello %s" "World"))
|
|
||||||
(format! (blue "Hello %s" "World"))))))
|
|
|
@ -1,72 +0,0 @@
|
||||||
;; -*- no-byte-compile: t; -*-
|
|
||||||
;;; core/test/autoload-package.el
|
|
||||||
|
|
||||||
(require 'package)
|
|
||||||
(require 'quelpa)
|
|
||||||
|
|
||||||
(defun -pkg (name version &optional reqs)
|
|
||||||
(package-desc-create :name name :version version :reqs reqs))
|
|
||||||
|
|
||||||
(defmacro with-packages!! (packages package-descs &rest body)
|
|
||||||
`(let* ((doom-packages-dir ,(expand-file-name "packages/" (file-name-directory load-file-name)))
|
|
||||||
(package-user-dir ,(expand-file-name "elpa" doom-packages-dir))
|
|
||||||
(quelpa-dir ,(expand-file-name "quelpa" doom-packages-dir)))
|
|
||||||
;; (make-directory doom-packages-dir t)
|
|
||||||
(let ((doom-packages ,packages)
|
|
||||||
(package-alist ,package-descs)
|
|
||||||
doom-core-packages)
|
|
||||||
(cl-letf (((symbol-function 'doom-initialize-packages) (lambda (&rest _))))
|
|
||||||
,@body))
|
|
||||||
;; (delete-directory doom-packages-dir t)
|
|
||||||
))
|
|
||||||
|
|
||||||
|
|
||||||
;;
|
|
||||||
;; Tests
|
|
||||||
;;
|
|
||||||
|
|
||||||
(def-test! backend-detection
|
|
||||||
(let ((package-alist `((doom-dummy ,(-pkg 'doom-dummy '(20160405 1234)))))
|
|
||||||
(quelpa-cache '((doom-quelpa-dummy :fetcher github :repo "hlissner/does-not-exist")))
|
|
||||||
(quelpa-initialized-p t))
|
|
||||||
(should (eq (doom-package-backend 'doom-dummy) 'elpa))
|
|
||||||
(should (eq (doom-package-backend 'doom-quelpa-dummy) 'quelpa))
|
|
||||||
(should (eq (doom-package-backend 'org) 'emacs))))
|
|
||||||
|
|
||||||
(def-test! elpa-outdated-detection
|
|
||||||
(let* ((package-alist
|
|
||||||
`((doom-dummy ,(-pkg 'doom-dummy '(20160405 1234)))))
|
|
||||||
(package-archive-contents
|
|
||||||
`((doom-dummy ,(-pkg 'doom-dummy '(20170405 1234))))))
|
|
||||||
(cl-letf (((symbol-function 'package-refresh-contents) (lambda (&rest _))))
|
|
||||||
(should (equal (doom-package-outdated-p 'doom-dummy)
|
|
||||||
'(doom-dummy (20160405 1234) (20170405 1234)))))))
|
|
||||||
|
|
||||||
;; TODO quelpa-outdated-detection
|
|
||||||
|
|
||||||
(def-test! get-packages
|
|
||||||
(let ((quelpa-initialized-p t))
|
|
||||||
(with-packages!!
|
|
||||||
'((doom-dummy))
|
|
||||||
'((doom-dummy nil)
|
|
||||||
(doom-dummy-unwanted nil)
|
|
||||||
(doom-dummy-dep nil))
|
|
||||||
(should (equal (doom-get-packages) '((doom-dummy)))))))
|
|
||||||
|
|
||||||
(def-test! orphaned-packages
|
|
||||||
"Test `doom-get-orphaned-packages', which gets a list of packages that are
|
|
||||||
no longer enabled or depended on."
|
|
||||||
(with-packages!!
|
|
||||||
'((doom-dummy))
|
|
||||||
`((doom-dummy ,(-pkg 'doom-dummy '(20160405 1234) '((doom-dummy-dep (1 0)))))
|
|
||||||
(doom-dummy-unwanted ,(-pkg 'doom-dummy-unwanted '(20160601 1234)))
|
|
||||||
(doom-dummy-dep ,(-pkg 'doom-dummy-dep '(20160301 1234))))
|
|
||||||
(should (equal (doom-get-orphaned-packages) '(doom-dummy-unwanted)))))
|
|
||||||
|
|
||||||
(def-test! missing-packages
|
|
||||||
"Test `doom-get-missing-packages, which gets a list of enabled packages that
|
|
||||||
aren't installed."
|
|
||||||
(with-packages!!
|
|
||||||
'((doom-dummy) (doom-dummy-installed))
|
|
||||||
`((doom-dummy-installed ,(-pkg 'doom-dummy-installed '(20160405 1234))))
|
|
||||||
(should (equal (doom-get-missing-packages) '((doom-dummy))))))
|
|
|
@ -1,116 +0,0 @@
|
||||||
;; -*- no-byte-compile: t; -*-
|
|
||||||
;;; core/test/core-lib.el
|
|
||||||
|
|
||||||
;; --- Helpers ----------------------------
|
|
||||||
|
|
||||||
;; `doom--resolve-path-forms'
|
|
||||||
(def-test! resolve-path-forms
|
|
||||||
(should
|
|
||||||
(equal (doom--resolve-path-forms '(and "fileA" "fileB"))
|
|
||||||
'(and (file-exists-p (expand-file-name "fileA" nil))
|
|
||||||
(file-exists-p (expand-file-name "fileB" nil))))))
|
|
||||||
|
|
||||||
;; `doom--resolve-hook-forms'
|
|
||||||
(def-test! resolve-hook-forms
|
|
||||||
(should (equal (doom--resolve-hook-forms '(js2-mode haskell-mode))
|
|
||||||
'(js2-mode-hook haskell-mode-hook)))
|
|
||||||
(should (equal (doom--resolve-hook-forms '(quote (js2-mode-hook haskell-mode-hook)))
|
|
||||||
'(js2-mode-hook haskell-mode-hook))))
|
|
||||||
|
|
||||||
;; `doom-unquote'
|
|
||||||
(def-test! unquote
|
|
||||||
(should (equal (doom-unquote '(quote (a b c))) '(a b c)))
|
|
||||||
;; nested
|
|
||||||
(should (equal (doom-unquote '(quote (quote (a b c)))) '(a b c)))
|
|
||||||
;; sub-quote
|
|
||||||
(should (equal (doom-unquote '(quote (a (quote b) c))) '(a (quote b) c)))
|
|
||||||
;; function
|
|
||||||
(should (equal (doom-unquote '(function a)) 'a)))
|
|
||||||
|
|
||||||
;; `doom-enlist'
|
|
||||||
(def-test! enlist
|
|
||||||
(should (equal (doom-enlist 'a) '(a)))
|
|
||||||
(should (equal (doom-enlist '(a)) '(a))))
|
|
||||||
|
|
||||||
|
|
||||||
;; --- Macros -----------------------------
|
|
||||||
|
|
||||||
;; `add-hook!'
|
|
||||||
(def-test! add-one-to-one-hook
|
|
||||||
(let ((hooks '(old-hook)))
|
|
||||||
(add-hook! 'hooks 'a-hook)
|
|
||||||
(should (equal hooks '(a-hook old-hook)))))
|
|
||||||
|
|
||||||
(def-test! add-many-to-one-hook
|
|
||||||
(let ((hooks '(hook-x)))
|
|
||||||
(add-hook! 'hooks '(hook-a hook-b hook-c))
|
|
||||||
(should (equal hooks '(hook-a hook-b hook-c hook-x)))))
|
|
||||||
|
|
||||||
(def-test! add-one-to-many-hooks
|
|
||||||
(let (hooks-a hooks-b hooks-c)
|
|
||||||
(add-hook! '(hooks-a hooks-b hooks-c) 'a-hook)
|
|
||||||
(should (equal hooks-a '(a-hook)))
|
|
||||||
(should (equal hooks-b '(a-hook)))
|
|
||||||
(should (equal hooks-c '(a-hook)))))
|
|
||||||
|
|
||||||
(def-test! add-many-to-many-hooks
|
|
||||||
(let (hooks-a hooks-b hooks-c)
|
|
||||||
(add-hook! '(hooks-a hooks-b hooks-c) '(hook-a hook-b hook-c))
|
|
||||||
(should (equal hooks-a '(hook-a hook-b hook-c)))
|
|
||||||
(should (equal hooks-b '(hook-a hook-b hook-c)))
|
|
||||||
(should (equal hooks-c '(hook-a hook-b hook-c)))))
|
|
||||||
|
|
||||||
(def-test! add-non-literal-hooks
|
|
||||||
(let (some-mode-hook)
|
|
||||||
(add-hook! some-mode 'a-hook)
|
|
||||||
(should (equal some-mode-hook '(a-hook)))))
|
|
||||||
|
|
||||||
;; `remove-hook!'
|
|
||||||
(def-test! remove-hooks
|
|
||||||
(let ((hooks-a '(hook-c hook-b hook-a))
|
|
||||||
(hooks-b '(hook-c hook-b hook-a))
|
|
||||||
(hooks-c '(hook-c hook-b hook-a)))
|
|
||||||
(remove-hook! '(hooks-a hooks-b hooks-c) '(hook-a hook-b hook-c))
|
|
||||||
(should (null hooks-a))
|
|
||||||
(should (null hooks-b))
|
|
||||||
(should (null hooks-c))))
|
|
||||||
|
|
||||||
(def-test! remove-hook-forms
|
|
||||||
(let (hooks)
|
|
||||||
(add-hook! 'hooks (message "Hello world"))
|
|
||||||
(should hooks)
|
|
||||||
(remove-hook! 'hooks (message "Hello world"))
|
|
||||||
(should (null hooks))))
|
|
||||||
|
|
||||||
;; `add-transient-hook!'
|
|
||||||
(def-test! transient-hooks
|
|
||||||
(let (hooks value)
|
|
||||||
(add-transient-hook! 'hooks (setq value t))
|
|
||||||
(run-hooks 'hooks)
|
|
||||||
(should (eq value t))
|
|
||||||
(should (null hooks))))
|
|
||||||
|
|
||||||
(def-test! transient-function
|
|
||||||
(let (value)
|
|
||||||
(add-transient-hook! #'ignore (setq value (not value)))
|
|
||||||
(ignore t)
|
|
||||||
(should (eq value t))
|
|
||||||
;; repeat to ensure it was only run once
|
|
||||||
(ignore t)
|
|
||||||
(should (eq value t))))
|
|
||||||
|
|
||||||
|
|
||||||
;; TODO `associate!'
|
|
||||||
|
|
||||||
|
|
||||||
;; --- Settings ---------------------------
|
|
||||||
|
|
||||||
(def-test! set
|
|
||||||
(eval-and-compile
|
|
||||||
(def-setting! :-test-setting (x) `(setq result ,x))
|
|
||||||
(should (fboundp 'doom--set:-test-setting))
|
|
||||||
(let ((inhibit-message t)
|
|
||||||
result)
|
|
||||||
(set! :-test-setting t)
|
|
||||||
(should result)
|
|
||||||
(set! :non-existant-setting (error "This shouldn't trigger")))))
|
|
|
@ -1,47 +0,0 @@
|
||||||
;; -*- no-byte-compile: t; -*-
|
|
||||||
;;; ../core/test/core-projects.el
|
|
||||||
|
|
||||||
(require 'projectile)
|
|
||||||
|
|
||||||
;;
|
|
||||||
;; `doom-project-p'
|
|
||||||
(def-test! project-p
|
|
||||||
:minor-mode projectile-mode
|
|
||||||
(let ((buffer-file-name (expand-file-name "init.el" doom-emacs-dir))
|
|
||||||
(default-directory doom-emacs-dir))
|
|
||||||
(should (doom-project-p)))
|
|
||||||
(let ((buffer-file-name (expand-file-name "test" "~"))
|
|
||||||
(default-directory (expand-file-name "~")))
|
|
||||||
(should-not (doom-project-p))))
|
|
||||||
|
|
||||||
;; `doom-project-root'
|
|
||||||
(def-test! project-root
|
|
||||||
:minor-mode projectile-mode
|
|
||||||
;; Should resolve to project root
|
|
||||||
(let ((buffer-file-name (expand-file-name "core.el" doom-core-dir))
|
|
||||||
(default-directory doom-core-dir))
|
|
||||||
(should (equal (doom-project-root) doom-emacs-dir)))
|
|
||||||
;; Should resolve to `default-directory' if not a project
|
|
||||||
(let ((buffer-file-name (expand-file-name "test" "~"))
|
|
||||||
(default-directory (expand-file-name "~")))
|
|
||||||
(should (equal (doom-project-root) default-directory))))
|
|
||||||
|
|
||||||
;; `doom-project-expand'
|
|
||||||
(def-test! project-expand
|
|
||||||
:minor-mode projectile-mode
|
|
||||||
(let ((default-directory doom-core-dir))
|
|
||||||
(should (equal (doom-project-expand "init.el")
|
|
||||||
(expand-file-name "init.el" (doom-project-root))))))
|
|
||||||
|
|
||||||
;; `project-file-exists-p!'
|
|
||||||
(def-test! project-has!
|
|
||||||
:minor-mode projectile-mode
|
|
||||||
(let ((default-directory doom-core-dir))
|
|
||||||
;; Resolve from project root
|
|
||||||
(should (project-file-exists-p! "init.el"))
|
|
||||||
;; Chained file checks
|
|
||||||
(should (project-file-exists-p! (and "init.el" "LICENSE")))
|
|
||||||
(should (project-file-exists-p! (or "init.el" "does-not-exist")))
|
|
||||||
(should (project-file-exists-p! (and "init.el" (or "LICENSE" "does-not-exist"))))
|
|
||||||
;; Should resolve relative paths from `default-directory'
|
|
||||||
(should (project-file-exists-p! (and "core/core.el" "./init.el")))))
|
|
|
@ -1,34 +0,0 @@
|
||||||
;; -*- no-byte-compile: t; -*-
|
|
||||||
;;; ../core/test/core-ui.el
|
|
||||||
|
|
||||||
(defmacro with-temp-windows!! (&rest body)
|
|
||||||
(declare (indent defun))
|
|
||||||
`(cl-flet ((split-window (symbol-function #'split-window-horizontally)))
|
|
||||||
(delete-other-windows)
|
|
||||||
(let ((a (get-buffer-create "a"))
|
|
||||||
(b (get-buffer-create "b"))
|
|
||||||
(split-width-threshold 0)
|
|
||||||
(window-min-width 0))
|
|
||||||
,@body)))
|
|
||||||
|
|
||||||
;;
|
|
||||||
(def-test! set-mode-name
|
|
||||||
(let ((after-change-major-mode-hook '(doom|set-mode-name))
|
|
||||||
(doom-major-mode-names '((text-mode . "abc")
|
|
||||||
(lisp-mode . (lambda () "xyz"))
|
|
||||||
(js-mode . t))))
|
|
||||||
(text-mode)
|
|
||||||
(should (equal mode-name "abc"))
|
|
||||||
(lisp-mode)
|
|
||||||
(should (equal mode-name "xyz"))
|
|
||||||
(should-error (js-mode))))
|
|
||||||
|
|
||||||
(def-test! protect-visible-buffers
|
|
||||||
(with-temp-windows!!
|
|
||||||
(let ((kill-buffer-query-functions '(doom|protect-visible-buffers)))
|
|
||||||
(switch-to-buffer a) (split-window)
|
|
||||||
(switch-to-buffer b) (split-window)
|
|
||||||
(switch-to-buffer a)
|
|
||||||
(should-not (kill-buffer))
|
|
||||||
(select-window (get-buffer-window b))
|
|
||||||
(should (kill-buffer)))))
|
|
114
core/test/test-autoload-buffers.el
Normal file
114
core/test/test-autoload-buffers.el
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
;; -*- no-byte-compile: t; -*-
|
||||||
|
;;; core/test/test-autoload-buffers.el
|
||||||
|
|
||||||
|
(load! "autoload/buffers" doom-core-dir)
|
||||||
|
|
||||||
|
;;
|
||||||
|
(describe "core/autoload/buffers"
|
||||||
|
:var (a b c d)
|
||||||
|
(before-all
|
||||||
|
(spy-on 'buffer-list :and-call-fake
|
||||||
|
(lambda (&optional _)
|
||||||
|
(cl-remove-if-not #'buffer-live-p (list a b c d)))))
|
||||||
|
(before-each
|
||||||
|
(delete-other-windows)
|
||||||
|
(setq a (switch-to-buffer (get-buffer-create "a"))
|
||||||
|
b (get-buffer-create "b")
|
||||||
|
c (get-buffer-create "c")
|
||||||
|
d (get-buffer-create "d")))
|
||||||
|
(after-each
|
||||||
|
(kill-buffer a)
|
||||||
|
(kill-buffer b)
|
||||||
|
(kill-buffer c)
|
||||||
|
(kill-buffer d))
|
||||||
|
|
||||||
|
(describe "buffer-list"
|
||||||
|
(it "should only see four buffers"
|
||||||
|
(expect (doom-buffer-list) :to-have-same-items-as (list a b c d))))
|
||||||
|
|
||||||
|
(describe "project-buffer-list"
|
||||||
|
:var (projectile-projects-cache-time projectile-projects-cache)
|
||||||
|
(before-all (require 'projectile))
|
||||||
|
(after-all (unload-feature 'projectile t))
|
||||||
|
|
||||||
|
(before-each
|
||||||
|
(with-current-buffer a (setq default-directory doom-emacs-dir))
|
||||||
|
(with-current-buffer b (setq default-directory doom-emacs-dir))
|
||||||
|
(with-current-buffer c (setq default-directory "/tmp/"))
|
||||||
|
(with-current-buffer d (setq default-directory "~"))
|
||||||
|
(projectile-mode +1))
|
||||||
|
(after-each
|
||||||
|
(projectile-mode -1))
|
||||||
|
|
||||||
|
(it "returns buffers in the same project"
|
||||||
|
(with-current-buffer a
|
||||||
|
(expect (doom-project-buffer-list)
|
||||||
|
:to-have-same-items-as (list a b))))
|
||||||
|
|
||||||
|
(it "returns all buffers if not in a project"
|
||||||
|
(with-current-buffer c
|
||||||
|
(expect (doom-project-buffer-list)
|
||||||
|
:to-have-same-items-as (buffer-list)))))
|
||||||
|
|
||||||
|
(describe "fallback-buffer"
|
||||||
|
(it "returns a live buffer"
|
||||||
|
(expect (buffer-live-p (doom-fallback-buffer)))))
|
||||||
|
|
||||||
|
(describe "real buffers"
|
||||||
|
(before-each
|
||||||
|
(doom-set-buffer-real a t)
|
||||||
|
(with-current-buffer b (setq buffer-file-name "x"))
|
||||||
|
(with-current-buffer c (rename-buffer "*C*")))
|
||||||
|
|
||||||
|
(describe "real-buffer-p"
|
||||||
|
(it "returns t for buffers manually marked real"
|
||||||
|
(expect (doom-real-buffer-p a)))
|
||||||
|
(it "returns t for file-visiting buffers"
|
||||||
|
(expect (doom-real-buffer-p b)))
|
||||||
|
(it "returns nil for temporary buffers"
|
||||||
|
(expect (doom-real-buffer-p c) :to-be nil)
|
||||||
|
(expect (doom-real-buffer-p d) :to-be nil)))
|
||||||
|
|
||||||
|
(describe "real-buffer-list"
|
||||||
|
(it "returns only real buffers"
|
||||||
|
(expect (doom-real-buffer-list) :to-have-same-items-as (list a b)))))
|
||||||
|
|
||||||
|
(describe "buffer/window management"
|
||||||
|
(describe "buffer search methods"
|
||||||
|
(before-each
|
||||||
|
(with-current-buffer a (lisp-mode))
|
||||||
|
(with-current-buffer b (text-mode))
|
||||||
|
(with-current-buffer c (text-mode))
|
||||||
|
(split-window)
|
||||||
|
(switch-to-buffer b))
|
||||||
|
|
||||||
|
(it "can match buffers by regexp"
|
||||||
|
(expect (doom-matching-buffers "^[ac]$") :to-have-same-items-as (list a c)))
|
||||||
|
(it "can match buffers by major-mode"
|
||||||
|
(expect (doom-buffers-in-mode 'text-mode) :to-have-same-items-as (list b c)))
|
||||||
|
(it "can find all buried buffers"
|
||||||
|
(expect (doom-buried-buffers)
|
||||||
|
:to-have-same-items-as (list c d)))
|
||||||
|
(it "can find all visible buffers"
|
||||||
|
(expect (doom-visible-buffers)
|
||||||
|
:to-have-same-items-as (list a b)))
|
||||||
|
(it "can find all visible windows"
|
||||||
|
(expect (doom-visible-windows)
|
||||||
|
:to-have-same-items-as
|
||||||
|
(mapcar #'get-buffer-window (list a b)))))
|
||||||
|
|
||||||
|
(describe "kill-buffer-and-windows"
|
||||||
|
(before-each
|
||||||
|
(split-window) (switch-to-buffer b)
|
||||||
|
(split-window) (switch-to-buffer a))
|
||||||
|
|
||||||
|
(it "kills the selected buffers and all its windows"
|
||||||
|
(doom-kill-buffer-and-windows a)
|
||||||
|
(expect (buffer-live-p a) :to-be nil)
|
||||||
|
(expect (length (doom-visible-windows)) :to-be 1)))
|
||||||
|
|
||||||
|
;; TODO
|
||||||
|
(describe "kill-all-buffers")
|
||||||
|
(describe "kill-other-buffers")
|
||||||
|
(describe "kill-matching-buffers")
|
||||||
|
(describe "cleanup-session")))
|
54
core/test/test-autoload-files.el
Normal file
54
core/test/test-autoload-files.el
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
;; -*- no-byte-compile: t; -*-
|
||||||
|
;;; core/test/test-autoload-files.el
|
||||||
|
|
||||||
|
(describe "core/autoload/files"
|
||||||
|
:var (src dest projectile-projects-cache-time projectile-projects-cache)
|
||||||
|
(before-all (require 'projectile))
|
||||||
|
(after-all (unload-feature 'projectile t))
|
||||||
|
|
||||||
|
(before-each
|
||||||
|
(setq src (make-temp-file "test-src")
|
||||||
|
existing (make-temp-file "test-existing")
|
||||||
|
dest (expand-file-name "test-dest" temporary-file-directory))
|
||||||
|
(quiet! (find-file-literally src))
|
||||||
|
(spy-on 'y-or-n-p :and-return-value nil)
|
||||||
|
(projectile-mode +1))
|
||||||
|
|
||||||
|
(after-each
|
||||||
|
(projectile-mode -1)
|
||||||
|
(switch-to-buffer (doom-fallback-buffer))
|
||||||
|
(ignore-errors (delete-file src))
|
||||||
|
(ignore-errors (delete-file existing))
|
||||||
|
(ignore-errors (delete-file dest)))
|
||||||
|
|
||||||
|
(describe "move-this-file"
|
||||||
|
(it "won't move to itself"
|
||||||
|
(expect (quiet! (doom/move-this-file src)) :to-throw))
|
||||||
|
(it "will move to another file"
|
||||||
|
(expect (quiet! (doom/move-this-file dest t)))
|
||||||
|
(expect (file-exists-p dest))
|
||||||
|
(expect (file-exists-p src) :to-be nil))
|
||||||
|
(it "will prompt if overwriting a file"
|
||||||
|
(quiet! (doom/move-this-file existing))
|
||||||
|
(expect 'y-or-n-p :to-have-been-called-times 1)
|
||||||
|
(expect (file-exists-p src))))
|
||||||
|
|
||||||
|
(describe "copy-this-file"
|
||||||
|
(it "refuses to copy to itself"
|
||||||
|
(expect (quiet! (doom/copy-this-file src)) :to-throw))
|
||||||
|
(it "copies to another file"
|
||||||
|
(expect (quiet! (doom/copy-this-file dest t)))
|
||||||
|
(expect (file-exists-p! src dest)))
|
||||||
|
(it "prompts if overwriting a file"
|
||||||
|
(quiet! (quiet! (doom/copy-this-file existing)))
|
||||||
|
(expect 'y-or-n-p :to-have-been-called-times 1)))
|
||||||
|
|
||||||
|
(describe "delete-this-file"
|
||||||
|
(it "fails gracefully on non-existent files"
|
||||||
|
(expect (quiet! (doom/delete-this-file dest)) :to-throw))
|
||||||
|
(it "deletes existing files"
|
||||||
|
(quiet! (doom/delete-this-file existing t))
|
||||||
|
(expect (file-exists-p existing) :to-be nil))
|
||||||
|
(it "prompts to delete any existing file"
|
||||||
|
(quiet! (doom/delete-this-file existing))
|
||||||
|
(expect 'y-or-n-p :to-have-been-called-times 1))))
|
31
core/test/test-autoload-help.el
Normal file
31
core/test/test-autoload-help.el
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
;; -*- no-byte-compile: t; -*-
|
||||||
|
;;; core/test/test-autoload-help.el
|
||||||
|
|
||||||
|
(load! "autoload/help" doom-core-dir)
|
||||||
|
|
||||||
|
;;
|
||||||
|
(describe "core/autoload/help"
|
||||||
|
:var (a)
|
||||||
|
(before-each (setq a (switch-to-buffer (get-buffer-create "a"))))
|
||||||
|
(after-each (kill-buffer a))
|
||||||
|
|
||||||
|
(describe "what-face"
|
||||||
|
(before-each
|
||||||
|
(insert (propertize "Hello " 'face 'font-lock-keyword-face))
|
||||||
|
(insert "world"))
|
||||||
|
(it "returns list of faces at point"
|
||||||
|
(expect (doom/what-face (point-min)) :to-equal '((font-lock-keyword-face) ())))
|
||||||
|
(it "returns nil if no faces at point"
|
||||||
|
(expect (doom/what-face (point-max)) :to-be nil)))
|
||||||
|
|
||||||
|
(describe "what-face overlays"
|
||||||
|
(before-each
|
||||||
|
(insert "Hello world")
|
||||||
|
(let ((ov (make-overlay 1 6)))
|
||||||
|
(overlay-put ov 'face 'font-lock-keyword-face)))
|
||||||
|
|
||||||
|
(it "returns list of overlays at point"
|
||||||
|
(expect (doom/what-face (point-min)) :to-equal '(() (font-lock-keyword-face))))
|
||||||
|
(it "returns nil if no overlays at point"
|
||||||
|
(expect (doom/what-face (point-max)) :to-be nil))))
|
||||||
|
|
37
core/test/test-autoload-message.el
Normal file
37
core/test/test-autoload-message.el
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
;; -*- no-byte-compile: t; -*-
|
||||||
|
;;; core/test/test-autoload-message.el
|
||||||
|
|
||||||
|
(describe "core/autoload/message"
|
||||||
|
(describe "format!"
|
||||||
|
:var (noninteractive)
|
||||||
|
(before-all (setq noninteractive t))
|
||||||
|
|
||||||
|
(it "should be a drop-in replacement for `format'"
|
||||||
|
(expect (format! "Hello %s" "World")
|
||||||
|
:to-equal "Hello World"))
|
||||||
|
|
||||||
|
(it "supports ansi coloring in noninteractive sessions"
|
||||||
|
(expect (format! (red "Hello %s" "World"))
|
||||||
|
:to-equal "[31mHello World[0m"))
|
||||||
|
|
||||||
|
(it "supports faces in interactive sessions"
|
||||||
|
(let (noninteractive)
|
||||||
|
(expect (get-text-property 0 'face (format! (red "Hello %s" "World")))
|
||||||
|
:to-equal (list :foreground (face-foreground 'term-color-red)))))
|
||||||
|
|
||||||
|
(it "supports nested color specs"
|
||||||
|
(expect (format! (bold (red "Hello %s" "World")))
|
||||||
|
:to-equal (format "\e[%dm%s\e[0m" 1
|
||||||
|
(format "\e[%dm%s\e[0m" 31 "Hello World")))
|
||||||
|
(expect (format! (on-red (bold "Hello %s" "World")))
|
||||||
|
:to-equal (format "\e[%dm%s\e[0m" 41
|
||||||
|
(format "\e[%dm%s\e[0m" 1 "Hello World")))
|
||||||
|
(expect (format! (dark (white "Hello %s" "World")))
|
||||||
|
:to-equal (format "\e[%dm%s\e[0m" 2
|
||||||
|
(format "\e[%dm%s\e[0m" 37 "Hello World"))))
|
||||||
|
|
||||||
|
(it "supports dynamic color apply syntax"
|
||||||
|
(expect (format! (color 'red "Hello %s" "World"))
|
||||||
|
:to-equal (format! (red "Hello %s" "World")))
|
||||||
|
(expect (format! (color (if nil 'red 'blue) "Hello %s" "World"))
|
||||||
|
:to-equal (format! (blue "Hello %s" "World"))))))
|
128
core/test/test-autoload-package.el
Normal file
128
core/test/test-autoload-package.el
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
;; -*- no-byte-compile: t; -*-
|
||||||
|
;;; core/test/test-autoload-package.el
|
||||||
|
|
||||||
|
(describe "core/autoload/packages"
|
||||||
|
:var (package-alist
|
||||||
|
package-archive-contents
|
||||||
|
doom-packages
|
||||||
|
quelpa-cache
|
||||||
|
quelpa-initialized-p
|
||||||
|
doom-packages-dir
|
||||||
|
doom-core-packages
|
||||||
|
package-user-dir
|
||||||
|
quelpa-dir
|
||||||
|
pkg)
|
||||||
|
|
||||||
|
(before-all
|
||||||
|
(fset 'pkg
|
||||||
|
(lambda (name version &optional reqs)
|
||||||
|
(package-desc-create :name name :version version :reqs reqs)))
|
||||||
|
(require 'package)
|
||||||
|
(require 'quelpa)
|
||||||
|
(setq doom-packages-dir (expand-file-name "packages/" (file-name-directory load-file-name))
|
||||||
|
package-user-dir (expand-file-name "elpa" doom-packages-dir)
|
||||||
|
quelpa-dir (expand-file-name "quelpa" doom-packages-dir)
|
||||||
|
quelpa-initialized-p t
|
||||||
|
doom-core-packages nil)
|
||||||
|
(spy-on #'doom-initialize-packages :and-call-fake (lambda (&optional _)))
|
||||||
|
(spy-on #'package-refresh-contents :and-call-fake (lambda (&optional _)))
|
||||||
|
(spy-on #'quelpa-checkout :and-call-fake
|
||||||
|
(lambda (rcp _dir)
|
||||||
|
(when (eq (car rcp) 'doom-quelpa-dummy)
|
||||||
|
"20170405.1234"))))
|
||||||
|
|
||||||
|
(after-all
|
||||||
|
(unload-feature 'package t)
|
||||||
|
(unload-feature 'quelpa t))
|
||||||
|
|
||||||
|
(before-each
|
||||||
|
(setq package-alist
|
||||||
|
`((doom-dummy ,(pkg 'doom-dummy '(20160405 1234)))
|
||||||
|
(doom-uptodate-dummy ,(pkg 'doom-uptodate-dummy '(20160605 1234)))
|
||||||
|
(doom-unwanted-dummy ,(pkg 'doom-unwanted-dummy '(20160605 1234)))
|
||||||
|
(doom-quelpa-dummy ,(pkg 'doom-quelpa-dummy '(20160405 1234)))
|
||||||
|
(doom-noquelpa-dummy ,(pkg 'doom-noquelpa-dummy '(20160405 1234))))
|
||||||
|
package-archive-contents
|
||||||
|
`((doom-dummy ,(pkg 'doom-dummy '(20170405 1234)))
|
||||||
|
(doom-uptodate-dummy ,(pkg 'doom-uptodate-dummy '(20160605 1234))))
|
||||||
|
doom-packages
|
||||||
|
'((doom-dummy)
|
||||||
|
(doom-uptodate-dummy)
|
||||||
|
(doom-missing-dummy)
|
||||||
|
(doom-noquelpa-dummy)
|
||||||
|
(doom-disabled-dummy :disable t)
|
||||||
|
(doom-private-dummy :private t)
|
||||||
|
(doom-disabled-private-dummy :private t :disable t)
|
||||||
|
(doom-quelpa-dummy :recipe (doom-quelpa-dummy :fetcher github :repo "hlissner/does-not-exist")))
|
||||||
|
quelpa-cache
|
||||||
|
'((doom-quelpa-dummy :fetcher github :repo "hlissner/does-not-exist")
|
||||||
|
(doom-noquelpa-dummy :fetcher github :repo "hlissner/does-not-exist-3")
|
||||||
|
(doom-new-quelpa-dummy :fetcher github :repo "hlissner/does-not-exist-2"))))
|
||||||
|
|
||||||
|
(describe "package-backend"
|
||||||
|
(it "determines the correct backend of a package"
|
||||||
|
(expect (doom-package-backend 'doom-dummy) :to-be 'elpa)
|
||||||
|
(expect (doom-package-backend 'doom-quelpa-dummy) :to-be 'quelpa)
|
||||||
|
(expect (doom-package-backend 'org) :to-be 'emacs))
|
||||||
|
(it "errors out if package isn't installed"
|
||||||
|
(expect (doom-package-backend 'xyz) :to-throw)))
|
||||||
|
|
||||||
|
(describe "package-outdated-p (elpa)"
|
||||||
|
(it "detects outdated ELPA packages and returns both versions"
|
||||||
|
(expect (doom-package-outdated-p 'doom-dummy)
|
||||||
|
:to-equal '(doom-dummy (20160405 1234) (20170405 1234))))
|
||||||
|
(it "ignores up-to-date ELPA packages"
|
||||||
|
(expect (doom-package-outdated-p 'doom-uptodate-dummy) :to-be nil))
|
||||||
|
|
||||||
|
(it "detects outdated QUELPA packages and returns both versions"
|
||||||
|
(expect (doom-package-outdated-p 'doom-quelpa-dummy)
|
||||||
|
:to-equal '(doom-quelpa-dummy (20160405 1234) (20170405 1234))))
|
||||||
|
(it "ignores up-to-date QUELPA packages"
|
||||||
|
(expect (doom-package-outdated-p 'doom-uptodate-dummy) :to-be nil))
|
||||||
|
|
||||||
|
(it "returns nil if package isn't installed"
|
||||||
|
(expect (doom-package-outdated-p 'xyz) :to-be nil)))
|
||||||
|
|
||||||
|
(describe "get-packages"
|
||||||
|
(it "returns all packages"
|
||||||
|
(expect (mapcar #'car (doom-get-packages))
|
||||||
|
:to-have-same-items-as
|
||||||
|
(mapcar #'car doom-packages)))
|
||||||
|
(it "returns only disabled packages"
|
||||||
|
(expect (mapcar #'car (doom-get-packages :disabled t))
|
||||||
|
:to-have-same-items-as
|
||||||
|
'(doom-disabled-dummy doom-disabled-private-dummy)))
|
||||||
|
(it "returns only non-disabled packages"
|
||||||
|
(expect (mapcar #'car (doom-get-packages :disabled nil))
|
||||||
|
:to-have-same-items-as
|
||||||
|
'(doom-dummy doom-uptodate-dummy doom-quelpa-dummy doom-missing-dummy doom-noquelpa-dummy doom-private-dummy)))
|
||||||
|
(it "returns only installed packages"
|
||||||
|
(expect (mapcar #'car (doom-get-packages :disabled nil :installed t))
|
||||||
|
:to-have-same-items-as
|
||||||
|
'(doom-dummy doom-uptodate-dummy doom-quelpa-dummy doom-noquelpa-dummy)))
|
||||||
|
(it "returns only non-installed packages"
|
||||||
|
(expect (mapcar #'car (doom-get-packages :disabled nil :installed nil))
|
||||||
|
:to-have-same-items-as
|
||||||
|
'(doom-missing-dummy doom-private-dummy)))
|
||||||
|
(it "returns only private packages"
|
||||||
|
(expect (mapcar #'car (doom-get-packages :private t))
|
||||||
|
:to-have-same-items-as
|
||||||
|
'(doom-private-dummy doom-disabled-private-dummy)))
|
||||||
|
(it "returns only disabled and private packages"
|
||||||
|
(expect (mapcar #'car (doom-get-packages :disabled t :private t))
|
||||||
|
:to-have-same-items-as
|
||||||
|
'(doom-disabled-private-dummy))))
|
||||||
|
|
||||||
|
(describe "get-orphaned-packages"
|
||||||
|
(it "returns orphaned packages"
|
||||||
|
(expect (doom-get-orphaned-packages) :to-contain 'doom-unwanted-dummy))
|
||||||
|
(it "returns packages that have changed backends"
|
||||||
|
(expect (doom-get-orphaned-packages) :to-contain 'doom-noquelpa-dummy)))
|
||||||
|
|
||||||
|
(describe "get-missing-packages"
|
||||||
|
(it "returns packages that haven't been installed"
|
||||||
|
(expect (mapcar #'car (doom-get-missing-packages))
|
||||||
|
:to-contain 'doom-missing-dummy))
|
||||||
|
(it "returns packages that have changed backends"
|
||||||
|
(expect (mapcar #'car (doom-get-missing-packages))
|
||||||
|
:to-contain 'doom-noquelpa-dummy))))
|
90
core/test/test-core-lib.el
Normal file
90
core/test/test-core-lib.el
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
;; -*- no-byte-compile: t; -*-
|
||||||
|
;;; core/test/test-core-lib.el
|
||||||
|
|
||||||
|
(describe "core/lib"
|
||||||
|
;; --- Helpers ----------------------------
|
||||||
|
(describe "doom-unquote"
|
||||||
|
(it "unquotes a quoted form"
|
||||||
|
(expect (doom-unquote '(quote hello)) :to-be 'hello))
|
||||||
|
(it "unquotes nested-quoted forms"
|
||||||
|
(expect (doom-unquote '(quote (quote (a b c)))) :to-equal '(a b c)))
|
||||||
|
(it "unquotes function-quoted forms"
|
||||||
|
(expect (doom-unquote '(function a)) :to-be 'a))
|
||||||
|
(it "does nothing to unquoted forms"
|
||||||
|
(expect (doom-unquote 'hello) :to-be 'hello)))
|
||||||
|
|
||||||
|
(describe "doom-enlist"
|
||||||
|
(it "creates a list out of non-lists"
|
||||||
|
(expect (doom-enlist 'a) :to-equal '(a)))
|
||||||
|
(it "does nothing to lists"
|
||||||
|
(expect (doom-enlist '(a)) :to-equal '(a))))
|
||||||
|
|
||||||
|
|
||||||
|
;; --- Macros -----------------------------
|
||||||
|
(describe "hooks"
|
||||||
|
(describe "add-hook!"
|
||||||
|
:var (fake-mode-hook other-mode-hook some-mode-hook)
|
||||||
|
(before-each
|
||||||
|
(setq fake-mode-hook '(first-hook)
|
||||||
|
other-mode-hook nil
|
||||||
|
some-mode-hook '(first-hook second-hook)))
|
||||||
|
|
||||||
|
(it "adds one-to-one hook"
|
||||||
|
(add-hook! fake-mode #'hook-2)
|
||||||
|
(add-hook! 'fake-mode-hook #'hook-1)
|
||||||
|
(expect fake-mode-hook :to-equal '(hook-1 hook-2 first-hook)))
|
||||||
|
|
||||||
|
(it "adds many-to-one hook"
|
||||||
|
(add-hook! (fake-mode other-mode some-mode) #'hook-2)
|
||||||
|
(add-hook! '(fake-mode-hook other-mode-hook some-mode-hook) #'hook-1)
|
||||||
|
(add-hook! :append (fake-mode other-mode some-mode) #'last-hook)
|
||||||
|
(expect fake-mode-hook :to-equal '(hook-1 hook-2 first-hook last-hook))
|
||||||
|
(expect other-mode-hook :to-equal '(hook-1 hook-2 last-hook))
|
||||||
|
(expect some-mode-hook :to-equal '(hook-1 hook-2 first-hook second-hook last-hook)))
|
||||||
|
|
||||||
|
(it "adds many-to-many hooks and preserve provided order"
|
||||||
|
(add-hook! (fake-mode other-mode some-mode) #'(hook-3 hook-4))
|
||||||
|
(add-hook! '(fake-mode-hook other-mode-hook some-mode-hook) #'(hook-1 hook-2))
|
||||||
|
(add-hook! :append '(fake-mode-hook other-mode-hook some-mode-hook) #'(last-hook-1 last-hook-2))
|
||||||
|
(expect fake-mode-hook :to-equal '(hook-1 hook-2 hook-3 hook-4 first-hook last-hook-1 last-hook-2))
|
||||||
|
(expect other-mode-hook :to-equal '(hook-1 hook-2 hook-3 hook-4 last-hook-1 last-hook-2))
|
||||||
|
(expect some-mode-hook :to-equal '(hook-1 hook-2 hook-3 hook-4 first-hook second-hook last-hook-1 last-hook-2)))
|
||||||
|
|
||||||
|
(it "adds implicit lambda to one hook"
|
||||||
|
(add-hook! fake-mode (progn))
|
||||||
|
(add-hook! 'other-mode-hook (ignore))
|
||||||
|
(add-hook! :append 'some-mode-hook (ignore))
|
||||||
|
(expect (caar fake-mode-hook) :to-be 'lambda)
|
||||||
|
(expect (caar other-mode-hook) :to-be 'lambda)
|
||||||
|
(expect (caar (last other-mode-hook)) :to-be 'lambda)))
|
||||||
|
|
||||||
|
(describe "remove-hook!"
|
||||||
|
:var (fake-mode-hook)
|
||||||
|
(before-each
|
||||||
|
(setq fake-mode-hook '(first-hook second-hook third-hook fourth-hook)))
|
||||||
|
(it "removes one hook"
|
||||||
|
(remove-hook! fake-mode #'third-hook)
|
||||||
|
(remove-hook! 'fake-mode-hook #'second-hook)
|
||||||
|
(expect fake-mode-hook :to-equal '(first-hook fourth-hook)))
|
||||||
|
(it "removes multiple hooks"
|
||||||
|
(remove-hook! fake-mode #'(first-hook third-hook))
|
||||||
|
(remove-hook! 'fake-mode-hook #'(second-hook fourth-hook))
|
||||||
|
(expect fake-mode-hook :to-be nil))))
|
||||||
|
|
||||||
|
(describe "add-transient-hook!"
|
||||||
|
(it "adds a transient function to hooks"
|
||||||
|
(let (hooks value)
|
||||||
|
(add-transient-hook! 'hooks (setq value t))
|
||||||
|
(run-hooks 'hooks)
|
||||||
|
(expect value)
|
||||||
|
(expect hooks :to-be nil)))
|
||||||
|
(it "advises a function with a transient advisor"
|
||||||
|
(let (value)
|
||||||
|
(add-transient-hook! #'ignore (setq value (not value)))
|
||||||
|
(ignore t)
|
||||||
|
(expect value)
|
||||||
|
;; repeat to ensure it was only run once
|
||||||
|
(ignore t)
|
||||||
|
(expect value))))
|
||||||
|
|
||||||
|
(xdescribe "associate!")) ; TODO
|
4
core/test/test-core-modules.el
Normal file
4
core/test/test-core-modules.el
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
;; -*- no-byte-compile: t; -*-
|
||||||
|
;;; core/test/test-core-modules.el
|
||||||
|
|
||||||
|
(describe "core-modules")
|
4
core/test/test-core-packages.el
Normal file
4
core/test/test-core-packages.el
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
;; -*- no-byte-compile: t; -*-
|
||||||
|
;;; core/test/test-core-packages.el
|
||||||
|
|
||||||
|
(describe "core-packages")
|
46
core/test/test-core-projects.el
Normal file
46
core/test/test-core-projects.el
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
;; -*- no-byte-compile: t; -*-
|
||||||
|
;;; ../core/test/test-core-projects.el
|
||||||
|
|
||||||
|
(require 'core-projects)
|
||||||
|
|
||||||
|
(describe "core/projects"
|
||||||
|
(before-all (require 'projectile))
|
||||||
|
(after-all (unload-feature 'projectile t))
|
||||||
|
|
||||||
|
(before-each (projectile-mode +1))
|
||||||
|
(after-each (projectile-mode -1))
|
||||||
|
|
||||||
|
(describe "project-p"
|
||||||
|
(it "Should detect when in a valid project"
|
||||||
|
(let ((buffer-file-name (expand-file-name "init.el" doom-emacs-dir))
|
||||||
|
(default-directory doom-emacs-dir))
|
||||||
|
(expect (doom-project-p))))
|
||||||
|
(it "Should detect when not in a valid project"
|
||||||
|
(let ((buffer-file-name (expand-file-name "test" "~"))
|
||||||
|
(default-directory (expand-file-name "~")))
|
||||||
|
(expect (doom-project-p) :to-be nil))))
|
||||||
|
|
||||||
|
(describe "project-root"
|
||||||
|
(it "should resolve to the project's root"
|
||||||
|
(let ((buffer-file-name (expand-file-name "core.el" doom-core-dir))
|
||||||
|
(default-directory doom-core-dir))
|
||||||
|
(expect (doom-project-root) :to-equal doom-emacs-dir)))
|
||||||
|
(it "should resolve to the `default-directory'"
|
||||||
|
(let ((buffer-file-name (expand-file-name "test" "/"))
|
||||||
|
(default-directory (expand-file-name "/")))
|
||||||
|
(expect (doom-project-root) :to-equal default-directory))))
|
||||||
|
|
||||||
|
(describe "project-expand"
|
||||||
|
(it "expands to a path relative to the project root"
|
||||||
|
(let ((default-directory doom-core-dir))
|
||||||
|
(expect (doom-project-expand "init.el")
|
||||||
|
:to-equal (expand-file-name "init.el" (doom-project-root))))))
|
||||||
|
|
||||||
|
(describe "project-file-exists-p!"
|
||||||
|
(let ((default-directory doom-core-dir))
|
||||||
|
;; Resolve from project root
|
||||||
|
(expect (project-file-exists-p! "init.el"))
|
||||||
|
;; Chained file checks
|
||||||
|
(expect (project-file-exists-p! (and "init.el" "LICENSE")))
|
||||||
|
(expect (project-file-exists-p! (or "init.el" "does-not-exist")))
|
||||||
|
(expect (project-file-exists-p! (and "init.el" (or "LICENSE" "does-not-exist")))))))
|
132
core/test/test-core-ui.el
Normal file
132
core/test/test-core-ui.el
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
;; -*- no-byte-compile: t; -*-
|
||||||
|
;;; ../core/test/test-core-ui.el
|
||||||
|
|
||||||
|
(describe "core/ui"
|
||||||
|
(describe "doom|set-mode-name"
|
||||||
|
:var (doom-major-mode-names after-change-major-mode-hook)
|
||||||
|
(before-all
|
||||||
|
(setq doom-major-mode-names
|
||||||
|
'((text-mode . "abc")
|
||||||
|
(lisp-mode . (lambda () "xyz"))
|
||||||
|
(js-mode . t))
|
||||||
|
after-change-major-mode-hook '(doom|set-mode-name)))
|
||||||
|
|
||||||
|
(it "changes `mode-name' to match a given string"
|
||||||
|
(text-mode)
|
||||||
|
(expect mode-name :to-equal "abc"))
|
||||||
|
|
||||||
|
(it "changes `mode-name' to the result of a function"
|
||||||
|
(lisp-mode)
|
||||||
|
(expect mode-name :to-equal "xyz"))
|
||||||
|
|
||||||
|
(it "should fail if given an invalid name"
|
||||||
|
(expect (js-mode) :to-throw 'error)))
|
||||||
|
|
||||||
|
|
||||||
|
(describe "doom|protect-visible-buffers"
|
||||||
|
:var (kill-buffer-query-functions wconf a b)
|
||||||
|
(before-each
|
||||||
|
(setq a (switch-to-buffer (get-buffer-create "a"))
|
||||||
|
b (get-buffer-create "b")
|
||||||
|
kill-buffer-query-functions '(doom|protect-visible-buffers)
|
||||||
|
wconf (current-window-configuration))
|
||||||
|
(delete-other-windows))
|
||||||
|
|
||||||
|
(after-each
|
||||||
|
(let (kill-buffer-query-functions kill-buffer-hook)
|
||||||
|
(kill-buffer a)
|
||||||
|
(kill-buffer b))
|
||||||
|
(set-window-configuration wconf))
|
||||||
|
|
||||||
|
(it "shouldn't kill buffers that are visible in more than one window"
|
||||||
|
(with-temp-buffer-window
|
||||||
|
(switch-to-buffer a) (split-window)
|
||||||
|
(switch-to-buffer b) (split-window)
|
||||||
|
(switch-to-buffer a)
|
||||||
|
(expect (kill-buffer) :to-be nil)
|
||||||
|
|
||||||
|
(select-window (get-buffer-window b))
|
||||||
|
(expect (kill-buffer)))))
|
||||||
|
|
||||||
|
|
||||||
|
(describe "doom|protect-fallback-buffer"
|
||||||
|
:var (kill-buffer-query-functions a b)
|
||||||
|
(before-all
|
||||||
|
(setq kill-buffer-query-functions '(doom|protect-fallback-buffer)))
|
||||||
|
|
||||||
|
(it "should kill other buffers"
|
||||||
|
(expect (kill-buffer (get-buffer-create "a"))))
|
||||||
|
|
||||||
|
(it "shouldn't kill the fallback buffer"
|
||||||
|
(expect (not (kill-buffer (doom-fallback-buffer))))))
|
||||||
|
|
||||||
|
|
||||||
|
(describe "switch hooks"
|
||||||
|
:var (before-hook after-hook a b)
|
||||||
|
(before-each
|
||||||
|
(setq a (switch-to-buffer (get-buffer-create "a"))
|
||||||
|
b (get-buffer-create "b"))
|
||||||
|
(spy-on 'before-hook)
|
||||||
|
(spy-on 'after-hook)
|
||||||
|
(doom|init-custom-hooks))
|
||||||
|
(after-each
|
||||||
|
(doom|init-custom-hooks 'disable)
|
||||||
|
(kill-buffer a)
|
||||||
|
(kill-buffer b))
|
||||||
|
|
||||||
|
|
||||||
|
(describe "switch-buffer"
|
||||||
|
:var (doom-before-switch-buffer-hook
|
||||||
|
doom-after-switch-buffer-hook)
|
||||||
|
(before-each
|
||||||
|
(setq doom-before-switch-buffer-hook '(before-hook)
|
||||||
|
doom-after-switch-buffer-hook '(after-hook)))
|
||||||
|
(after-each
|
||||||
|
(setq doom-before-switch-buffer-hook nil
|
||||||
|
doom-after-switch-buffer-hook nil))
|
||||||
|
|
||||||
|
(it "should trigger when switching buffers"
|
||||||
|
(switch-to-buffer b)
|
||||||
|
(switch-to-buffer a)
|
||||||
|
(switch-to-buffer b)
|
||||||
|
(expect 'before-hook :to-have-been-called-times 3)
|
||||||
|
(expect 'after-hook :to-have-been-called-times 3))
|
||||||
|
|
||||||
|
(it "should trigger only once on the same buffer"
|
||||||
|
(switch-to-buffer b)
|
||||||
|
(switch-to-buffer b)
|
||||||
|
(switch-to-buffer a)
|
||||||
|
(expect 'before-hook :to-have-been-called-times 2)
|
||||||
|
(expect 'after-hook :to-have-been-called-times 2)))
|
||||||
|
|
||||||
|
|
||||||
|
(describe "switch-window"
|
||||||
|
:var (doom-before-switch-window-hook
|
||||||
|
doom-after-switch-window-hook
|
||||||
|
x y)
|
||||||
|
(before-each
|
||||||
|
(delete-other-windows)
|
||||||
|
(setq x (get-buffer-window a)
|
||||||
|
y (save-selected-window (split-window)))
|
||||||
|
(with-selected-window y
|
||||||
|
(switch-to-buffer b))
|
||||||
|
(select-window x)
|
||||||
|
(spy-calls-reset 'before-hook)
|
||||||
|
(spy-calls-reset 'after-hook)
|
||||||
|
(setq doom-before-switch-window-hook '(before-hook)
|
||||||
|
doom-after-switch-window-hook '(after-hook)))
|
||||||
|
|
||||||
|
(it "should trigger when switching windows"
|
||||||
|
(select-window y)
|
||||||
|
(select-window x)
|
||||||
|
(select-window y)
|
||||||
|
(expect 'before-hook :to-have-been-called-times 3)
|
||||||
|
(expect 'after-hook :to-have-been-called-times 3))
|
||||||
|
|
||||||
|
(it "should trigger only once on the same window"
|
||||||
|
(select-window y)
|
||||||
|
(select-window y)
|
||||||
|
(select-window x)
|
||||||
|
(expect 'before-hook :to-have-been-called-times 2)
|
||||||
|
(expect 'after-hook :to-have-been-called-times 2)))))
|
||||||
|
|
56
core/test/test-core.el
Normal file
56
core/test/test-core.el
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
;; -*- no-byte-compile: t; -*-
|
||||||
|
;;; core/test/test-core.el
|
||||||
|
|
||||||
|
(xdescribe "core"
|
||||||
|
(describe "initialize"
|
||||||
|
:var (doom-init-p doom-init-modules-p doom-private-dir)
|
||||||
|
(before-each
|
||||||
|
(setq doom-init-p nil
|
||||||
|
doom-init-modules-p nil
|
||||||
|
doom-private-dir doom-emacs-dir)
|
||||||
|
|
||||||
|
(spy-on 'require)
|
||||||
|
(spy-on 'load)
|
||||||
|
(spy-on 'doom//reload-doom-autoloads)
|
||||||
|
(spy-on 'doom//reload-package-autoloads)
|
||||||
|
(spy-on 'doom-initialize-autoloads)
|
||||||
|
(spy-on 'doom-ensure-core-directories)
|
||||||
|
(spy-on 'doom-ensure-core-packages)
|
||||||
|
(spy-on 'doom-ensure-packages-initialized)
|
||||||
|
(spy-on 'doom-ensure-same-emacs-version-p))
|
||||||
|
|
||||||
|
(describe "in interactive session"
|
||||||
|
:var (noninteractive)
|
||||||
|
(before-each (setq noninteractive t))
|
||||||
|
|
||||||
|
(it "initializes once, unless forced")
|
||||||
|
(it "does not initialize on consecutive invokations")
|
||||||
|
(it "loads all core libraries" )
|
||||||
|
(it "loads autoloads file" )
|
||||||
|
(it "does not load autoloads file if forced" )
|
||||||
|
(it "regenerates missing autoloads" ))
|
||||||
|
|
||||||
|
(describe "in non-interactive session"
|
||||||
|
:var (noninteractive)
|
||||||
|
(before-each (setq noninteractive nil))
|
||||||
|
|
||||||
|
(it "initializes once, unless forced")
|
||||||
|
(it "does not initialize on consecutive invokations")
|
||||||
|
(it "does not load all core libraries" )
|
||||||
|
(it "loads autoloads file" )
|
||||||
|
(it "does not load autoloads file if forced" )
|
||||||
|
(it "does not regenerate missing autoloads" )))
|
||||||
|
|
||||||
|
(describe "initialize-packages"
|
||||||
|
(before-each (spy-on 'quelpa-setup-p))
|
||||||
|
|
||||||
|
(it "initializes package.el once, unless forced" )
|
||||||
|
(it "initializes quelpa once, unless forced" )
|
||||||
|
(it "initializes doom-packages once, unless forced" ))
|
||||||
|
|
||||||
|
(describe "initialize-modules"
|
||||||
|
(it "loads private init.el once, unless forced" ))
|
||||||
|
|
||||||
|
(describe "initialize-autoloads"
|
||||||
|
(it "loads autoloads file" )
|
||||||
|
(it "ignores autoloads file if cleared" )))
|
|
@ -1,21 +0,0 @@
|
||||||
;; -*- lexical-binding: t; no-byte-compile: t; -*-
|
|
||||||
;;; completion/company/test/company.el
|
|
||||||
|
|
||||||
;;
|
|
||||||
(def-test! set-company-backend
|
|
||||||
:minor-mode company-mode
|
|
||||||
(let ((company-backends '(default)))
|
|
||||||
(set! :company-backend 'emacs-lisp-mode '(backend-1))
|
|
||||||
(set! :company-backend 'lisp-interaction-mode 'backend-1 'backend-2)
|
|
||||||
(set! :company-backend 'text-mode 'backend-1)
|
|
||||||
(with-temp-buffer
|
|
||||||
(emacs-lisp-mode)
|
|
||||||
(should (equal company-backends '((backend-1) default))))
|
|
||||||
(with-temp-buffer
|
|
||||||
(lisp-interaction-mode)
|
|
||||||
(should (equal company-backends '(backend-1 backend-2 default))))
|
|
||||||
(with-temp-buffer
|
|
||||||
(text-mode)
|
|
||||||
(should (equal company-backends '(backend-1 default))))
|
|
||||||
;; global backends shouldn't be affected
|
|
||||||
(should (equal company-backends '(default)))))
|
|
44
modules/completion/company/test/test-company.el
Normal file
44
modules/completion/company/test/test-company.el
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
;; -*- lexical-binding: t; no-byte-compile: t; -*-
|
||||||
|
;;; completion/company/test/test-company.el
|
||||||
|
|
||||||
|
(load! "../autoload")
|
||||||
|
|
||||||
|
;;
|
||||||
|
(xdescribe "completion/company"
|
||||||
|
:var (company-backends)
|
||||||
|
|
||||||
|
(before-all
|
||||||
|
(provide 'company))
|
||||||
|
(after-all
|
||||||
|
(unload-feature 'company t))
|
||||||
|
|
||||||
|
(describe ":company-backend"
|
||||||
|
:var (text-mode-hook company-backends)
|
||||||
|
(before-each
|
||||||
|
(setq company-backends '(default)
|
||||||
|
text-mode-hook nil))
|
||||||
|
|
||||||
|
(it "adds grouped backends"
|
||||||
|
(set-company-backend! 'text-mode '(backend-1))
|
||||||
|
(with-temp-buffer
|
||||||
|
(text-mode)
|
||||||
|
(expect company-backends :to-equal '((backend-1) default))))
|
||||||
|
|
||||||
|
(it "adds multiple backends"
|
||||||
|
(set-company-backend! 'text-mode 'backend-1 'backend-2)
|
||||||
|
(with-temp-buffer
|
||||||
|
(text-mode)
|
||||||
|
(expect company-backends :to-equal '(backend-1 backend-2 default))))
|
||||||
|
|
||||||
|
(it "adds single backend"
|
||||||
|
(set-company-backend! 'text-mode 'backend-1)
|
||||||
|
(with-temp-buffer
|
||||||
|
(text-mode)
|
||||||
|
(expect company-backends :to-equal '(backend-1 default))))
|
||||||
|
|
||||||
|
(it "overwrites past values"
|
||||||
|
(set-company-backend! 'text-mode 'backend-1)
|
||||||
|
(set-company-backend! 'text-mode 'backend-2)
|
||||||
|
(with-temp-buffer
|
||||||
|
(text-mode)
|
||||||
|
(expect company-backends :to-equal '(backend-2 default))))))
|
|
@ -18,6 +18,36 @@
|
||||||
`(set-evil-initial-state! ,modes ,state))
|
`(set-evil-initial-state! ,modes ,state))
|
||||||
|
|
||||||
|
|
||||||
|
;;
|
||||||
|
;; Custom arguments / interactive codes
|
||||||
|
;;
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(after! evil
|
||||||
|
;; These arg types will highlight matches in the current buffer
|
||||||
|
(evil-ex-define-argument-type buffer-match :runner +evil-ex-buffer-match)
|
||||||
|
(evil-ex-define-argument-type global-match :runner +evil-ex-global-match)
|
||||||
|
;; Other commands can make use of this
|
||||||
|
(evil-define-interactive-code "<//>"
|
||||||
|
:ex-arg buffer-match (list (if (evil-ex-p) evil-ex-argument)))
|
||||||
|
(macroexpand '
|
||||||
|
(evil-define-interactive-code "<//g>"
|
||||||
|
:ex-arg global-match (list (if (evil-ex-p) evil-ex-argument))))
|
||||||
|
|
||||||
|
;; By default :g[lobal] doesn't highlight matches in the current buffer. I've
|
||||||
|
;; got to write my own argument type and interactive code to get it to do so.
|
||||||
|
(evil-ex-define-argument-type global-delim-match :runner +evil-ex-global-delim-match)
|
||||||
|
(dolist (sym '(evil-ex-global evil-ex-global-inverted))
|
||||||
|
(evil-set-command-property sym :ex-arg 'global-delim-match))
|
||||||
|
|
||||||
|
;; Forward declare these so that ex completion works, even if the autoloaded
|
||||||
|
;; functions aren't loaded yet.
|
||||||
|
(evil-set-command-properties
|
||||||
|
'+evil:align :move-point t :ex-arg 'buffer-match :ex-bang t :evil-mc t :keep-visual t :suppress-operator t)
|
||||||
|
(evil-set-command-properties
|
||||||
|
'+evil:mc :move-point nil :ex-arg 'global-match :ex-bang t :evil-mc t))
|
||||||
|
|
||||||
|
|
||||||
;;
|
;;
|
||||||
;; Commands
|
;; Commands
|
||||||
;;
|
;;
|
||||||
|
|
|
@ -141,28 +141,6 @@ variable for an explanation of the defaults (in comments). See
|
||||||
(advice-add #'evil-window-split :override #'+evil*window-split)
|
(advice-add #'evil-window-split :override #'+evil*window-split)
|
||||||
(advice-add #'evil-window-vsplit :override #'+evil*window-vsplit)
|
(advice-add #'evil-window-vsplit :override #'+evil*window-vsplit)
|
||||||
|
|
||||||
;; By default :g[lobal] doesn't highlight matches in the current buffer. I've
|
|
||||||
;; got to write my own argument type and interactive code to get it to do so.
|
|
||||||
(evil-ex-define-argument-type global-delim-match :runner +evil-ex-global-delim-match)
|
|
||||||
(dolist (sym '(evil-ex-global evil-ex-global-inverted))
|
|
||||||
(evil-set-command-property sym :ex-arg 'global-delim-match))
|
|
||||||
|
|
||||||
;; These arg types will highlight matches in the current buffer
|
|
||||||
(evil-ex-define-argument-type buffer-match :runner +evil-ex-buffer-match)
|
|
||||||
(evil-ex-define-argument-type global-match :runner +evil-ex-global-match)
|
|
||||||
;; Other commands can make use of this
|
|
||||||
(evil-define-interactive-code "<//>"
|
|
||||||
:ex-arg buffer-match (list (if (evil-ex-p) evil-ex-argument)))
|
|
||||||
(evil-define-interactive-code "<//g>"
|
|
||||||
:ex-arg global-match (list (if (evil-ex-p) evil-ex-argument)))
|
|
||||||
|
|
||||||
;; Forward declare these so that ex completion works, even if the autoloaded
|
|
||||||
;; functions aren't loaded yet.
|
|
||||||
(evil-set-command-properties
|
|
||||||
'+evil:align :move-point t :ex-arg 'buffer-match :ex-bang t :evil-mc t :keep-visual t :suppress-operator t)
|
|
||||||
(evil-set-command-properties
|
|
||||||
'+evil:mc :move-point nil :ex-arg 'global-match :ex-bang t :evil-mc t)
|
|
||||||
|
|
||||||
;; Ensure jump points are created
|
;; Ensure jump points are created
|
||||||
(defun +evil*set-jump (&rest _)
|
(defun +evil*set-jump (&rest _)
|
||||||
(evil-set-jump))
|
(evil-set-jump))
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
;; -*- no-byte-compile: t; -*-
|
|
||||||
;;; feature/evil/test/autoload-files.el
|
|
||||||
|
|
||||||
(defmacro with-temp-files!! (src dest &rest body)
|
|
||||||
"Run FORMS in the context of a temporary package setup (as in, it won't
|
|
||||||
affects your Emacs packages)."
|
|
||||||
(declare (indent 2) (doc-string 3))
|
|
||||||
`(let ((it ,src)
|
|
||||||
(other ,dest))
|
|
||||||
(with-temp-file it
|
|
||||||
(insert "Hello world"))
|
|
||||||
(with-minor-mode! projectile-mode
|
|
||||||
(unwind-protect
|
|
||||||
(progn
|
|
||||||
(should (file-exists-p it))
|
|
||||||
(find-file-literally it)
|
|
||||||
(should (equal (buffer-string) "Hello world"))
|
|
||||||
(should (equal (buffer-file-name) it))
|
|
||||||
(let ((inhibit-message (not doom-debug-mode)))
|
|
||||||
,@body))
|
|
||||||
(ignore-errors (delete-file it))
|
|
||||||
,(if dest `(ignore-errors (delete-file other)))))))
|
|
||||||
|
|
||||||
;;
|
|
||||||
(def-test! move-this-file
|
|
||||||
":mv"
|
|
||||||
(with-temp-files!! "/tmp/doom-buffer" "/tmp/doom-buffer-new"
|
|
||||||
(should-error (+evil:move-this-file it))
|
|
||||||
(should (+evil:move-this-file other t))
|
|
||||||
(should (file-exists-p other))
|
|
||||||
(should (not (file-exists-p it)))))
|
|
||||||
|
|
||||||
(def-test! copy-this-file
|
|
||||||
":cp"
|
|
||||||
(with-temp-files!! "/tmp/doom-buffer-2" "/tmp/doom-buffer-2-new"
|
|
||||||
(should-error (+evil:copy-this-file it))
|
|
||||||
(should (+evil:copy-this-file other t))
|
|
||||||
(should (file-exists-p other))
|
|
||||||
(should (file-exists-p it))))
|
|
||||||
|
|
||||||
(def-test! delete-this-file
|
|
||||||
":rm"
|
|
||||||
(with-temp-files!! "/tmp/doom-buffer-3" nil
|
|
||||||
(should-error (+evil:delete-this-file "this-file-does-not-exist"))
|
|
||||||
(should (+evil:delete-this-file nil t))
|
|
||||||
(should (not (file-exists-p it)))))
|
|
||||||
|
|
|
@ -1,59 +0,0 @@
|
||||||
;; -*- no-byte-compile: t; -*-
|
|
||||||
;;; feature/evil/test/evil.el
|
|
||||||
|
|
||||||
;;
|
|
||||||
;; `evil-ex-replace-special-filenames'
|
|
||||||
(def-test! resolve-vim-path
|
|
||||||
(cl-flet ((do-it #'evil-ex-replace-special-filenames))
|
|
||||||
;; file modifiers
|
|
||||||
(let ((buffer-file-name "~/.emacs.d/test/modules/feature/test-evil.el")
|
|
||||||
(default-directory "~/.emacs.d/test/modules/"))
|
|
||||||
(should (equal (do-it "%") "feature/test-evil.el"))
|
|
||||||
(should (equal (do-it "%:r") "feature/test-evil"))
|
|
||||||
(should (equal (do-it "%:r.elc") "feature/test-evil.elc"))
|
|
||||||
(should (equal (do-it "%:e") "el"))
|
|
||||||
(should (equal (do-it "%:p") (expand-file-name buffer-file-name)))
|
|
||||||
(should (equal (do-it "%:h") "feature"))
|
|
||||||
(should (equal (do-it "%:t") "test-evil.el"))
|
|
||||||
(should (equal (do-it "%:.") "feature/test-evil.el"))
|
|
||||||
(should (equal (do-it "%:~") "~/.emacs.d/test/modules/feature/test-evil.el"))
|
|
||||||
(should (equal (file-truename (do-it "%:p"))
|
|
||||||
(file-truename buffer-file-name))))
|
|
||||||
;; nested file modifiers
|
|
||||||
(let ((buffer-file-name "~/vim/src/version.c")
|
|
||||||
(default-directory "~/vim/"))
|
|
||||||
(should (equal (do-it "%:p") (expand-file-name "~/vim/src/version.c")))
|
|
||||||
(should (equal (do-it "%:p:.") "src/version.c"))
|
|
||||||
(should (equal (do-it "%:p:~") "~/vim/src/version.c"))
|
|
||||||
(should (equal (do-it "%:h") "src"))
|
|
||||||
(should (equal (do-it "%:p:h") (expand-file-name "~/vim/src")))
|
|
||||||
(should (equal (do-it "%:p:h:h") (expand-file-name "~/vim")))
|
|
||||||
(should (equal (do-it "%:t") "version.c"))
|
|
||||||
(should (equal (do-it "%:p:t") "version.c"))
|
|
||||||
(should (equal (do-it "%:r") "src/version"))
|
|
||||||
(should (equal (do-it "%:p:r") (expand-file-name "~/vim/src/version")))
|
|
||||||
(should (equal (do-it "%:t:r") "version")))
|
|
||||||
;; empty file modifiers
|
|
||||||
(let (buffer-file-name default-directory)
|
|
||||||
(should (equal (do-it "%") ""))
|
|
||||||
(should (equal (do-it "%:r") ""))
|
|
||||||
(should (equal (do-it "%:e") ""))
|
|
||||||
(should (equal (do-it "%:h") ""))
|
|
||||||
(should (equal (do-it "%:t") ""))
|
|
||||||
(should (equal (do-it "%:.") ""))
|
|
||||||
(should (equal (do-it "%:~") ""))
|
|
||||||
(should (equal (do-it "%:P") "")))))
|
|
||||||
|
|
||||||
(def-test! file-modifiers
|
|
||||||
(cl-flet ((do-it #'evil-ex-replace-special-filenames))
|
|
||||||
(let ((buffer-file-name "~/.emacs.d/test/modules/feature/test-evil.el")
|
|
||||||
(default-directory "~/.emacs.d/test/modules/"))
|
|
||||||
(should (equal (do-it "%:s?e?x?") "fxature/test-evil.el"))
|
|
||||||
(should (equal (do-it "%:gs?e?x?") "fxaturx/txst-xvil.xl")))))
|
|
||||||
|
|
||||||
(def-test! empty-file-modifiers
|
|
||||||
(cl-flet ((do-it #'evil-ex-replace-special-filenames))
|
|
||||||
(let (buffer-file-name default-directory)
|
|
||||||
(should (equal (do-it "%:s?e?x?") ""))
|
|
||||||
(should (equal (do-it "%:gs?e?x?") "")))))
|
|
||||||
|
|
66
modules/feature/evil/test/test-evil.el
Normal file
66
modules/feature/evil/test/test-evil.el
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
;; -*- no-byte-compile: t; -*-
|
||||||
|
;;; feature/evil/test/test-evil.el
|
||||||
|
|
||||||
|
(describe "feature/evil"
|
||||||
|
:var (resv project-root)
|
||||||
|
(before-all (require 'evil))
|
||||||
|
(after-all (unload-feature 'evil t))
|
||||||
|
(before-each
|
||||||
|
(fset 'resv #'+evil*resolve-vim-path)
|
||||||
|
(spy-on 'doom-project-root :and-call-fake (lambda () project-root)))
|
||||||
|
|
||||||
|
;; `evil-ex-replace-special-filenames' / `+evil*resolve-vim-path'
|
||||||
|
(describe "file modifiers"
|
||||||
|
(it "supports basic vim file modifiers"
|
||||||
|
(let ((buffer-file-name "~/.emacs.d/test/modules/feature/test-evil.el")
|
||||||
|
(default-directory "~/.emacs.d/test/modules/")
|
||||||
|
(project-root "~/.emacs.d/"))
|
||||||
|
(expect (resv "%") :to-equal "feature/test-evil.el")
|
||||||
|
(expect (resv "%:r") :to-equal "feature/test-evil")
|
||||||
|
(expect (resv "%:r.elc") :to-equal "feature/test-evil.elc")
|
||||||
|
(expect (resv "%:e") :to-equal "el")
|
||||||
|
(expect (resv "%:p") :to-equal (expand-file-name buffer-file-name))
|
||||||
|
(expect (resv "%:h") :to-equal "feature")
|
||||||
|
(expect (resv "%:t") :to-equal "test-evil.el")
|
||||||
|
(expect (resv "%:.") :to-equal "feature/test-evil.el")
|
||||||
|
(expect (resv "%:~") :to-equal "~/.emacs.d/test/modules/feature/test-evil.el")
|
||||||
|
(expect (file-truename (resv "%:p"))
|
||||||
|
:to-equal (file-truename buffer-file-name))))
|
||||||
|
|
||||||
|
(it "supports nested vim file modifiers"
|
||||||
|
(let ((buffer-file-name "~/vim/src/version.c")
|
||||||
|
(default-directory "~/vim/")
|
||||||
|
(project-root "~/vim/"))
|
||||||
|
(expect (resv "%:p") :to-equal (expand-file-name "~/vim/src/version.c"))
|
||||||
|
(expect (resv "%:p:.") :to-equal "src/version.c")
|
||||||
|
(expect (resv "%:p:~") :to-equal "~/vim/src/version.c")
|
||||||
|
(expect (resv "%:h") :to-equal "src")
|
||||||
|
(expect (resv "%:p:h") :to-equal (expand-file-name "~/vim/src"))
|
||||||
|
(expect (resv "%:p:h:h") :to-equal (expand-file-name "~/vim"))
|
||||||
|
(expect (resv "%:t") :to-equal "version.c")
|
||||||
|
(expect (resv "%:p:t") :to-equal "version.c")
|
||||||
|
(expect (resv "%:r") :to-equal "src/version")
|
||||||
|
(expect (resv "%:p:r") :to-equal (expand-file-name "~/vim/src/version"))
|
||||||
|
(expect (resv "%:t:r") :to-equal "version")))
|
||||||
|
|
||||||
|
(it "cleans up empty file modifiers"
|
||||||
|
(let (buffer-file-name default-directory)
|
||||||
|
(expect (resv "%") :to-equal "")
|
||||||
|
(expect (resv "%:r") :to-equal "")
|
||||||
|
(expect (resv "%:e") :to-equal "")
|
||||||
|
(expect (resv "%:h") :to-equal "")
|
||||||
|
(expect (resv "%:t") :to-equal "")
|
||||||
|
(expect (resv "%:.") :to-equal "")
|
||||||
|
(expect (resv "%:~") :to-equal "")
|
||||||
|
(expect (resv "%:P") :to-equal "")))
|
||||||
|
|
||||||
|
(it "supports substitution modifiers"
|
||||||
|
(let ((buffer-file-name "~/.emacs.d/test/modules/feature/test-evil.el")
|
||||||
|
(default-directory "~/.emacs.d/test/modules/"))
|
||||||
|
(expect (resv "%:s?e?x?") :to-equal "fxature/test-evil.el")
|
||||||
|
(expect (resv "%:gs?e?x?") :to-equal "fxaturx/txst-xvil.xl")))
|
||||||
|
|
||||||
|
(it "cleans up empty substitution modifiers"
|
||||||
|
(let (buffer-file-name default-directory)
|
||||||
|
(expect (resv "%:s?e?x?") :to-equal "")
|
||||||
|
(expect (resv "%:gs?e?x?") :to-equal "")))))
|
|
@ -1,124 +0,0 @@
|
||||||
;; -*- no-byte-compile: t; -*-
|
|
||||||
;;; feature/workspaces/test/autoload-workspaces.el
|
|
||||||
|
|
||||||
(require! :feature workspaces)
|
|
||||||
(doom|init-custom-hooks)
|
|
||||||
|
|
||||||
(defmacro with-workspace!! (buffer-args &rest body)
|
|
||||||
(declare (indent defun))
|
|
||||||
(let ((buffers
|
|
||||||
(cl-loop for bsym in buffer-args
|
|
||||||
collect `(,bsym (get-buffer-create ,(symbol-name bsym))))))
|
|
||||||
`(let ((persp-auto-resume-time -1)
|
|
||||||
(persp-auto-save-opt 0))
|
|
||||||
(require 'persp-mode)
|
|
||||||
(let (noninteractive)
|
|
||||||
(persp-mode +1))
|
|
||||||
(let (persp-before-switch-functions persp-activated-functions)
|
|
||||||
(+workspace-switch +workspaces-main t))
|
|
||||||
(let* (,@buffers)
|
|
||||||
(cl-loop with persp = (get-current-persp)
|
|
||||||
for buf in (list ,@(mapcar #'car buffers))
|
|
||||||
do (persp-add-buffer buf persp)
|
|
||||||
do (with-current-buffer buf
|
|
||||||
(setq buffer-file-name (make-temp-file "workspaces-test-"))))
|
|
||||||
,@body
|
|
||||||
(let (kill-buffer-query-functions kill-buffer-hook)
|
|
||||||
(mapc #'kill-buffer (list ,@(mapcar #'car buffers)))))
|
|
||||||
(let (noninteractive)
|
|
||||||
(persp-mode -1)))))
|
|
||||||
|
|
||||||
;; `+workspaces|init'
|
|
||||||
(def-test! init
|
|
||||||
(with-workspace!! ()
|
|
||||||
(should (equal (+workspace-current-name) +workspaces-main))))
|
|
||||||
|
|
||||||
;; `+workspaces*auto-add-buffer'
|
|
||||||
(def-test! auto-add-buffer-to-persp
|
|
||||||
(let ((a (generate-new-buffer "a")))
|
|
||||||
(doom-set-buffer-real a t)
|
|
||||||
(with-workspace!! ()
|
|
||||||
(should-not (+workspace-contains-buffer-p a))
|
|
||||||
(switch-to-buffer a)
|
|
||||||
(should (+workspace-contains-buffer-p a)))))
|
|
||||||
|
|
||||||
;; `+workspace-current'
|
|
||||||
;; `+workspace-current-name'
|
|
||||||
(def-test! current
|
|
||||||
(with-workspace!! ()
|
|
||||||
(should (equal (+workspace-current-name) +workspaces-main))
|
|
||||||
(should (+workspace-exists-p +workspaces-main))
|
|
||||||
(let ((workspace (+workspace-get +workspaces-main))
|
|
||||||
(current-workspace (+workspace-current)))
|
|
||||||
(should workspace)
|
|
||||||
(should (+workspace-p workspace))
|
|
||||||
(should (+workspace-p current-workspace))
|
|
||||||
(should (equal workspace current-workspace)))))
|
|
||||||
|
|
||||||
;; `+workspace-list'
|
|
||||||
;; `+workspace-list-names'
|
|
||||||
(def-test! workspace-list
|
|
||||||
(with-workspace!! ()
|
|
||||||
(should (equal (+workspace-list-names)
|
|
||||||
(list (+workspace-current-name))))
|
|
||||||
(should (equal (+workspace-list)
|
|
||||||
(list (+workspace-current))))))
|
|
||||||
|
|
||||||
;; `+workspace-new'
|
|
||||||
;; `+workspace-rename'
|
|
||||||
;; `+workspace-delete'
|
|
||||||
(def-test! workspace-crud
|
|
||||||
"Creating, reading, updating and deleting workspaces."
|
|
||||||
(with-workspace!! ()
|
|
||||||
(let ((new-workspace-name "*new-test*")
|
|
||||||
(renamed-workspace-name "*old-test*"))
|
|
||||||
(should (+workspace-new new-workspace-name))
|
|
||||||
(should (seq-contains (+workspace-list-names) new-workspace-name))
|
|
||||||
(should (equal new-workspace-name
|
|
||||||
(+workspace-rename new-workspace-name renamed-workspace-name)))
|
|
||||||
(should-not (seq-contains (+workspace-list-names) new-workspace-name))
|
|
||||||
(should (seq-contains (+workspace-list-names) renamed-workspace-name))
|
|
||||||
(should (= (length (+workspace-list-names)) 2))
|
|
||||||
(+workspace-delete renamed-workspace-name)
|
|
||||||
(should (= (length (+workspace-list-names)) 1)))))
|
|
||||||
|
|
||||||
;; `+workspace-switch'
|
|
||||||
(def-test! workspace-switch
|
|
||||||
(with-workspace!! ()
|
|
||||||
(let ((new-workspace-name "*new-test*"))
|
|
||||||
(should-error (+workspace-switch new-workspace-name))
|
|
||||||
(should (+workspace-switch new-workspace-name t))
|
|
||||||
(should (equal (+workspace-current-name) new-workspace-name)))))
|
|
||||||
|
|
||||||
;; `+workspace-buffer-list'
|
|
||||||
;; `+workspace-contains-buffer-p'
|
|
||||||
(def-test! buffer-list
|
|
||||||
(with-workspace!! (a b)
|
|
||||||
(let ((c (get-buffer-create "c"))
|
|
||||||
(d (get-buffer-create "d")))
|
|
||||||
(should (+workspace-contains-buffer-p a))
|
|
||||||
(should (+workspace-contains-buffer-p b))
|
|
||||||
(should-not (+workspace-contains-buffer-p c))
|
|
||||||
;; New (and real) buffers should be added to workspace buffer list.
|
|
||||||
(doom-set-buffer-real c t)
|
|
||||||
(switch-to-buffer "c")
|
|
||||||
(should (+workspace-contains-buffer-p c))
|
|
||||||
;; unreal buffers shouldn't
|
|
||||||
(switch-to-buffer "d")
|
|
||||||
(should-not (+workspace-contains-buffer-p d)))))
|
|
||||||
|
|
||||||
;; `+workspace/close-window-or-workspace'
|
|
||||||
(def-test! close-window-or-workspace
|
|
||||||
(with-workspace!! (a b)
|
|
||||||
(let ((ws (+workspace-current-name))
|
|
||||||
(inhibit-message t))
|
|
||||||
(+workspace-switch "test" t)
|
|
||||||
(split-window)
|
|
||||||
(should (equal (+workspace-current-name) "test"))
|
|
||||||
(should (= (length (doom-visible-windows)) 2))
|
|
||||||
;; kill window if more than one
|
|
||||||
(+workspace/close-window-or-workspace)
|
|
||||||
(should (= (length (doom-visible-windows)) 1))
|
|
||||||
;; kill workspace on last window
|
|
||||||
(+workspace/close-window-or-workspace)
|
|
||||||
(should (equal (+workspace-current-name) "main")))))
|
|
135
modules/feature/workspaces/test/test-workspaces.el
Normal file
135
modules/feature/workspaces/test/test-workspaces.el
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
;; -*- no-byte-compile: t; -*-
|
||||||
|
;;; feature/workspaces/test/test-workspaces.el
|
||||||
|
|
||||||
|
(describe "feature/workspaces"
|
||||||
|
:var (persp-auto-resume-time
|
||||||
|
persp-auto-save-opt
|
||||||
|
persp-switch-to-added-buffer
|
||||||
|
in1 in2 out1 out2
|
||||||
|
persp1 persp1-name persp2 persp2-name
|
||||||
|
doom-before-switch-buffer-hook
|
||||||
|
doom-after-switch-buffer-hook)
|
||||||
|
|
||||||
|
(before-all
|
||||||
|
(require! :feature workspaces)
|
||||||
|
(require 'persp-mode))
|
||||||
|
(after-all
|
||||||
|
(unload-feature 'persp-mode t))
|
||||||
|
|
||||||
|
(before-each
|
||||||
|
(setq persp-auto-resume-time -1
|
||||||
|
persp-auto-save-opt 0
|
||||||
|
persp-switch-to-added-buffer nil
|
||||||
|
in1 (get-buffer-create "a")
|
||||||
|
in2 (get-buffer-create "b")
|
||||||
|
out1 (get-buffer-create "c")
|
||||||
|
out2 (get-buffer-create "d"))
|
||||||
|
(doom-set-buffer-real in1 t)
|
||||||
|
(doom-set-buffer-real out1 t)
|
||||||
|
(let (noninteractive)
|
||||||
|
(persp-mode +1))
|
||||||
|
(let (persp-before-switch-functions persp-activated-functions)
|
||||||
|
(setq persp1-name +workspaces-main
|
||||||
|
persp1 (persp-add-new persp1-name)
|
||||||
|
persp2-name "test"
|
||||||
|
persp2 (persp-add-new persp2-name))
|
||||||
|
(persp-frame-switch +workspaces-main))
|
||||||
|
(delete-other-windows)
|
||||||
|
(switch-to-buffer in1)
|
||||||
|
(persp-add-buffer (list in1 in2))
|
||||||
|
(spy-on 'persp-add-buffer :and-call-through)
|
||||||
|
(doom|init-custom-hooks))
|
||||||
|
|
||||||
|
(after-each
|
||||||
|
(doom|init-custom-hooks 'disable)
|
||||||
|
(let (kill-buffer-query-functions kill-buffer-hook)
|
||||||
|
(mapc #'kill-buffer (list in1 in2 out1 out2)))
|
||||||
|
(let (noninteractive)
|
||||||
|
(mapc #'persp-kill (cdr (persp-names)))
|
||||||
|
(persp-mode -1)))
|
||||||
|
|
||||||
|
;;
|
||||||
|
(describe "switch"
|
||||||
|
(it "throws an error when switching to a non-existent workspace"
|
||||||
|
(expect (+workspace-switch "non-existent") :to-throw))
|
||||||
|
(it "switches to a valid workspace"
|
||||||
|
(+workspace-switch persp2-name)
|
||||||
|
(expect (+workspace-current-name) :to-equal persp2-name)))
|
||||||
|
|
||||||
|
(describe "current"
|
||||||
|
(it "returns the current workspace persp"
|
||||||
|
(expect (+workspace-p (+workspace-current)))
|
||||||
|
(expect (+workspace-current) :to-equal (get-current-persp)))
|
||||||
|
(it "returns the current workspace's name"
|
||||||
|
(expect (+workspace-current-name) :to-equal persp1-name)
|
||||||
|
(persp-switch (persp-name persp2))
|
||||||
|
(expect (+workspace-current-name) :to-equal persp2-name)))
|
||||||
|
|
||||||
|
(describe "exists-p"
|
||||||
|
(it "returns t for valid workspaces"
|
||||||
|
(expect (+workspace-exists-p persp1-name)))
|
||||||
|
(it "returns t for non-current (but valid) workspaces"
|
||||||
|
(expect (+workspace-exists-p persp2-name)))
|
||||||
|
(it "returns nil for non-existent workspaces"
|
||||||
|
(expect (+workspace-exists-p "non-existent") :to-be nil)))
|
||||||
|
|
||||||
|
(describe "buffer membership"
|
||||||
|
(it "returns t for buffers in current workspace"
|
||||||
|
(expect (+workspace-contains-buffer-p in1)))
|
||||||
|
(it "returns nil for buffers outside of current workspace"
|
||||||
|
(expect (+workspace-contains-buffer-p out1) :to-be nil))
|
||||||
|
(it "automatically adds interactively opened buffers"
|
||||||
|
(expect (+workspace-contains-buffer-p out1) :to-be nil)
|
||||||
|
(switch-to-buffer out1)
|
||||||
|
(expect (+workspace-contains-buffer-p out1)))
|
||||||
|
(xit "returns a list of orphaned buffers"
|
||||||
|
(expect (+workspace-orphaned-buffer-list) :to-contain out2)))
|
||||||
|
|
||||||
|
(describe "list"
|
||||||
|
(it "returns a list of names"
|
||||||
|
(expect (+workspace-list-names)
|
||||||
|
:to-have-same-items-as (list persp1-name persp2-name)))
|
||||||
|
(it "returns a list of perspective structs"
|
||||||
|
(expect (+workspace-list)
|
||||||
|
:to-have-same-items-as (list persp1 persp2))))
|
||||||
|
|
||||||
|
(describe "CRUD"
|
||||||
|
(it "creates new workspaces"
|
||||||
|
(+workspace-new "X")
|
||||||
|
(expect (+workspace-list-names) :to-contain "X"))
|
||||||
|
(it "renames an existing workspace"
|
||||||
|
(+workspace-rename persp2-name "X")
|
||||||
|
(expect (persp-name persp2) :to-equal "X")
|
||||||
|
(expect (+workspace-list-names)
|
||||||
|
:to-have-same-items-as (list persp1-name "X")))
|
||||||
|
(it "deletes a live workspace"
|
||||||
|
(+workspace-delete persp2-name)
|
||||||
|
(expect (+workspace-list-names) :not :to-contain persp2-name)))
|
||||||
|
|
||||||
|
(describe "command"
|
||||||
|
(describe "new"
|
||||||
|
(it "creates a new, blank workspace"
|
||||||
|
(quiet! (+workspace/new "X"))
|
||||||
|
(expect (one-window-p))
|
||||||
|
(expect (current-buffer) :to-be (doom-fallback-buffer)))
|
||||||
|
(it "clones a workspace"
|
||||||
|
(quiet! (+workspace/new "X" t))
|
||||||
|
(expect (current-buffer) :to-be in1)))
|
||||||
|
|
||||||
|
(describe "rename"
|
||||||
|
(it "renames the current workspace"
|
||||||
|
(quiet! (+workspace/rename "X"))
|
||||||
|
(expect (+workspace-current-name) :to-equal "X")))
|
||||||
|
|
||||||
|
(describe "close-window-or-workspace"
|
||||||
|
(before-each
|
||||||
|
(+workspace-switch persp2-name)
|
||||||
|
(split-window)
|
||||||
|
(expect (length (doom-visible-windows)) :to-be 2))
|
||||||
|
(it "kills window if more than one window"
|
||||||
|
(quiet! (+workspace/close-window-or-workspace))
|
||||||
|
(expect (length (doom-visible-windows)) :to-be 1))
|
||||||
|
(it "kills workspace on last window"
|
||||||
|
(quiet! (+workspace/close-window-or-workspace)
|
||||||
|
(+workspace/close-window-or-workspace))
|
||||||
|
(expect (+workspace-current-name) :to-equal persp1-name)))))
|
|
@ -40,7 +40,7 @@
|
||||||
"Improve imenu support with better expression regexps and Doom-specific forms."
|
"Improve imenu support with better expression regexps and Doom-specific forms."
|
||||||
(setq imenu-generic-expression
|
(setq imenu-generic-expression
|
||||||
'(("Evil Commands" "^\\s-*(evil-define-\\(?:command\\|operator\\|motion\\) +\\(\\_<[^ ()\n]+\\_>\\)" 1)
|
'(("Evil Commands" "^\\s-*(evil-define-\\(?:command\\|operator\\|motion\\) +\\(\\_<[^ ()\n]+\\_>\\)" 1)
|
||||||
("Unit tests" "^\\s-*(\\(?:ert-deftest\\|def-test!\\) +\\(\\_<[^ ()\n]+\\_>\\)" 1)
|
("Unit tests" "^\\s-*(\\(?:ert-deftest\\|describe\\) +\"\\([^\")]+\\)\"" 1)
|
||||||
("Package" "^\\s-*(\\(?:def-\\)?package! +\\(\\_<[^ ()\n]+\\_>\\)" 1)
|
("Package" "^\\s-*(\\(?:def-\\)?package! +\\(\\_<[^ ()\n]+\\_>\\)" 1)
|
||||||
("Settings" "^\\s-*(def-setting! +\\([^ ()\n]+\\)" 1)
|
("Settings" "^\\s-*(def-setting! +\\([^ ()\n]+\\)" 1)
|
||||||
("Major modes" "^\\s-*(define-derived-mode +\\([^ ()\n]+\\)" 1)
|
("Major modes" "^\\s-*(define-derived-mode +\\([^ ()\n]+\\)" 1)
|
||||||
|
@ -113,3 +113,11 @@
|
||||||
(def-project-mode! +emacs-lisp-ert-mode
|
(def-project-mode! +emacs-lisp-ert-mode
|
||||||
:modes (emacs-lisp-mode)
|
:modes (emacs-lisp-mode)
|
||||||
:match "/test[/-].+\\.el$")
|
:match "/test[/-].+\\.el$")
|
||||||
|
|
||||||
|
(associate! buttercup-minor-mode
|
||||||
|
:modes (emacs-lisp-mode)
|
||||||
|
:match "/test[/-].+\\.el$")
|
||||||
|
|
||||||
|
(after! buttercup
|
||||||
|
(set! :yas-minor-mode 'buttercup-minor-mode))
|
||||||
|
|
||||||
|
|
|
@ -1,62 +0,0 @@
|
||||||
;; -*- no-byte-compile: t; -*-
|
|
||||||
;;; lang/org/test/autoload-org.el
|
|
||||||
|
|
||||||
(require! :lang org)
|
|
||||||
|
|
||||||
(defmacro should-org-buffer!! (source expected &rest body)
|
|
||||||
`(should-buffer! ,source ,expected
|
|
||||||
(org-mode)
|
|
||||||
,@body))
|
|
||||||
|
|
||||||
;;
|
|
||||||
;; `+org/insert-item'
|
|
||||||
(def-test! insert-item-h1
|
|
||||||
"Should append/prepend new first-level headers with an extra newline."
|
|
||||||
(should-org-buffer!! ("* {0}Header") ("* Header\n\n* {|}")
|
|
||||||
(+org/insert-item 'below))
|
|
||||||
(should-org-buffer!! ("* {0}Header") ("* {|}\n\n* Header")
|
|
||||||
(+org/insert-item 'above)))
|
|
||||||
|
|
||||||
(def-test! insert-item-h2
|
|
||||||
"Should append/prepend new second-level (and higher) headers without an extra
|
|
||||||
newline."
|
|
||||||
(should-org-buffer!! ("** {0}Header") ("** Header\n** {|}")
|
|
||||||
(+org/insert-item 'below))
|
|
||||||
(should-org-buffer!! ("** {0}Header") ("** {|}\n** Header")
|
|
||||||
(+org/insert-item 'above)))
|
|
||||||
|
|
||||||
(def-test! insert-item-plain-list
|
|
||||||
"Should append/prepend new second-level (and higher) headers without an extra
|
|
||||||
newline."
|
|
||||||
(should-org-buffer!! ("+ {0}List item") ("+ List item\n+ {|}")
|
|
||||||
(+org/insert-item 'below))
|
|
||||||
(should-org-buffer!! ("+ {0}List item"
|
|
||||||
" + Sub item")
|
|
||||||
("+ List item"
|
|
||||||
" + Sub item"
|
|
||||||
"+ {|}")
|
|
||||||
(+org/insert-item 'below))
|
|
||||||
(should-org-buffer!! ("+ {0}List item"
|
|
||||||
"+ Next item")
|
|
||||||
("+ List item"
|
|
||||||
"+ {|}"
|
|
||||||
"+ Next item")
|
|
||||||
(+org/insert-item 'below)))
|
|
||||||
|
|
||||||
(def-test! insert-item-numbered-list
|
|
||||||
"Should append/prepend new second-level (and higher) headers without an extra
|
|
||||||
newline."
|
|
||||||
(should-org-buffer!! ("1. {0}List item") ("1. List item\n2. {|}")
|
|
||||||
(+org/insert-item 'below))
|
|
||||||
(should-org-buffer!! ("1. {0}List item"
|
|
||||||
"2. Sub item")
|
|
||||||
("1. List item"
|
|
||||||
"2. {|}"
|
|
||||||
"3. Sub item")
|
|
||||||
(+org/insert-item 'below))
|
|
||||||
(should-org-buffer!! ("1. {0}List item"
|
|
||||||
"2. Next item")
|
|
||||||
("1. {|}"
|
|
||||||
"2. List item"
|
|
||||||
"3. Next item")
|
|
||||||
(+org/insert-item 'above)))
|
|
145
modules/lang/org/test/test-org.el
Normal file
145
modules/lang/org/test/test-org.el
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
;; -*- no-byte-compile: t; -*-
|
||||||
|
;;; lang/org/test/test-autoload-org.el
|
||||||
|
|
||||||
|
(describe "lang/org"
|
||||||
|
;; `+org/insert-item'
|
||||||
|
(describe "insert-item"
|
||||||
|
(before-all
|
||||||
|
(require 'org)
|
||||||
|
(load! "../autoload/org.el"))
|
||||||
|
(after-all
|
||||||
|
(unload-feature 'org t))
|
||||||
|
|
||||||
|
(before-each
|
||||||
|
(set-buffer (get-buffer-create "org"))
|
||||||
|
(erase-buffer)
|
||||||
|
(delay-mode-hooks (org-mode)))
|
||||||
|
(after-each
|
||||||
|
(kill-buffer (get-buffer "org")))
|
||||||
|
|
||||||
|
(describe "headlines"
|
||||||
|
(it "appends first-level headlines with an extra newline"
|
||||||
|
(insert! "* {0}Header")
|
||||||
|
(+org/insert-item 'below)
|
||||||
|
(expect (eobp))
|
||||||
|
(expect (buffer-substring-no-properties (point-min) (point-max))
|
||||||
|
:to-equal "* Header\n\n* "))
|
||||||
|
(it "prepends first-level headlines with an extra newline"
|
||||||
|
(insert! "* {0}Header")
|
||||||
|
(+org/insert-item 'above)
|
||||||
|
(expect (eolp))
|
||||||
|
(expect (buffer-substring-no-properties (point-min) (point-max))
|
||||||
|
:to-equal "* \n\n* Header"))
|
||||||
|
|
||||||
|
(it "appends second-level headlines with an no extra newline"
|
||||||
|
(insert! "** {0}Header")
|
||||||
|
(+org/insert-item 'below)
|
||||||
|
(expect (eobp))
|
||||||
|
(expect (buffer-substring-no-properties (point-min) (point-max))
|
||||||
|
:to-equal "** Header\n** "))
|
||||||
|
(it "prepends second-level headlines with an no extra newline"
|
||||||
|
(insert! "** {0}Header")
|
||||||
|
(+org/insert-item 'above)
|
||||||
|
(expect (eolp))
|
||||||
|
(expect (buffer-substring-no-properties (point-min) (point-max))
|
||||||
|
:to-equal "** \n** Header"))
|
||||||
|
|
||||||
|
(it "appends headlines, skipping subtrees"
|
||||||
|
(insert! "** {0}First\n"
|
||||||
|
"*** sub 1\n"
|
||||||
|
"*** sub 2\n"
|
||||||
|
"**** subsub 1\n"
|
||||||
|
"** Header")
|
||||||
|
(+org/insert-item 'below)
|
||||||
|
(expect (eolp))
|
||||||
|
(expect (line-number-at-pos) :to-be 5)
|
||||||
|
(expect (buffer-substring-no-properties (point-min) (point-max))
|
||||||
|
:to-equal
|
||||||
|
(string-join '("** First"
|
||||||
|
"*** sub 1"
|
||||||
|
"*** sub 2"
|
||||||
|
"**** subsub 1"
|
||||||
|
"** "
|
||||||
|
"** Header")
|
||||||
|
"\n")))
|
||||||
|
(it "prepends headlines, skipping subtrees"
|
||||||
|
(insert! "** First\n"
|
||||||
|
"*** sub 1\n"
|
||||||
|
"*** sub 2\n"
|
||||||
|
"**** {0}subsub 1\n"
|
||||||
|
"** Header")
|
||||||
|
(+org/insert-item 'above)
|
||||||
|
(expect (eolp))
|
||||||
|
(expect (line-number-at-pos) :to-be 4)
|
||||||
|
(expect (buffer-substring-no-properties (point-min) (point-max))
|
||||||
|
:to-equal
|
||||||
|
(string-join '("** First"
|
||||||
|
"*** sub 1"
|
||||||
|
"*** sub 2"
|
||||||
|
"**** "
|
||||||
|
"**** subsub 1"
|
||||||
|
"** Header")
|
||||||
|
"\n"))))
|
||||||
|
|
||||||
|
(describe "plain lists"
|
||||||
|
(it "appends items"
|
||||||
|
(insert! "+ {0}List item")
|
||||||
|
(+org/insert-item 'below)
|
||||||
|
(expect (buffer-substring-no-properties (point-min) (point-max))
|
||||||
|
:to-equal "+ List item\n+ "))
|
||||||
|
(it "prepends items"
|
||||||
|
(insert! "+ {0}List item")
|
||||||
|
(+org/insert-item 'above)
|
||||||
|
(expect (buffer-substring-no-properties (point-min) (point-max))
|
||||||
|
:to-equal "+ \n+ List item"))
|
||||||
|
|
||||||
|
(it "appends items, but skips over child items"
|
||||||
|
(insert! "+ {0}List item\n"
|
||||||
|
" + Sub item\n"
|
||||||
|
"+ List item")
|
||||||
|
(+org/insert-item 'below)
|
||||||
|
(expect (buffer-substring-no-properties (point-min) (point-max))
|
||||||
|
:to-equal
|
||||||
|
(string-join '("+ List item"
|
||||||
|
" + Sub item"
|
||||||
|
"+ "
|
||||||
|
"+ List item")
|
||||||
|
"\n")))
|
||||||
|
(it "prepends items, but skips over child items"
|
||||||
|
(insert! "+ List item\n"
|
||||||
|
" + Sub item\n"
|
||||||
|
"+ {0}List item")
|
||||||
|
(+org/insert-item 'above)
|
||||||
|
(expect (buffer-substring-no-properties (point-min) (point-max))
|
||||||
|
:to-equal
|
||||||
|
(string-join '("+ List item"
|
||||||
|
" + Sub item"
|
||||||
|
"+ "
|
||||||
|
"+ List item")
|
||||||
|
"\n"))))
|
||||||
|
|
||||||
|
(describe "numbered lists"
|
||||||
|
(it "appends items and updates numbers"
|
||||||
|
(insert! "1. {0}List item\n"
|
||||||
|
"2. Sub item\n"
|
||||||
|
"3. List item")
|
||||||
|
(+org/insert-item 'below)
|
||||||
|
(expect (buffer-substring-no-properties (point-min) (point-max))
|
||||||
|
:to-equal
|
||||||
|
(string-join '("1. List item"
|
||||||
|
"2. "
|
||||||
|
"3. Sub item"
|
||||||
|
"4. List item")
|
||||||
|
"\n")))
|
||||||
|
(it "prepends items and updates numbers"
|
||||||
|
(insert! "1. List item\n"
|
||||||
|
"2. Sub item\n"
|
||||||
|
"3. {0}List item")
|
||||||
|
(+org/insert-item 'above)
|
||||||
|
(expect (buffer-substring-no-properties (point-min) (point-max))
|
||||||
|
:to-equal
|
||||||
|
(string-join '("1. List item"
|
||||||
|
"2. Sub item"
|
||||||
|
"3. "
|
||||||
|
"4. List item")
|
||||||
|
"\n"))))))
|
|
@ -1,32 +0,0 @@
|
||||||
;; -*- no-byte-compile: t; -*-
|
|
||||||
;;; lang/web/test/autoload-css.el
|
|
||||||
|
|
||||||
(def-test! toggle-inline-or-block
|
|
||||||
(let ((css-indent-offset 2))
|
|
||||||
(should-buffer!
|
|
||||||
("body { color: red{0}; font-size: 2em; }")
|
|
||||||
("body {"
|
|
||||||
" color: red{|};"
|
|
||||||
" font-size: 2em;"
|
|
||||||
"}")
|
|
||||||
(delay-mode-hooks (css-mode))
|
|
||||||
(+css/toggle-inline-or-block))))
|
|
||||||
|
|
||||||
(def-test! comment-indent-new-line
|
|
||||||
(should-buffer!
|
|
||||||
("// test{0}"
|
|
||||||
"body { color: red; font-size: 2em; }")
|
|
||||||
("// test"
|
|
||||||
"// {|}"
|
|
||||||
"body { color: red; font-size: 2em; }")
|
|
||||||
(delay-mode-hooks (scss-mode))
|
|
||||||
(+css/comment-indent-new-line))
|
|
||||||
(should-buffer!
|
|
||||||
("// test{0}"
|
|
||||||
"body { color: red; font-size: 2em; }")
|
|
||||||
("// test"
|
|
||||||
"// {|}"
|
|
||||||
"body { color: red; font-size: 2em; }")
|
|
||||||
(delay-mode-hooks (scss-mode))
|
|
||||||
(+css/comment-indent-new-line)))
|
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
;; -*- no-byte-compile: t; -*-
|
|
||||||
;;; lang/web/test/autoload-html.el
|
|
||||||
|
|
||||||
(def-test! encode-entities
|
|
||||||
(should (equal (+web-encode-entities "Hello world")
|
|
||||||
"Hello world"))
|
|
||||||
(should (equal (+web-encode-entities "H€llø wørld")
|
|
||||||
"H€llø wørld")))
|
|
||||||
|
|
||||||
(def-test! decode-entities
|
|
||||||
(should (equal (+web-decode-entities "Hello world")
|
|
||||||
"Hello world"))
|
|
||||||
(should (equal (+web-decode-entities "H€llø wørld")
|
|
||||||
"H€llø wørld")))
|
|
93
modules/lang/web/test/test-web.el
Normal file
93
modules/lang/web/test/test-web.el
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
;; -*- no-byte-compile: t; -*-
|
||||||
|
;;; lang/web/test/test-autoload-web.el
|
||||||
|
|
||||||
|
(describe "lang/web"
|
||||||
|
(describe "+html"
|
||||||
|
(before-all (load! "../autoload/html.el"))
|
||||||
|
|
||||||
|
(describe "encode entities"
|
||||||
|
(it "encodes strings with html entities"
|
||||||
|
(expect (+web-encode-entities "H€llø wørld")
|
||||||
|
:to-equal "H€llø wørld"))
|
||||||
|
(it "does nothing when html entities are absent"
|
||||||
|
(expect (+web-encode-entities "Hello world")
|
||||||
|
:to-equal "Hello world")))
|
||||||
|
|
||||||
|
(describe "decode entities"
|
||||||
|
(it "decodes strings with html entities"
|
||||||
|
(expect (+web-decode-entities "H€llø wørld")
|
||||||
|
:to-equal "H€llø wørld"))
|
||||||
|
(it "does nothing when html entities are absent"
|
||||||
|
(expect (+web-decode-entities "Hello world")
|
||||||
|
:to-equal "Hello world"))))
|
||||||
|
|
||||||
|
(describe "+css"
|
||||||
|
:var (css-indent-offset)
|
||||||
|
(before-all
|
||||||
|
(load! "../autoload/css.el")
|
||||||
|
(require 'smartparens)
|
||||||
|
(smartparens-mode +1))
|
||||||
|
(after-all
|
||||||
|
(smartparens-mode -1)
|
||||||
|
(unload-feature 'smartparens t))
|
||||||
|
|
||||||
|
(before-each
|
||||||
|
(setq css-indent-offset 2)
|
||||||
|
(set-buffer (get-buffer-create "css"))
|
||||||
|
(delay-mode-hooks (css-mode)))
|
||||||
|
(after-each
|
||||||
|
(kill-buffer (get-buffer "css")))
|
||||||
|
|
||||||
|
(describe "toggle-inline-or-block"
|
||||||
|
(after-each
|
||||||
|
(+css/toggle-inline-or-block)
|
||||||
|
(expect (string-trim (buffer-string)) :to-equal
|
||||||
|
(string-join
|
||||||
|
'("body {"
|
||||||
|
" color: red;"
|
||||||
|
" font-size: 2em;"
|
||||||
|
"}")
|
||||||
|
"\n")))
|
||||||
|
|
||||||
|
(describe "css-mode"
|
||||||
|
(before-each )
|
||||||
|
(it "converts inline statements into multiline blocks"
|
||||||
|
(insert! "body { color: red{0}; font-size: 2em; }"))
|
||||||
|
(it "works when cursor is on closing brace"
|
||||||
|
(insert! "body { color: red; font-size: 2em; {0}}"))
|
||||||
|
(it "works when cursor is on opening brace"
|
||||||
|
(insert! "body {{0} color: red; font-size: 2em; }"))
|
||||||
|
(it "works when cursor is on same line"
|
||||||
|
(insert! "{0}body { color: red; font-size: 2em; }"))))
|
||||||
|
|
||||||
|
(describe "comment-indent-new-line"
|
||||||
|
(before-each
|
||||||
|
(delay-mode-hooks (scss-mode)))
|
||||||
|
|
||||||
|
(it "continues commented lines on newline"
|
||||||
|
(insert! "// test{0}\n"
|
||||||
|
"body { color: red; font-size: 2em; }")
|
||||||
|
(+css/comment-indent-new-line)
|
||||||
|
(expect (string-trim (buffer-string)) :to-equal
|
||||||
|
(string-join
|
||||||
|
'("// test"
|
||||||
|
"// "
|
||||||
|
"body { color: red; font-size: 2em; }")
|
||||||
|
"\n"))
|
||||||
|
(expect (eolp))
|
||||||
|
(expect (line-number-at-pos) :to-be 2))
|
||||||
|
(it "preserves indentation within continued comments"
|
||||||
|
(insert! "// test{0}\n"
|
||||||
|
"body { color: red; font-size: 2em; }")
|
||||||
|
(+css/comment-indent-new-line)
|
||||||
|
(expect (string-trim (buffer-string)) :to-equal
|
||||||
|
(string-join
|
||||||
|
'("// test"
|
||||||
|
"// "
|
||||||
|
"body { color: red; font-size: 2em; }")
|
||||||
|
"\n"))
|
||||||
|
(expect (eolp))
|
||||||
|
(expect (line-number-at-pos) :to-be 2)))))
|
||||||
|
|
||||||
|
|
||||||
|
;;
|
|
@ -1,42 +0,0 @@
|
||||||
;; -*- no-byte-compile: t; -*-
|
|
||||||
;;; tools/password-store/test/autoload-pass.el
|
|
||||||
|
|
||||||
(load! "../autoload")
|
|
||||||
|
|
||||||
(defmacro with-passwords!! (buffer-args &rest body)
|
|
||||||
(declare (indent defun))
|
|
||||||
`(cl-letf
|
|
||||||
(((symbol-function '+pass-get-entry)
|
|
||||||
(lambda (entry)
|
|
||||||
(when (equal entry "fake/source")
|
|
||||||
'((secret . "defuse-account-gad")
|
|
||||||
("login" . "HL2532-GANDI")
|
|
||||||
("alt-login" . "hlissner")
|
|
||||||
("email" . "henrik@lissner.net")
|
|
||||||
("url" . "https://www.gandi.net/login"))))))
|
|
||||||
,@body))
|
|
||||||
|
|
||||||
;;
|
|
||||||
(def-test! get-field
|
|
||||||
(with-passwords!!
|
|
||||||
(should (equal (+pass-get-field "fake/source" "login")
|
|
||||||
"HL2532-GANDI"))
|
|
||||||
(should (equal (+pass-get-field "fake/source" "email")
|
|
||||||
"henrik@lissner.net"))
|
|
||||||
(should (equal (+pass-get-field "fake/source" '("alt-login" "email"))
|
|
||||||
"hlissner"))
|
|
||||||
(should (equal (+pass-get-field "fake/source" '("username" "email"))
|
|
||||||
"henrik@lissner.net"))))
|
|
||||||
|
|
||||||
(def-test! missing-fields-return-nil
|
|
||||||
(with-passwords!!
|
|
||||||
(should-not (+pass-get-field "fake/source" '("x" "y" "z")))))
|
|
||||||
|
|
||||||
(def-test! missing-entries-throw-error
|
|
||||||
(with-passwords!!
|
|
||||||
(should-error (+pass-get-field "nonexistent/source" "login"))))
|
|
||||||
|
|
||||||
(def-test! get-login
|
|
||||||
(with-passwords!!
|
|
||||||
(should (equal (+pass-get-user "fake/source") "HL2532-GANDI"))
|
|
||||||
(should (equal (+pass-get-secret "fake/source") "defuse-account-gad"))))
|
|
41
modules/tools/password-store/test/test-pass.el
Normal file
41
modules/tools/password-store/test/test-pass.el
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
;; -*- no-byte-compile: t; -*-
|
||||||
|
;;; tools/password-store/test/test-pass.el
|
||||||
|
|
||||||
|
(describe "tools/password-store"
|
||||||
|
(before-all
|
||||||
|
(load! "../autoload"))
|
||||||
|
|
||||||
|
(before-each
|
||||||
|
(spy-on 'auth-source-pass-parse-entry :and-call-fake
|
||||||
|
(lambda (entry)
|
||||||
|
(when (equal entry "fake/source")
|
||||||
|
'((secret . "defuse-account-gad")
|
||||||
|
("login" . "HL2532")
|
||||||
|
("alt-login" . "hlissner")
|
||||||
|
("email" . "henrik@lissner.net")
|
||||||
|
("url" . "https://some-place.net/login"))))))
|
||||||
|
|
||||||
|
(describe "get field"
|
||||||
|
(it "returns specific fields"
|
||||||
|
(expect (+pass-get-field "fake/source" "email")
|
||||||
|
:to-equal "henrik@lissner.net"))
|
||||||
|
(it "returns first existing of a list of fields"
|
||||||
|
(expect (+pass-get-field "fake/source" '("alt-login" "email"))
|
||||||
|
:to-equal "hlissner")
|
||||||
|
(expect (+pass-get-field "fake/source" '("username" "email"))
|
||||||
|
:to-equal "henrik@lissner.net"))
|
||||||
|
(it "returns nil for missing fields"
|
||||||
|
(expect (+pass-get-field "fake/source" '("x" "y" "z"))
|
||||||
|
:to-be nil))
|
||||||
|
(it "throws error on missing entries"
|
||||||
|
(expect (+pass-get-field "nonexistent/source" "login")
|
||||||
|
:to-throw)))
|
||||||
|
|
||||||
|
(describe "get user/secret"
|
||||||
|
(it "returns the user"
|
||||||
|
(let ((+pass-user-fields '("login" "user" "username" "email")))
|
||||||
|
(expect (+pass-get-user "fake/source")
|
||||||
|
:to-equal "HL2532")))
|
||||||
|
(it "returns the secret"
|
||||||
|
(expect (+pass-get-secret "fake/source")
|
||||||
|
:to-equal "defuse-account-gad"))))
|
|
@ -1,50 +0,0 @@
|
||||||
;; -*- no-byte-compile: t; -*-
|
|
||||||
;;; ui/doom-dashboard/test/doom-dashboard.el
|
|
||||||
|
|
||||||
(require! :ui doom-dashboard)
|
|
||||||
|
|
||||||
(defun -dashboard-test-pwd (spec file)
|
|
||||||
(let ((kill-buffer-query-functions '(+doom-dashboard|reload-on-kill))
|
|
||||||
(+doom-dashboard-pwd-policy (car spec))
|
|
||||||
(fallback-buffer (doom-fallback-buffer))
|
|
||||||
+doom-dashboard--last-cwd
|
|
||||||
projectile-enable-caching)
|
|
||||||
(with-temp-buffer
|
|
||||||
(setq buffer-file-name file
|
|
||||||
default-directory (file-name-directory file)
|
|
||||||
doom-real-buffer-p t))
|
|
||||||
(should +doom-dashboard--last-cwd)
|
|
||||||
(+doom-dashboard-update-pwd)
|
|
||||||
(should (equal (buffer-local-value 'default-directory fallback-buffer)
|
|
||||||
(cdr spec)))))
|
|
||||||
|
|
||||||
;;
|
|
||||||
(def-test! dashboard-p
|
|
||||||
(let ((fallback-buffer (doom-fallback-buffer)))
|
|
||||||
(should (equal (buffer-name fallback-buffer) +doom-dashboard-name))
|
|
||||||
(should (+doom-dashboard-p fallback-buffer))))
|
|
||||||
|
|
||||||
(def-test! get-pwd
|
|
||||||
:minor-mode projectile-mode
|
|
||||||
(let ((default-directory doom-core-dir)
|
|
||||||
(+doom-dashboard--last-cwd doom-core-dir)
|
|
||||||
projectile-enable-caching)
|
|
||||||
(dolist (spec (list (cons 'last-project doom-emacs-dir)
|
|
||||||
(cons 'last doom-core-dir)
|
|
||||||
(cons (lambda (x) "x") "x")
|
|
||||||
(cons "~" (expand-file-name "~"))
|
|
||||||
(cons nil default-directory)))
|
|
||||||
(let ((+doom-dashboard-pwd-policy (car spec)))
|
|
||||||
(should (equal (+doom-dashboard--get-pwd) (cdr spec)))))))
|
|
||||||
|
|
||||||
(def-test! pwd-policy
|
|
||||||
:minor-mode projectile-mode
|
|
||||||
(dolist (spec (list (cons 'last-project doom-emacs-dir)
|
|
||||||
(cons 'last doom-core-dir)
|
|
||||||
(cons "~" (expand-file-name "~/"))
|
|
||||||
(cons (lambda (x) "/tmp") "/tmp/")))
|
|
||||||
(-dashboard-test-pwd spec (expand-file-name "core.el" doom-core-dir))))
|
|
||||||
|
|
||||||
;;
|
|
||||||
(def-test! inhibit-refresh :skip t)
|
|
||||||
(def-test! inhibit-functions :skip t)
|
|
40
modules/ui/doom-dashboard/test/test-doom-dashboard.el
Normal file
40
modules/ui/doom-dashboard/test/test-doom-dashboard.el
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
;; -*- no-byte-compile: t; -*-
|
||||||
|
;;; ui/doom-dashboard/test/test-doom-dashboard.el
|
||||||
|
|
||||||
|
(require! :ui doom-dashboard)
|
||||||
|
|
||||||
|
(describe "ui/doom-dashboard"
|
||||||
|
:var (default-directory projectile-enable-caching)
|
||||||
|
(before-all
|
||||||
|
(require 'projectile)
|
||||||
|
(setq projectile-enable-caching nil))
|
||||||
|
(after-all
|
||||||
|
(unload-feature 'projectile t))
|
||||||
|
|
||||||
|
(before-each (projectile-mode +1))
|
||||||
|
(after-each (projectile-mode +1))
|
||||||
|
|
||||||
|
(describe "get-pwd"
|
||||||
|
:var (+doom-dashboard--last-cwd)
|
||||||
|
(before-each
|
||||||
|
(setq +doom-dashboard--last-cwd doom-core-dir
|
||||||
|
default-directory doom-core-dir))
|
||||||
|
(it "returns the current directory when policy is nil"
|
||||||
|
(let (+doom-dashboard-pwd-policy)
|
||||||
|
(expect (+doom-dashboard--get-pwd) :to-equal default-directory)))
|
||||||
|
(it "returns a path if policy is a path"
|
||||||
|
(let ((+doom-dashboard-pwd-policy "~"))
|
||||||
|
(expect (+doom-dashboard--get-pwd) :to-equal (expand-file-name "~"))))
|
||||||
|
(it "returns return value of policy as a function"
|
||||||
|
(let ((+doom-dashboard-pwd-policy (lambda (x) "x")))
|
||||||
|
(expect (+doom-dashboard--get-pwd) :to-equal "x")))
|
||||||
|
(it "returns last cwd if policy is 'last"
|
||||||
|
(let ((+doom-dashboard-pwd-policy 'last))
|
||||||
|
(expect (+doom-dashboard--get-pwd) :to-equal doom-core-dir)))
|
||||||
|
(it "returns last project if policy is 'last-project"
|
||||||
|
(let ((+doom-dashboard-pwd-policy 'last-project))
|
||||||
|
(expect (+doom-dashboard--get-pwd) :to-equal doom-emacs-dir))))
|
||||||
|
|
||||||
|
(describe "dashboard-p"
|
||||||
|
(it "changes the fallback buffer to the dashboard buffer"
|
||||||
|
(expect (+doom-dashboard-p (doom-fallback-buffer))))))
|
Loading…
Add table
Add a link
Reference in a new issue