diff options
| -rw-r--r-- | modules/custom-file-buffer.el | 2 | ||||
| -rw-r--r-- | tests/test-custom-file-buffer-clear-to-bottom-of-buffer.el | 163 | ||||
| -rw-r--r-- | tests/test-custom-file-buffer-clear-to-top-of-buffer.el | 162 | ||||
| -rw-r--r-- | tests/test-custom-file-buffer-copy-link-to-buffer-file.el | 209 | ||||
| -rw-r--r-- | tests/test-custom-file-buffer-copy-path-to-buffer-file-as-kill.el | 205 | ||||
| -rw-r--r-- | tests/test-custom-file-buffer-copy-whole-buffer.el | 194 |
6 files changed, 934 insertions, 1 deletions
diff --git a/modules/custom-file-buffer.el b/modules/custom-file-buffer.el index a56edf18..e0224a32 100644 --- a/modules/custom-file-buffer.el +++ b/modules/custom-file-buffer.el @@ -108,7 +108,7 @@ Returns t on success, nil if buffer not visiting a file." When called interactively, prompts for confirmation if target file exists." (interactive (list (read-directory-name "Move buffer and file (to new directory): "))) (let* ((target (expand-file-name (buffer-name) (expand-file-name dir)))) - (condition-case err + (condition-case _ (cj/--move-buffer-and-file dir nil) (file-already-exists (if (yes-or-no-p (format "File %s exists; overwrite? " target)) diff --git a/tests/test-custom-file-buffer-clear-to-bottom-of-buffer.el b/tests/test-custom-file-buffer-clear-to-bottom-of-buffer.el new file mode 100644 index 00000000..969f9bb7 --- /dev/null +++ b/tests/test-custom-file-buffer-clear-to-bottom-of-buffer.el @@ -0,0 +1,163 @@ +;;; test-custom-file-buffer-clear-to-bottom-of-buffer.el --- Tests for cj/clear-to-bottom-of-buffer -*- lexical-binding: t; -*- + +;;; Commentary: +;; Tests for the cj/clear-to-bottom-of-buffer function from custom-file-buffer.el +;; +;; This function deletes all text from point to the end of the current buffer. +;; It does not save the deleted text in the kill ring. + +;;; Code: + +(require 'ert) +(require 'testutil-general) + +;; Add modules directory to load path +(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory)) + +;; Stub dependencies before loading the module +(defvar cj/custom-keymap (make-sparse-keymap) + "Stub keymap for testing.") + +;; Stub ps-print package +(provide 'ps-print) + +;; Now load the actual production module +(require 'custom-file-buffer) + +;;; Setup and Teardown + +(defun test-clear-to-bottom-setup () + "Set up test environment." + (setq kill-ring nil)) + +(defun test-clear-to-bottom-teardown () + "Clean up test environment." + (setq kill-ring nil)) + +;;; Normal Cases + +(ert-deftest test-clear-to-bottom-point-in-middle () + "Should delete from point to end when point in middle." + (test-clear-to-bottom-setup) + (unwind-protect + (with-temp-buffer + (insert "Line 1\nLine 2\nLine 3") + (goto-char (point-min)) + (forward-line 1) ; Point at start of "Line 2" + (cj/clear-to-bottom-of-buffer) + (should (equal (buffer-string) "Line 1\n"))) + (test-clear-to-bottom-teardown))) + +(ert-deftest test-clear-to-bottom-empty-buffer () + "Should do nothing in empty buffer." + (test-clear-to-bottom-setup) + (unwind-protect + (with-temp-buffer + (cj/clear-to-bottom-of-buffer) + (should (equal (buffer-string) ""))) + (test-clear-to-bottom-teardown))) + +;;; Boundary Cases + +(ert-deftest test-clear-to-bottom-point-at-beginning () + "Should delete entire buffer when point at beginning." + (test-clear-to-bottom-setup) + (unwind-protect + (with-temp-buffer + (insert "Line 1\nLine 2\nLine 3") + (goto-char (point-min)) + (cj/clear-to-bottom-of-buffer) + (should (equal (buffer-string) ""))) + (test-clear-to-bottom-teardown))) + +(ert-deftest test-clear-to-bottom-point-at-end () + "Should delete nothing when point at end." + (test-clear-to-bottom-setup) + (unwind-protect + (with-temp-buffer + (insert "Line 1\nLine 2\nLine 3") + (goto-char (point-max)) + (cj/clear-to-bottom-of-buffer) + (should (equal (buffer-string) "Line 1\nLine 2\nLine 3"))) + (test-clear-to-bottom-teardown))) + +(ert-deftest test-clear-to-bottom-point-second-to-last-char () + "Should delete last character when point at second-to-last." + (test-clear-to-bottom-setup) + (unwind-protect + (with-temp-buffer + (insert "Hello") + (goto-char (1- (point-max))) ; Before 'o' + (cj/clear-to-bottom-of-buffer) + (should (equal (buffer-string) "Hell"))) + (test-clear-to-bottom-teardown))) + +(ert-deftest test-clear-to-bottom-unicode-content () + "Should handle unicode content." + (test-clear-to-bottom-setup) + (unwind-protect + (with-temp-buffer + (insert "Hello 👋\nÙ…Ø±ØØ¨Ø§\nWorld") + (goto-char (point-min)) + (forward-line 1) + (cj/clear-to-bottom-of-buffer) + (should (equal (buffer-string) "Hello 👋\n"))) + (test-clear-to-bottom-teardown))) + +(ert-deftest test-clear-to-bottom-narrowed-buffer () + "Should respect narrowing." + (test-clear-to-bottom-setup) + (unwind-protect + (with-temp-buffer + (insert "Line 1\nLine 2\nLine 3\nLine 4") + (goto-char (point-min)) + (forward-line 1) + (let ((start (point))) + (forward-line 2) + (narrow-to-region start (point)) + (goto-char (point-min)) + (forward-line 1) ; Point at "Line 3" + (cj/clear-to-bottom-of-buffer) + (should (equal (buffer-string) "Line 2\n")))) + (test-clear-to-bottom-teardown))) + +(ert-deftest test-clear-to-bottom-multiple-windows () + "Should update all windows showing buffer." + (test-clear-to-bottom-setup) + (unwind-protect + (with-temp-buffer + (insert "Line 1\nLine 2\nLine 3") + (goto-char (point-min)) + (forward-line 1) + (cj/clear-to-bottom-of-buffer) + ;; Just verify content changed + (should (equal (buffer-string) "Line 1\n"))) + (test-clear-to-bottom-teardown))) + +(ert-deftest test-clear-to-bottom-does-not-affect-kill-ring () + "Should not add deleted text to kill ring." + (test-clear-to-bottom-setup) + (unwind-protect + (with-temp-buffer + (insert "Line 1\nLine 2\nLine 3") + (goto-char (point-min)) + (setq kill-ring nil) + (cj/clear-to-bottom-of-buffer) + (should (null kill-ring))) + (test-clear-to-bottom-teardown))) + +;;; Error Cases + +(ert-deftest test-clear-to-bottom-read-only-buffer () + "Should signal error in read-only buffer." + (test-clear-to-bottom-setup) + (unwind-protect + (with-temp-buffer + (insert "Read-only content") + (read-only-mode 1) + (goto-char (point-min)) + (should-error (cj/clear-to-bottom-of-buffer))) + (test-clear-to-bottom-teardown))) + +(provide 'test-custom-file-buffer-clear-to-bottom-of-buffer) +;;; test-custom-file-buffer-clear-to-bottom-of-buffer.el ends here diff --git a/tests/test-custom-file-buffer-clear-to-top-of-buffer.el b/tests/test-custom-file-buffer-clear-to-top-of-buffer.el new file mode 100644 index 00000000..18e3f71b --- /dev/null +++ b/tests/test-custom-file-buffer-clear-to-top-of-buffer.el @@ -0,0 +1,162 @@ +;;; test-custom-file-buffer-clear-to-top-of-buffer.el --- Tests for cj/clear-to-top-of-buffer -*- lexical-binding: t; -*- + +;;; Commentary: +;; Tests for the cj/clear-to-top-of-buffer function from custom-file-buffer.el +;; +;; This function deletes all text from point to the beginning of the current buffer. +;; It does not save the deleted text in the kill ring. + +;;; Code: + +(require 'ert) +(require 'testutil-general) + +;; Add modules directory to load path +(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory)) + +;; Stub dependencies before loading the module +(defvar cj/custom-keymap (make-sparse-keymap) + "Stub keymap for testing.") + +;; Stub ps-print package +(provide 'ps-print) + +;; Now load the actual production module +(require 'custom-file-buffer) + +;;; Setup and Teardown + +(defun test-clear-to-top-setup () + "Set up test environment." + (setq kill-ring nil)) + +(defun test-clear-to-top-teardown () + "Clean up test environment." + (setq kill-ring nil)) + +;;; Normal Cases + +(ert-deftest test-clear-to-top-point-in-middle () + "Should delete from beginning to point when point in middle." + (test-clear-to-top-setup) + (unwind-protect + (with-temp-buffer + (insert "Line 1\nLine 2\nLine 3") + (goto-char (point-min)) + (forward-line 2) ; Point at start of "Line 3" + (cj/clear-to-top-of-buffer) + (should (equal (buffer-string) "Line 3"))) + (test-clear-to-top-teardown))) + +(ert-deftest test-clear-to-top-empty-buffer () + "Should do nothing in empty buffer." + (test-clear-to-top-setup) + (unwind-protect + (with-temp-buffer + (cj/clear-to-top-of-buffer) + (should (equal (buffer-string) ""))) + (test-clear-to-top-teardown))) + +;;; Boundary Cases + +(ert-deftest test-clear-to-top-point-at-beginning () + "Should delete nothing when point at beginning." + (test-clear-to-top-setup) + (unwind-protect + (with-temp-buffer + (insert "Line 1\nLine 2\nLine 3") + (goto-char (point-min)) + (cj/clear-to-top-of-buffer) + (should (equal (buffer-string) "Line 1\nLine 2\nLine 3"))) + (test-clear-to-top-teardown))) + +(ert-deftest test-clear-to-top-point-at-end () + "Should delete entire buffer when point at end." + (test-clear-to-top-setup) + (unwind-protect + (with-temp-buffer + (insert "Line 1\nLine 2\nLine 3") + (goto-char (point-max)) + (cj/clear-to-top-of-buffer) + (should (equal (buffer-string) ""))) + (test-clear-to-top-teardown))) + +(ert-deftest test-clear-to-top-point-at-second-char () + "Should delete first character when point at second." + (test-clear-to-top-setup) + (unwind-protect + (with-temp-buffer + (insert "Hello") + (goto-char (1+ (point-min))) ; After 'H' + (cj/clear-to-top-of-buffer) + (should (equal (buffer-string) "ello"))) + (test-clear-to-top-teardown))) + +(ert-deftest test-clear-to-top-unicode-content () + "Should handle unicode content." + (test-clear-to-top-setup) + (unwind-protect + (with-temp-buffer + (insert "Hello 👋\nÙ…Ø±ØØ¨Ø§\nWorld") + (goto-char (point-min)) + (forward-line 2) + (cj/clear-to-top-of-buffer) + (should (equal (buffer-string) "World"))) + (test-clear-to-top-teardown))) + +(ert-deftest test-clear-to-top-narrowed-buffer () + "Should respect narrowing." + (test-clear-to-top-setup) + (unwind-protect + (with-temp-buffer + (insert "Line 1\nLine 2\nLine 3\nLine 4") + (goto-char (point-min)) + (forward-line 1) + (let ((start (point))) + (forward-line 2) + (narrow-to-region start (point)) + (goto-char (point-min)) + (forward-line 1) ; Point at "Line 3" + (cj/clear-to-top-of-buffer) + (should (equal (buffer-string) "Line 3\n")))) + (test-clear-to-top-teardown))) + +(ert-deftest test-clear-to-top-multiple-windows () + "Should update all windows showing buffer." + (test-clear-to-top-setup) + (unwind-protect + (with-temp-buffer + (insert "Line 1\nLine 2\nLine 3") + (goto-char (point-max)) + (cj/clear-to-top-of-buffer) + ;; Just verify content changed + (should (equal (buffer-string) ""))) + (test-clear-to-top-teardown))) + +(ert-deftest test-clear-to-top-does-not-affect-kill-ring () + "Should not add deleted text to kill ring." + (test-clear-to-top-setup) + (unwind-protect + (with-temp-buffer + (insert "Line 1\nLine 2\nLine 3") + (goto-char (point-max)) + (setq kill-ring nil) + (cj/clear-to-top-of-buffer) + (should (null kill-ring))) + (test-clear-to-top-teardown))) + +;;; Error Cases + +(ert-deftest test-clear-to-top-read-only-buffer () + "Should signal error in read-only buffer." + (test-clear-to-top-setup) + (unwind-protect + (with-temp-buffer + (insert "Read-only content") + (read-only-mode 1) + (goto-char (point-max)) + (should-error (cj/clear-to-top-of-buffer))) + (test-clear-to-top-teardown))) + +(provide 'test-custom-file-buffer-clear-to-top-of-buffer) +;;; test-custom-file-buffer-clear-to-top-of-buffer.el ends here diff --git a/tests/test-custom-file-buffer-copy-link-to-buffer-file.el b/tests/test-custom-file-buffer-copy-link-to-buffer-file.el new file mode 100644 index 00000000..94d1e01e --- /dev/null +++ b/tests/test-custom-file-buffer-copy-link-to-buffer-file.el @@ -0,0 +1,209 @@ +;;; test-custom-file-buffer-copy-link-to-buffer-file.el --- Tests for cj/copy-link-to-buffer-file -*- lexical-binding: t; -*- + +;;; Commentary: +;; Tests for the cj/copy-link-to-buffer-file function from custom-file-buffer.el +;; +;; This function copies the full file:// path of the current buffer's file to +;; the kill ring. For non-file buffers, it does nothing (no error). + +;;; Code: + +(require 'ert) +(require 'testutil-general) + +;; Add modules directory to load path +(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory)) + +;; Stub dependencies before loading the module +(defvar cj/custom-keymap (make-sparse-keymap) + "Stub keymap for testing.") + +;; Stub ps-print package +(provide 'ps-print) + +;; Now load the actual production module +(require 'custom-file-buffer) + +;;; Setup and Teardown + +(defun test-copy-link-setup () + "Set up test environment." + (setq kill-ring nil)) + +(defun test-copy-link-teardown () + "Clean up test environment." + ;; Kill all buffers visiting files in the test directory + (dolist (buf (buffer-list)) + (when (buffer-file-name buf) + (when (string-prefix-p cj/test-base-dir (buffer-file-name buf)) + (with-current-buffer buf + (set-buffer-modified-p nil) + (kill-buffer buf))))) + (cj/delete-test-base-dir) + (setq kill-ring nil)) + +;;; Normal Cases + +(ert-deftest test-copy-link-simple-file () + "Should copy file:// link for simple file buffer." + (test-copy-link-setup) + (unwind-protect + (let* ((test-dir (cj/create-test-subdirectory "test")) + (test-file (expand-file-name "test.txt" test-dir))) + (with-temp-file test-file + (insert "content")) + (with-current-buffer (find-file test-file) + (cj/copy-link-to-buffer-file) + (should (equal (car kill-ring) (concat "file://" test-file))))) + (test-copy-link-teardown))) + +(ert-deftest test-copy-link-non-file-buffer () + "Should do nothing for non-file buffer without error." + (test-copy-link-setup) + (unwind-protect + (with-temp-buffer + (setq kill-ring nil) + (cj/copy-link-to-buffer-file) + (should (null kill-ring))) + (test-copy-link-teardown))) + +;;; Boundary Cases + +(ert-deftest test-copy-link-unicode-filename () + "Should handle unicode in filename." + (test-copy-link-setup) + (unwind-protect + (let* ((test-dir (cj/create-test-subdirectory "test")) + (test-file (expand-file-name "café.txt" test-dir))) + (with-temp-file test-file + (insert "content")) + (with-current-buffer (find-file test-file) + (cj/copy-link-to-buffer-file) + (should (equal (car kill-ring) (concat "file://" test-file))))) + (test-copy-link-teardown))) + +(ert-deftest test-copy-link-spaces-in-filename () + "Should handle spaces in filename." + (test-copy-link-setup) + (unwind-protect + (let* ((test-dir (cj/create-test-subdirectory "test")) + (test-file (expand-file-name "my file.txt" test-dir))) + (with-temp-file test-file + (insert "content")) + (with-current-buffer (find-file test-file) + (cj/copy-link-to-buffer-file) + (should (equal (car kill-ring) (concat "file://" test-file))))) + (test-copy-link-teardown))) + +(ert-deftest test-copy-link-special-chars-filename () + "Should handle special characters in filename." + (test-copy-link-setup) + (unwind-protect + (let* ((test-dir (cj/create-test-subdirectory "test")) + (test-file (expand-file-name "[test]-(1).txt" test-dir))) + (with-temp-file test-file + (insert "content")) + (with-current-buffer (find-file test-file) + (cj/copy-link-to-buffer-file) + (should (equal (car kill-ring) (concat "file://" test-file))))) + (test-copy-link-teardown))) + +(ert-deftest test-copy-link-very-long-path () + "Should handle very long path." + (test-copy-link-setup) + (unwind-protect + (let* ((test-dir (cj/create-test-subdirectory "test")) + (long-name (make-string 200 ?x)) + (test-file (expand-file-name (concat long-name ".txt") test-dir))) + (with-temp-file test-file + (insert "content")) + (with-current-buffer (find-file test-file) + (cj/copy-link-to-buffer-file) + (should (equal (car kill-ring) (concat "file://" test-file))))) + (test-copy-link-teardown))) + +(ert-deftest test-copy-link-hidden-file () + "Should handle hidden file." + (test-copy-link-setup) + (unwind-protect + (let* ((test-dir (cj/create-test-subdirectory "test")) + (test-file (expand-file-name ".hidden" test-dir))) + (with-temp-file test-file + (insert "content")) + (with-current-buffer (find-file test-file) + (cj/copy-link-to-buffer-file) + (should (equal (car kill-ring) (concat "file://" test-file))))) + (test-copy-link-teardown))) + +(ert-deftest test-copy-link-no-extension () + "Should handle file with no extension." + (test-copy-link-setup) + (unwind-protect + (let* ((test-dir (cj/create-test-subdirectory "test")) + (test-file (expand-file-name "README" test-dir))) + (with-temp-file test-file + (insert "content")) + (with-current-buffer (find-file test-file) + (cj/copy-link-to-buffer-file) + (should (equal (car kill-ring) (concat "file://" test-file))))) + (test-copy-link-teardown))) + +(ert-deftest test-copy-link-symlink-file () + "Should use buffer's filename for symlink." + (test-copy-link-setup) + (unwind-protect + (let* ((test-dir (cj/create-test-subdirectory "test")) + (target-file (expand-file-name "target.txt" test-dir)) + (link-file (expand-file-name "link.txt" test-dir))) + (with-temp-file target-file + (insert "content")) + (make-symbolic-link target-file link-file) + (with-current-buffer (find-file link-file) + (cj/copy-link-to-buffer-file) + ;; Should use the link name (what buffer-file-name returns) + (should (equal (car kill-ring) (concat "file://" (buffer-file-name)))))) + (test-copy-link-teardown))) + +(ert-deftest test-copy-link-kill-ring-has-content () + "Should add to kill ring when it already has content." + (test-copy-link-setup) + (unwind-protect + (let* ((test-dir (cj/create-test-subdirectory "test")) + (test-file (expand-file-name "test.txt" test-dir))) + (with-temp-file test-file + (insert "content")) + (kill-new "existing content") + (with-current-buffer (find-file test-file) + (cj/copy-link-to-buffer-file) + (should (equal (car kill-ring) (concat "file://" test-file))) + (should (equal (cadr kill-ring) "existing content")))) + (test-copy-link-teardown))) + +(ert-deftest test-copy-link-empty-kill-ring () + "Should populate empty kill ring." + (test-copy-link-setup) + (unwind-protect + (let* ((test-dir (cj/create-test-subdirectory "test")) + (test-file (expand-file-name "test.txt" test-dir))) + (with-temp-file test-file + (insert "content")) + (setq kill-ring nil) + (with-current-buffer (find-file test-file) + (cj/copy-link-to-buffer-file) + (should (equal (car kill-ring) (concat "file://" test-file))) + (should (= (length kill-ring) 1)))) + (test-copy-link-teardown))) + +(ert-deftest test-copy-link-scratch-buffer () + "Should do nothing for *scratch* buffer." + (test-copy-link-setup) + (unwind-protect + (progn + (setq kill-ring nil) + (with-current-buffer "*scratch*" + (cj/copy-link-to-buffer-file) + (should (null kill-ring)))) + (test-copy-link-teardown))) + +(provide 'test-custom-file-buffer-copy-link-to-buffer-file) +;;; test-custom-file-buffer-copy-link-to-buffer-file.el ends here diff --git a/tests/test-custom-file-buffer-copy-path-to-buffer-file-as-kill.el b/tests/test-custom-file-buffer-copy-path-to-buffer-file-as-kill.el new file mode 100644 index 00000000..e7a6f64b --- /dev/null +++ b/tests/test-custom-file-buffer-copy-path-to-buffer-file-as-kill.el @@ -0,0 +1,205 @@ +;;; test-custom-file-buffer-copy-path-to-buffer-file-as-kill.el --- Tests for cj/copy-path-to-buffer-file-as-kill -*- lexical-binding: t; -*- + +;;; Commentary: +;; Tests for the cj/copy-path-to-buffer-file-as-kill function from custom-file-buffer.el +;; +;; This function copies the full path of the current buffer's file to the kill ring +;; and returns the path. It signals an error if the buffer is not visiting a file. + +;;; Code: + +(require 'ert) +(require 'testutil-general) + +;; Add modules directory to load path +(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory)) + +;; Stub dependencies before loading the module +(defvar cj/custom-keymap (make-sparse-keymap) + "Stub keymap for testing.") + +;; Stub ps-print package +(provide 'ps-print) + +;; Now load the actual production module +(require 'custom-file-buffer) + +;;; Setup and Teardown + +(defun test-copy-path-setup () + "Set up test environment." + (setq kill-ring nil)) + +(defun test-copy-path-teardown () + "Clean up test environment." + ;; Kill all buffers visiting files in the test directory + (dolist (buf (buffer-list)) + (when (buffer-file-name buf) + (when (string-prefix-p cj/test-base-dir (buffer-file-name buf)) + (with-current-buffer buf + (set-buffer-modified-p nil) + (kill-buffer buf))))) + (cj/delete-test-base-dir) + (setq kill-ring nil)) + +;;; Normal Cases + +(ert-deftest test-copy-path-simple-file () + "Should copy absolute path for simple file buffer." + (test-copy-path-setup) + (unwind-protect + (let* ((test-dir (cj/create-test-subdirectory "test")) + (test-file (expand-file-name "test.txt" test-dir))) + (with-temp-file test-file + (insert "content")) + (with-current-buffer (find-file test-file) + (let ((result (cj/copy-path-to-buffer-file-as-kill))) + (should (equal result test-file)) + (should (equal (car kill-ring) test-file))))) + (test-copy-path-teardown))) + +(ert-deftest test-copy-path-returns-path () + "Should return the path value." + (test-copy-path-setup) + (unwind-protect + (let* ((test-dir (cj/create-test-subdirectory "test")) + (test-file (expand-file-name "test.txt" test-dir))) + (with-temp-file test-file + (insert "content")) + (with-current-buffer (find-file test-file) + (let ((result (cj/copy-path-to-buffer-file-as-kill))) + (should (stringp result)) + (should (equal result test-file))))) + (test-copy-path-teardown))) + +;;; Boundary Cases + +(ert-deftest test-copy-path-unicode-filename () + "Should handle unicode in filename." + (test-copy-path-setup) + (unwind-protect + (let* ((test-dir (cj/create-test-subdirectory "test")) + (test-file (expand-file-name "café.txt" test-dir))) + (with-temp-file test-file + (insert "content")) + (with-current-buffer (find-file test-file) + (cj/copy-path-to-buffer-file-as-kill) + (should (equal (car kill-ring) test-file)))) + (test-copy-path-teardown))) + +(ert-deftest test-copy-path-spaces-in-filename () + "Should handle spaces in filename." + (test-copy-path-setup) + (unwind-protect + (let* ((test-dir (cj/create-test-subdirectory "test")) + (test-file (expand-file-name "my file.txt" test-dir))) + (with-temp-file test-file + (insert "content")) + (with-current-buffer (find-file test-file) + (cj/copy-path-to-buffer-file-as-kill) + (should (equal (car kill-ring) test-file)))) + (test-copy-path-teardown))) + +(ert-deftest test-copy-path-special-chars-filename () + "Should handle special characters in filename." + (test-copy-path-setup) + (unwind-protect + (let* ((test-dir (cj/create-test-subdirectory "test")) + (test-file (expand-file-name "[test]-(1).txt" test-dir))) + (with-temp-file test-file + (insert "content")) + (with-current-buffer (find-file test-file) + (cj/copy-path-to-buffer-file-as-kill) + (should (equal (car kill-ring) test-file)))) + (test-copy-path-teardown))) + +(ert-deftest test-copy-path-very-long-path () + "Should handle very long path." + (test-copy-path-setup) + (unwind-protect + (let* ((test-dir (cj/create-test-subdirectory "test")) + (long-name (make-string 200 ?x)) + (test-file (expand-file-name (concat long-name ".txt") test-dir))) + (with-temp-file test-file + (insert "content")) + (with-current-buffer (find-file test-file) + (cj/copy-path-to-buffer-file-as-kill) + (should (equal (car kill-ring) test-file)))) + (test-copy-path-teardown))) + +(ert-deftest test-copy-path-hidden-file () + "Should handle hidden file." + (test-copy-path-setup) + (unwind-protect + (let* ((test-dir (cj/create-test-subdirectory "test")) + (test-file (expand-file-name ".hidden" test-dir))) + (with-temp-file test-file + (insert "content")) + (with-current-buffer (find-file test-file) + (cj/copy-path-to-buffer-file-as-kill) + (should (equal (car kill-ring) test-file)))) + (test-copy-path-teardown))) + +(ert-deftest test-copy-path-no-extension () + "Should handle file with no extension." + (test-copy-path-setup) + (unwind-protect + (let* ((test-dir (cj/create-test-subdirectory "test")) + (test-file (expand-file-name "README" test-dir))) + (with-temp-file test-file + (insert "content")) + (with-current-buffer (find-file test-file) + (cj/copy-path-to-buffer-file-as-kill) + (should (equal (car kill-ring) test-file)))) + (test-copy-path-teardown))) + +(ert-deftest test-copy-path-symlink-file () + "Should use buffer's filename for symlink." + (test-copy-path-setup) + (unwind-protect + (let* ((test-dir (cj/create-test-subdirectory "test")) + (target-file (expand-file-name "target.txt" test-dir)) + (link-file (expand-file-name "link.txt" test-dir))) + (with-temp-file target-file + (insert "content")) + (make-symbolic-link target-file link-file) + (with-current-buffer (find-file link-file) + (cj/copy-path-to-buffer-file-as-kill) + (should (equal (car kill-ring) (buffer-file-name))))) + (test-copy-path-teardown))) + +(ert-deftest test-copy-path-kill-ring-has-content () + "Should add to kill ring when it already has content." + (test-copy-path-setup) + (unwind-protect + (let* ((test-dir (cj/create-test-subdirectory "test")) + (test-file (expand-file-name "test.txt" test-dir))) + (with-temp-file test-file + (insert "content")) + (kill-new "existing content") + (with-current-buffer (find-file test-file) + (cj/copy-path-to-buffer-file-as-kill) + (should (equal (car kill-ring) test-file)) + (should (equal (cadr kill-ring) "existing content")))) + (test-copy-path-teardown))) + +;;; Error Cases + +(ert-deftest test-copy-path-non-file-buffer () + "Should signal user-error for non-file buffer." + (test-copy-path-setup) + (unwind-protect + (with-temp-buffer + (should-error (cj/copy-path-to-buffer-file-as-kill) :type 'user-error)) + (test-copy-path-teardown))) + +(ert-deftest test-copy-path-scratch-buffer () + "Should signal user-error for *scratch* buffer." + (test-copy-path-setup) + (unwind-protect + (with-current-buffer "*scratch*" + (should-error (cj/copy-path-to-buffer-file-as-kill) :type 'user-error)) + (test-copy-path-teardown))) + +(provide 'test-custom-file-buffer-copy-path-to-buffer-file-as-kill) +;;; test-custom-file-buffer-copy-path-to-buffer-file-as-kill.el ends here diff --git a/tests/test-custom-file-buffer-copy-whole-buffer.el b/tests/test-custom-file-buffer-copy-whole-buffer.el new file mode 100644 index 00000000..a0546b18 --- /dev/null +++ b/tests/test-custom-file-buffer-copy-whole-buffer.el @@ -0,0 +1,194 @@ +;;; test-custom-file-buffer-copy-whole-buffer.el --- Tests for cj/copy-whole-buffer -*- lexical-binding: t; -*- + +;;; Commentary: +;; Tests for the cj/copy-whole-buffer function from custom-file-buffer.el +;; +;; This function copies the entire contents of the current buffer to the kill ring. +;; Point and mark are left exactly where they were. No transient region is created. + +;;; Code: + +(require 'ert) +(require 'testutil-general) + +;; Add modules directory to load path +(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory)) + +;; Stub dependencies before loading the module +(defvar cj/custom-keymap (make-sparse-keymap) + "Stub keymap for testing.") + +;; Stub ps-print package +(provide 'ps-print) + +;; Now load the actual production module +(require 'custom-file-buffer) + +;;; Setup and Teardown + +(defun test-copy-whole-buffer-setup () + "Set up test environment." + (setq kill-ring nil)) + +(defun test-copy-whole-buffer-teardown () + "Clean up test environment." + (setq kill-ring nil)) + +;;; Normal Cases + +(ert-deftest test-copy-whole-buffer-simple-text () + "Should copy simple text content to kill ring." + (test-copy-whole-buffer-setup) + (unwind-protect + (with-temp-buffer + (insert "Hello, world!") + (cj/copy-whole-buffer) + (should (equal (car kill-ring) "Hello, world!"))) + (test-copy-whole-buffer-teardown))) + +(ert-deftest test-copy-whole-buffer-preserves-point () + "Should preserve point position." + (test-copy-whole-buffer-setup) + (unwind-protect + (with-temp-buffer + (insert "Hello, world!") + (goto-char 7) ; Position in middle + (cj/copy-whole-buffer) + (should (= (point) 7))) + (test-copy-whole-buffer-teardown))) + +(ert-deftest test-copy-whole-buffer-preserves-mark () + "Should preserve mark position." + (test-copy-whole-buffer-setup) + (unwind-protect + (with-temp-buffer + (insert "Hello, world!") + (push-mark 5) + (goto-char 10) + (cj/copy-whole-buffer) + (should (= (mark) 5)) + (should (= (point) 10))) + (test-copy-whole-buffer-teardown))) + +;;; Boundary Cases + +(ert-deftest test-copy-whole-buffer-empty () + "Should handle empty buffer." + (test-copy-whole-buffer-setup) + (unwind-protect + (with-temp-buffer + (cj/copy-whole-buffer) + (should (equal (car kill-ring) ""))) + (test-copy-whole-buffer-teardown))) + +(ert-deftest test-copy-whole-buffer-large () + "Should handle very large buffer." + (test-copy-whole-buffer-setup) + (unwind-protect + (with-temp-buffer + (let ((large-content (make-string 100000 ?x))) + (insert large-content) + (cj/copy-whole-buffer) + (should (equal (car kill-ring) large-content)))) + (test-copy-whole-buffer-teardown))) + +(ert-deftest test-copy-whole-buffer-unicode () + "Should handle unicode content (emoji, RTL text)." + (test-copy-whole-buffer-setup) + (unwind-protect + (with-temp-buffer + (insert "Hello 👋 Ù…Ø±ØØ¨Ø§") + (cj/copy-whole-buffer) + (should (equal (car kill-ring) "Hello 👋 Ù…Ø±ØØ¨Ø§"))) + (test-copy-whole-buffer-teardown))) + +(ert-deftest test-copy-whole-buffer-binary () + "Should handle binary content." + (test-copy-whole-buffer-setup) + (unwind-protect + (with-temp-buffer + (insert (string 0 1 2 255)) + (cj/copy-whole-buffer) + (should (equal (car kill-ring) (string 0 1 2 255)))) + (test-copy-whole-buffer-teardown))) + +(ert-deftest test-copy-whole-buffer-only-whitespace () + "Should handle buffer with only whitespace." + (test-copy-whole-buffer-setup) + (unwind-protect + (with-temp-buffer + (insert " \t\n ") + (cj/copy-whole-buffer) + (should (equal (car kill-ring) " \t\n "))) + (test-copy-whole-buffer-teardown))) + +(ert-deftest test-copy-whole-buffer-newlines-at-boundaries () + "Should handle newlines at start/end." + (test-copy-whole-buffer-setup) + (unwind-protect + (with-temp-buffer + (insert "\n\nHello\n\n") + (cj/copy-whole-buffer) + (should (equal (car kill-ring) "\n\nHello\n\n"))) + (test-copy-whole-buffer-teardown))) + +(ert-deftest test-copy-whole-buffer-narrowed () + "Should copy only visible region in narrowed buffer." + (test-copy-whole-buffer-setup) + (unwind-protect + (with-temp-buffer + (insert "Line 1\nLine 2\nLine 3\n") + (goto-char (point-min)) + (forward-line 1) + (narrow-to-region (point) (progn (forward-line 1) (point))) + (cj/copy-whole-buffer) + ;; Should copy only the narrowed region + (should (equal (car kill-ring) "Line 2\n"))) + (test-copy-whole-buffer-teardown))) + +(ert-deftest test-copy-whole-buffer-read-only () + "Should work in read-only buffer." + (test-copy-whole-buffer-setup) + (unwind-protect + (with-temp-buffer + (insert "Read-only content") + (read-only-mode 1) + (cj/copy-whole-buffer) + (should (equal (car kill-ring) "Read-only content"))) + (test-copy-whole-buffer-teardown))) + +(ert-deftest test-copy-whole-buffer-kill-ring-has-content () + "Should add to kill ring when it already has content." + (test-copy-whole-buffer-setup) + (unwind-protect + (with-temp-buffer + (insert "New content") + (kill-new "existing content") + (cj/copy-whole-buffer) + (should (equal (car kill-ring) "New content")) + (should (equal (cadr kill-ring) "existing content"))) + (test-copy-whole-buffer-teardown))) + +(ert-deftest test-copy-whole-buffer-multiline () + "Should preserve multiline content." + (test-copy-whole-buffer-setup) + (unwind-protect + (with-temp-buffer + (insert "Line 1\nLine 2\nLine 3") + (cj/copy-whole-buffer) + (should (equal (car kill-ring) "Line 1\nLine 2\nLine 3"))) + (test-copy-whole-buffer-teardown))) + +(ert-deftest test-copy-whole-buffer-no-properties () + "Should strip text properties." + (test-copy-whole-buffer-setup) + (unwind-protect + (with-temp-buffer + (insert (propertize "Hello" 'face 'bold)) + (cj/copy-whole-buffer) + (should (equal (car kill-ring) "Hello")) + (should (null (text-properties-at 0 (car kill-ring))))) + (test-copy-whole-buffer-teardown))) + +(provide 'test-custom-file-buffer-copy-whole-buffer) +;;; test-custom-file-buffer-copy-whole-buffer.el ends here |
