aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/test-ai-vterm--display-saved.el4
-rw-r--r--tests/test-ai-vterm--reuse-edge-window.el10
-rw-r--r--tests/test-ai-vterm--single-window-toggle.el12
-rw-r--r--tests/test-ai-vterm--terminal-guard.el78
-rw-r--r--tests/testutil-vterm-buffers.el13
5 files changed, 104 insertions, 13 deletions
diff --git a/tests/test-ai-vterm--display-saved.el b/tests/test-ai-vterm--display-saved.el
index 866ff11d..0cf59a29 100644
--- a/tests/test-ai-vterm--display-saved.el
+++ b/tests/test-ai-vterm--display-saved.el
@@ -155,8 +155,8 @@ once and no spurious extra window leaks."
(let ((display-buffer-alist (cj/--ai-vterm-display-rule-list))
(window-count-before (count-windows)))
(select-window agent-win)
- (cj/ai-vterm) ; off
- (cj/ai-vterm) ; on
+ (cj/test--call-as-gui #'cj/ai-vterm) ; off
+ (cj/test--call-as-gui #'cj/ai-vterm) ; on
(should (<= (count-windows) window-count-before))
;; Agent must be displayed exactly once.
(let ((agent-windows
diff --git a/tests/test-ai-vterm--reuse-edge-window.el b/tests/test-ai-vterm--reuse-edge-window.el
index a7009423..9f621477 100644
--- a/tests/test-ai-vterm--reuse-edge-window.el
+++ b/tests/test-ai-vterm--reuse-edge-window.el
@@ -175,7 +175,7 @@ window count stays 2 (the native `quit-restore-window' puts 2 back)."
(should (= (count-windows) 2))
(should (member agent-name (cj/test--displayed-buffer-names)))
;; Toggle off -> the displaced buffer (2) returns to the slot.
- (cj/ai-vterm)
+ (cj/test--call-as-gui #'cj/ai-vterm)
(should (= (count-windows) 2))
(let ((bufs (cj/test--displayed-buffer-names)))
(should (member right-name bufs))
@@ -213,11 +213,11 @@ the same width."
(display-buffer agent-buf)
(should (= (count-windows) 2))
;; off
- (cj/ai-vterm)
+ (cj/test--call-as-gui #'cj/ai-vterm)
(should (= (count-windows) 2))
(should-not (cj/--ai-vterm-displayed-agent-window))
;; on again
- (cj/ai-vterm)
+ (cj/test--call-as-gui #'cj/ai-vterm)
(should (= (count-windows) 2))
(let ((win (cj/--ai-vterm-displayed-agent-window)))
(should (windowp win))
@@ -259,9 +259,9 @@ most-recent agent, which would now be the other one."
(display-buffer a2) ; | left | A2 |
(should (eq (window-buffer (cj/--ai-vterm-displayed-agent-window))
a2))
- (cj/ai-vterm) ; off -> | left | right |
+ (cj/test--call-as-gui #'cj/ai-vterm) ; off -> | left | right |
(should-not (cj/--ai-vterm-displayed-agent-window))
- (cj/ai-vterm) ; on -> must bring A2 back
+ (cj/test--call-as-gui #'cj/ai-vterm) ; on -> must bring A2 back
(should (eq (window-buffer (cj/--ai-vterm-displayed-agent-window))
a2))))))
(when (get-buffer left-name) (kill-buffer left-name))
diff --git a/tests/test-ai-vterm--single-window-toggle.el b/tests/test-ai-vterm--single-window-toggle.el
index 50f1504a..928656f2 100644
--- a/tests/test-ai-vterm--single-window-toggle.el
+++ b/tests/test-ai-vterm--single-window-toggle.el
@@ -48,12 +48,12 @@ batch use both."
(let ((display-buffer-alist (cj/--ai-vterm-display-rule-list)))
;; Toggle off -- the dispatcher's force-swap should put the
;; window on a non-agent buffer.
- (cj/ai-vterm)
+ (cj/test--call-as-gui #'cj/ai-vterm)
(should (one-window-p))
(should-not (cj/--ai-vterm-displayed-agent-window))
(should (eq cj/--ai-vterm-last-was-bury t))
;; Toggle on -- should restore agent in the same lone window.
- (cj/ai-vterm)
+ (cj/test--call-as-gui #'cj/ai-vterm)
(should (one-window-p))
(let ((win (cj/--ai-vterm-displayed-agent-window)))
(should (windowp win))
@@ -80,7 +80,7 @@ agent-window state and can route through the display-saved path."
(win (selected-window)))
(set-window-buffer win agent-buf)
(let ((display-buffer-alist (cj/--ai-vterm-display-rule-list)))
- (cj/ai-vterm))
+ (cj/test--call-as-gui #'cj/ai-vterm))
(should (window-live-p win))
(should-not (cj/--ai-vterm-buffer-p (window-buffer win)))))
(cj/test--kill-agent-buffers))))
@@ -96,7 +96,7 @@ agent-window state and can route through the display-saved path."
(let ((agent-buf (get-buffer-create agent-name)))
(set-window-buffer (selected-window) agent-buf)
(let ((display-buffer-alist (cj/--ai-vterm-display-rule-list)))
- (cj/ai-vterm)
+ (cj/test--call-as-gui #'cj/ai-vterm)
(should (eq cj/--ai-vterm-last-was-bury t)))))
(cj/test--kill-agent-buffers))))
@@ -119,7 +119,7 @@ toggle-off."
(display-buffer-alist (cj/--ai-vterm-display-rule-list)))
(set-window-buffer agent-win agent-buf)
(select-window agent-win)
- (cj/ai-vterm)
+ (cj/test--call-as-gui #'cj/ai-vterm)
(should-not cj/--ai-vterm-last-was-bury))))
(when (get-buffer left-name) (kill-buffer left-name))
(cj/test--kill-agent-buffers))))
@@ -176,7 +176,7 @@ the flag nil (no spurious set)."
(display-buffer-alist (cj/--ai-vterm-display-rule-list)))
(set-window-buffer agent-win agent-buf)
(select-window agent-win)
- (cj/ai-vterm)
+ (cj/test--call-as-gui #'cj/ai-vterm)
(should-not cj/--ai-vterm-last-was-bury))))
(when (get-buffer "*test-sw-untouched-left*")
(kill-buffer "*test-sw-untouched-left*"))
diff --git a/tests/test-ai-vterm--terminal-guard.el b/tests/test-ai-vterm--terminal-guard.el
new file mode 100644
index 00000000..5a7971bf
--- /dev/null
+++ b/tests/test-ai-vterm--terminal-guard.el
@@ -0,0 +1,78 @@
+;;; test-ai-vterm--terminal-guard.el --- Tests for the terminal-frame guard -*- lexical-binding: t; -*-
+
+;;; Commentary:
+;; AI-vterm launches a graphical vterm side window, so it is GUI-only.
+;; `cj/--ai-vterm-refuse-in-terminal' signals a `user-error' when the
+;; current frame is a terminal frame; each interactive entry point
+;; (`cj/ai-vterm', `cj/ai-vterm-pick-project', `cj/ai-vterm-close')
+;; calls it first so F9 and friends decline -- with a message -- in a
+;; terminal frame instead of launching a vterm. The check is per-frame
+;; at command time, not at load, so a daemon serving both GUI and
+;; terminal frames keeps the launcher working in its GUI frames.
+;;
+;; `env-terminal-p' is mocked so the tests are deterministic regardless
+;; of whether the run itself is graphical (batch runs are terminal).
+
+;;; Code:
+
+(require 'ert)
+(require 'cl-lib)
+
+(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory))
+(add-to-list 'load-path (expand-file-name "tests" user-emacs-directory))
+(require 'ai-vterm)
+
+;; ---------------------------- the guard helper ----------------------------
+
+(ert-deftest test-ai-vterm--refuse-in-terminal-errors-in-terminal-frame ()
+ "Error: terminal frame -> `user-error', so the command declines."
+ (cl-letf (((symbol-function 'env-terminal-p) (lambda () t)))
+ (should-error (cj/--ai-vterm-refuse-in-terminal) :type 'user-error)))
+
+(ert-deftest test-ai-vterm--refuse-in-terminal-passes-in-gui-frame ()
+ "Normal: GUI frame -> returns nil, no error, command proceeds."
+ (cl-letf (((symbol-function 'env-terminal-p) (lambda () nil)))
+ (should-not (cj/--ai-vterm-refuse-in-terminal))))
+
+;; ------------------- the three interactive entry points -------------------
+
+(ert-deftest test-ai-vterm-f9-declines-in-terminal-without-dispatching ()
+ "Error: F9 in a terminal frame errors and never reaches dispatch."
+ (let ((dispatched nil))
+ (cl-letf (((symbol-function 'env-terminal-p) (lambda () t))
+ ((symbol-function 'cj/--ai-vterm-dispatch)
+ (lambda () (setq dispatched t) '(pick-project))))
+ (should-error (cj/ai-vterm) :type 'user-error)
+ (should-not dispatched))))
+
+(ert-deftest test-ai-vterm-pick-project-declines-in-terminal-without-prompting ()
+ "Error: C-F9 in a terminal frame errors and never reaches the picker."
+ (let ((prompted nil))
+ (cl-letf (((symbol-function 'env-terminal-p) (lambda () t))
+ ((symbol-function 'cj/--ai-vterm-pick-project)
+ (lambda () (setq prompted t) "/tmp")))
+ (should-error (cj/ai-vterm-pick-project) :type 'user-error)
+ (should-not prompted))))
+
+(ert-deftest test-ai-vterm-close-declines-in-terminal-without-targeting ()
+ "Error: M-F9 in a terminal frame errors and never reaches close-target."
+ (let ((targeted nil))
+ (cl-letf (((symbol-function 'env-terminal-p) (lambda () t))
+ ((symbol-function 'cj/--ai-vterm-close-target)
+ (lambda () (setq targeted t) nil)))
+ (should-error (cj/ai-vterm-close) :type 'user-error)
+ (should-not targeted))))
+
+(ert-deftest test-ai-vterm-f9-passes-guard-in-gui-frame ()
+ "Normal: F9 in a GUI frame passes the guard and reaches dispatch."
+ (let ((dispatched nil))
+ (cl-letf (((symbol-function 'env-terminal-p) (lambda () nil))
+ ((symbol-function 'cj/--ai-vterm-dispatch)
+ (lambda () (setq dispatched t) '(pick-project)))
+ ((symbol-function 'cj/ai-vterm-pick-project)
+ (lambda (&optional _arg) nil)))
+ (cj/ai-vterm)
+ (should dispatched))))
+
+(provide 'test-ai-vterm--terminal-guard)
+;;; test-ai-vterm--terminal-guard.el ends here
diff --git a/tests/testutil-vterm-buffers.el b/tests/testutil-vterm-buffers.el
index 01a65d90..17f0a69a 100644
--- a/tests/testutil-vterm-buffers.el
+++ b/tests/testutil-vterm-buffers.el
@@ -9,6 +9,19 @@
;;; Code:
+(require 'cl-lib)
+
+(defun cj/test--call-as-gui (fn)
+ "Call FN with `env-terminal-p' stubbed to return nil (a GUI frame).
+
+The AI-vterm interactive commands refuse to run in a terminal frame
+via `cj/--ai-vterm-refuse-in-terminal'. A batch test run is itself a
+terminal frame, so tests that exercise the GUI-frame window behavior
+of those commands call them through this helper to present a GUI
+context."
+ (cl-letf (((symbol-function 'env-terminal-p) (lambda () nil)))
+ (funcall fn)))
+
(defun cj/test--kill-buffers-matching-prefix (prefix)
"Kill all live buffers whose name starts with PREFIX."
(dolist (b (buffer-list))