diff options
| author | Evgeni Kolev <evgenysw@gmail.com> | 2017-06-05 09:39:58 +0300 |
|---|---|---|
| committer | Evgeni Kolev <evgenysw@gmail.com> | 2017-06-05 09:47:18 +0300 |
| commit | 15b0b14091b6740a32ccb074bbd832868643958a (patch) | |
| tree | 0cae854b62f9a6f0a50e7bdc2299f2ecd4d4c69a | |
| parent | 7a0358ce3eb9ed01744170fa8a1e12d98f8b8839 (diff) | |
Add tests
| -rw-r--r-- | .gitignore | 2 | ||||
| -rw-r--r-- | .travis.yml | 15 | ||||
| -rw-r--r-- | Makefile | 16 | ||||
| -rw-r--r-- | test/elpa.el | 4 | ||||
| -rw-r--r-- | test/evil-surround-test.el | 378 | ||||
| -rw-r--r-- | test/make-compile.el | 5 | ||||
| -rw-r--r-- | test/make-test.el | 11 | ||||
| -rw-r--r-- | test/make-update.el | 25 |
8 files changed, 456 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..397e90c --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.elpa/ +*.elc diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..4d9b382 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,15 @@ +sudo: true +dist: precise +language: emacs-lisp +env: + matrix: + - emacs=emacs-snapshot + +before_install: + - sudo add-apt-repository -y ppa:ubuntu-elisp + - sudo apt-get update -qq + - sudo apt-get install -qq $emacs + +script: + - make update + - make test diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..a9a8e86 --- /dev/null +++ b/Makefile @@ -0,0 +1,16 @@ +emacs ?= emacs +bemacs = $(emacs) -batch -l test/elpa.el + +update: + $(emacs) -batch -l test/make-update.el + +compile: clean + $(bemacs) -l test/make-compile.el + +test: + $(bemacs) -l test/make-test.el + +clean: + rm -f *.elc + +.PHONY: update compile test clean diff --git a/test/elpa.el b/test/elpa.el new file mode 100644 index 0000000..f501af1 --- /dev/null +++ b/test/elpa.el @@ -0,0 +1,4 @@ +(setq package-user-dir + (expand-file-name (format ".elpa/%s/elpa" emacs-version))) +(package-initialize) +(add-to-list 'load-path default-directory) diff --git a/test/evil-surround-test.el b/test/evil-surround-test.el new file mode 100644 index 0000000..f0ad61d --- /dev/null +++ b/test/evil-surround-test.el @@ -0,0 +1,378 @@ + +(require 'ert) +(require 'evil) +(require 'evil-surround) + +(ert-deftest evil-surround-test () + (ert-info ("basic surrounding") + (evil-test-buffer + "one [t]wo three" + (turn-on-evil-surround-mode) + ("ysiwb") + "one (two) three" + ("csb'") + "one 'two' three" + ("ds'") + "one two three"))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; code below is copied from evil-tests.el +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defvar evil-test-point nil + "Marker for point.") +(make-variable-buffer-local 'evil-test-point) +(defvar evil-test-visual-start nil + "Marker for Visual beginning.") +(make-variable-buffer-local 'evil-test-visual-start) +(defvar evil-test-visual-end nil + "Marker for Visual end.") +(make-variable-buffer-local 'evil-test-visual-end) + + +(defmacro evil-test-buffer (&rest body) + "Execute FORMS in a temporary buffer. +The following optional keywords specify the buffer's properties: +:state STATE The initial state, defaults to `normal'. +:visual SELECTION The Visual selection, defaults to `char'. +:point-start STRING String for matching beginning of point, + defaults to \"[\". +:point-end STRING String for matching end of point, + defaults to \"]\". +:visual-start STRING String for matching beginning of + Visual selection, defaults to \"<\". +:visual-end STRING String for matching end of + Visual selection, defaults to \">\". +Then follows one or more forms. If the first form is a string, +it is taken to be a buffer description as passed to +`evil-test-buffer-from-string', and initializes the buffer. +Subsequent string forms validate the buffer. +If a form is a list of strings or vectors, it is taken to be a +key sequence and is passed to `execute-kbd-macro'. If the form +is \(file FILENAME CONTENTS), then the test fails unless the +contents of FILENAME equal CONTENTS. If the form is \(error +SYMBOL ...) then the test fails unless an error of type SYMBOL is +raised. Remaining forms are evaluated as-is. +\(fn [[KEY VALUE]...] FORMS...)" + (declare (indent defun)) + (let ((state 'normal) + arg key point-start point-end string + visual visual-start visual-end) + ;; collect keywords + (while (keywordp (car-safe body)) + (setq key (pop body) + arg (pop body)) + (cond + ((eq key :point-start) + (setq point-start (or arg ""))) + ((eq key :point-end) + (setq point-end (or arg ""))) + ((eq key :state) + (setq state arg)) + ((eq key :visual) + (setq visual arg)) + ((eq key :visual-start) + (setq visual-start (or arg ""))) + ((eq key :visual-end) + (setq visual-end (or arg ""))))) + ;; collect buffer initialization + (when (stringp (car-safe body)) + (setq string (pop body))) + ;; macro expansion + `(let ((buffer (evil-test-buffer-from-string + ,string ',state + ,point-start ,point-end + ',visual ,visual-start ,visual-end)) + (kill-ring kill-ring) + (kill-ring-yank-pointer kill-ring-yank-pointer) + x-select-enable-clipboard + message-log-max) + (unwind-protect + (save-window-excursion + (with-current-buffer buffer + ;; necessary for keyboard macros to work + (switch-to-buffer-other-window (current-buffer)) + (buffer-enable-undo) + (undo-tree-mode 1) + ;; parse remaining forms + ,@(mapcar + #'(lambda (form) + (let (error-symbol) + (when (and (listp form) + (eq (car-safe form) 'error)) + (setq error-symbol (car-safe (cdr-safe form)) + form (cdr-safe (cdr-safe form)))) + (let ((result + (cond + ((stringp form) + `(evil-test-buffer-string + ,form + ',point-start ',point-end + ',visual-start ',visual-end)) + ((eq (car-safe form) 'file) + `(evil-test-file-contents ,(cadr form) + ,(caddr form))) + ((or (stringp (car-safe form)) + (vectorp (car-safe form)) + (memq (car-safe (car-safe form)) + '(kbd vconcat))) + ;; we need to execute everything as a single + ;; sequence for command loop hooks to work + `(execute-kbd-macro + (apply #'vconcat + (mapcar #'listify-key-sequence + (mapcar #'eval ',form))))) + ((memq (car-safe form) '(kbd vconcat)) + `(execute-kbd-macro ,form)) + (t + form)))) + (if error-symbol + `(should-error ,result :type ',error-symbol) + result)))) + body))) + (and (buffer-name buffer) + (kill-buffer buffer)))))) + +(when (fboundp 'font-lock-add-keywords) + (font-lock-add-keywords 'emacs-lisp-mode + '(("(\\(evil-test-buffer\\)\\>" + 1 font-lock-keyword-face)))) + +(defun evil-test-buffer-string (string &optional + point-start point-end + visual-start visual-end) + "Validate the current buffer according to STRING. +If STRING contains an occurrence of POINT-START immediately +followed by POINT-END, that position is compared against point. +If STRING contains an occurrence of VISUAL-START followed by +VISUAL-END, those positions are compared against the Visual selection. +POINT-START and POINT-END default to [ and ]. +VISUAL-START and VISUAL-END default to < and >." + (let ((actual-buffer (current-buffer)) + (marker-buffer (evil-test-marker-buffer-from-string + string + point-start point-end + visual-start visual-end)) + before-point after-point string selection) + (unwind-protect + (with-current-buffer marker-buffer + (setq string (buffer-string)) + (when evil-test-point + (setq before-point (buffer-substring (point-min) evil-test-point) + after-point (buffer-substring evil-test-point (point-max)))) + (when (and evil-test-visual-start evil-test-visual-end) + (setq selection (buffer-substring + evil-test-visual-start evil-test-visual-end))) + (with-current-buffer actual-buffer + (if (or before-point after-point) + (evil-test-text before-point after-point) + ;; if the cursor isn't specified, just test the whole buffer + (save-excursion + (goto-char (point-min)) + (evil-test-text nil string #'bobp #'eobp))) + (when selection + (evil-test-selection selection)))) + (kill-buffer marker-buffer)))) + +(defun evil-test-buffer-from-string (string &optional + state + point-start point-end + visual visual-start visual-end) + "Create a new buffer according to STRING. +If STRING contains an occurrence of POINT-START immediately +followed by POINT-END, then point is moved to that position. +If STRING contains an occurrence of VISUAL-START followed by +VISUAL-END, then a Visual selection is created with those boundaries. +POINT-START and POINT-END default to [ and ]. +VISUAL-START and VISUAL-END default to < and >. +STATE is the initial state; it defaults to `normal'. +VISUAL is the Visual selection: it defaults to `char'." + (let ((type (evil-visual-type (or visual 'char))) + (buffer (evil-test-marker-buffer-from-string + string point-start point-end + visual-start visual-end))) + (with-current-buffer buffer + (prog1 buffer + (evil-change-state state) + ;; let the buffer change its major mode without disabling Evil + (add-hook 'after-change-major-mode-hook #'evil-initialize) + (when (and (markerp evil-test-visual-start) + (markerp evil-test-visual-end)) + (evil-visual-select + evil-test-visual-start evil-test-visual-end type) + (when evil-test-point + (goto-char evil-test-point) + (evil-visual-refresh) + (unless (and (= evil-visual-beginning + evil-test-visual-start) + (= evil-visual-end + evil-test-visual-end)) + (evil-visual-select + evil-test-visual-start evil-test-visual-end type -1) + (goto-char evil-test-point) + (evil-visual-refresh)))) + (when (markerp evil-test-point) + (goto-char evil-test-point)))))) + +(defun evil-test-marker-buffer-from-string (string &optional + point-start point-end + visual-start visual-end) + "Create a new marker buffer according to STRING. +If STRING contains an occurrence of POINT-START immediately +followed by POINT-END, that position is stored in the +buffer-local variable `evil-test-point'. Similarly, +if STRING contains an occurrence of VISUAL-START followed by +VISUAL-END, those positions are stored in the variables +`evil-test-visual-beginning' and `evil-test-visual-end'. +POINT-START and POINT-END default to [ and ]. +VISUAL-START and VISUAL-END default to < and >." + (let ((string (or string "")) + (point-start (regexp-quote + (if (characterp point-start) + (string point-start) + (or point-start "[")))) + (point-end (regexp-quote + (if (characterp point-end) + (string point-end) + (or point-end "]")))) + (visual-start (regexp-quote + (if (characterp visual-start) + (string visual-start) + (or visual-start "<")))) + (visual-end (regexp-quote + (if (characterp visual-end) + (string visual-end) + (or visual-end ">"))))) + (with-current-buffer (generate-new-buffer " *test*") + (prog1 (current-buffer) + (save-excursion + (insert string)) + (save-excursion + (when (> (length point-start) 0) + (if (> (length point-end) 0) + (when (re-search-forward + (format "\\(%s\\)[^%s]?\\(%s\\)" + point-start point-end point-end) nil t) + (goto-char (match-beginning 0)) + (delete-region (match-beginning 2) (match-end 2)) + (delete-region (match-beginning 1) (match-end 1)) + (setq evil-test-point + (move-marker (make-marker) (point)))) + (when (re-search-forward point-start nil t) + (goto-char (match-beginning 0)) + (delete-region (match-beginning 0) (match-end 0)) + (setq evil-test-point + (move-marker (make-marker) (point))))))) + (save-excursion + (when (and (> (length visual-start) 0) + (> (length visual-end) 0)) + (when (re-search-forward visual-start nil t) + (goto-char (match-beginning 0)) + (delete-region (match-beginning 0) (match-end 0)) + (setq evil-test-visual-start + (move-marker (make-marker) (point)))) + (when (re-search-forward visual-end nil t) + (goto-char (match-beginning 0)) + (delete-region (match-beginning 0) (match-end 0)) + (setq evil-test-visual-end + (move-marker (make-marker) (point)))))))))) + +(defun evil-test-text (before after &optional before-predicate after-predicate) + "Verify the text around point. +BEFORE is the expected text before point, and AFTER is +the text after point. BEFORE-PREDICATE is a predicate function +to execute at the beginning of the text, and AFTER-PREDICATE +is executed at the end." + (when before + (if (functionp before) + (setq before-predicate before + before nil) + (should (string= (buffer-substring + (max (point-min) (- (point) (length before))) + (point)) + before)))) + (when after + (if (functionp after) + (setq after-predicate after + after nil) + (should (string= (buffer-substring + (point) + (min (point-max) (+ (point) (length after)))) + after)))) + (when before-predicate + (ert-info ((format "Expect `%s' at the beginning" before-predicate)) + (save-excursion + (backward-char (length before)) + (should (funcall before-predicate))))) + (when after-predicate + (ert-info ((format "Expect `%s' at the end" after-predicate)) + (save-excursion + (forward-char (length after)) + (should (funcall after-predicate)))))) + +(defmacro evil-test-selection (string &optional end-string + before-predicate after-predicate) + "Verify that the Visual selection contains STRING." + (declare (indent defun)) + `(progn + (save-excursion + (goto-char (or evil-visual-beginning (region-beginning))) + (evil-test-text nil (or ,string ,end-string) ,before-predicate)) + (save-excursion + (goto-char (or evil-visual-end (region-end))) + (evil-test-text (or ,end-string ,string) nil nil ,after-predicate)))) + +(defmacro evil-test-region (string &optional end-string + before-predicate after-predicate) + "Verify that the region contains STRING." + (declare (indent defun)) + `(progn + (save-excursion + (goto-char (region-beginning)) + (evil-test-text nil (or ,string ,end-string) ,before-predicate)) + (save-excursion + (goto-char (region-end)) + (evil-test-text (or ,end-string ,string) nil nil ,after-predicate)))) + +(defmacro evil-test-overlay (overlay string &optional end-string + before-predicate after-predicate) + "Verify that OVERLAY contains STRING." + (declare (indent defun)) + `(progn + (save-excursion + (goto-char (overlay-start ,overlay)) + (evil-test-text nil (or ,string ,end-string) ,before-predicate)) + (save-excursion + (goto-char (overlay-end ,overlay)) + (evil-test-text (or ,end-string ,string) nil nil ,after-predicate)))) + +(defun evil-temp-filename () + "Return an appropriate temporary filename." + (make-temp-name (expand-file-name "evil-test" + temporary-file-directory))) + +(defmacro evil-with-temp-file (file-var content &rest body) + "Create a temp file with CONTENT and bind its name to FILE-VAR within BODY. +FILE-VAR must be a symbol which contains the name of the +temporary file within the macro body. CONTENT is either a string +to be used as the content of the temporary file or a form to be +executed with the temporary file's buffer as \(current-buffer), +see `with-temp-file'. BODY contains the forms to be executed +while the temporary file exists. The temporary file is deleted at +the end of the execution of BODY." + (declare (indent 2) + (debug (symbolp form body))) + `(let ((,file-var (evil-temp-filename))) + (with-temp-file ,file-var + ,(if (stringp content) + `(insert ,content) + content)) + ,@body + (delete-file ,file-var))) + +(defun evil-test-file-contents (name contents) + "Ensure that the contents of file with NAME equal CONTENTS." + (with-temp-buffer + (insert-file-contents name) + (should (string= (buffer-string) + contents)))) diff --git a/test/make-compile.el b/test/make-compile.el new file mode 100644 index 0000000..d3d8956 --- /dev/null +++ b/test/make-compile.el @@ -0,0 +1,5 @@ +(setq files '("evil-surround.el")) +(setq byte-compile--use-old-handlers nil) +(mapc #'byte-compile-file files) + + diff --git a/test/make-test.el b/test/make-test.el new file mode 100644 index 0000000..fb487b1 --- /dev/null +++ b/test/make-test.el @@ -0,0 +1,11 @@ + +(let ((current-directory (file-name-directory load-file-name))) + (setq evil-surround-test-path (expand-file-name "." current-directory)) + (setq evil-surround-root-path (expand-file-name ".." current-directory))) + +(add-to-list 'load-path evil-surround-root-path) +(add-to-list 'load-path evil-surround-test-path) + +(load (concat (file-name-as-directory evil-surround-test-path) "evil-surround-test.el") nil t) + +(ert-run-tests-batch-and-exit) diff --git a/test/make-update.el b/test/make-update.el new file mode 100644 index 0000000..d412f4b --- /dev/null +++ b/test/make-update.el @@ -0,0 +1,25 @@ +(setq package-user-dir + (expand-file-name (format ".elpa/%s/elpa" emacs-version))) +(message "installing in %s ...\n" package-user-dir) +(package-initialize) +(setq package-archives + '(("melpa" . "http://melpa.org/packages/") + ("gnu" . "http://elpa.gnu.org/packages/"))) +(package-refresh-contents) + +(defconst dev-packages + '(evil)) + +(dolist (package dev-packages) + (unless (package-installed-p package) + (ignore-errors + (package-install package)))) + +(save-window-excursion + (package-list-packages t) + (condition-case nil + (progn + (package-menu-mark-upgrades) + (package-menu-execute t)) + (error + (message "All packages up to date")))) |
