aboutsummaryrefslogtreecommitdiff
path: root/archive/gptel/tests/test-ai-config-commands.el
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-23 20:12:58 -0400
committerCraig Jennings <c@cjennings.net>2026-06-23 20:12:58 -0400
commit10fa6f4e2e7150ad99827721ada1ae4badcc5e90 (patch)
tree960065c8e69f1e7a4150ecf522e2f813c239b5ee /archive/gptel/tests/test-ai-config-commands.el
parentf4cc70c69e7707dd4a686637e14885f5443fcca6 (diff)
downloaddotemacs-10fa6f4e2e7150ad99827721ada1ae4badcc5e90.tar.gz
dotemacs-10fa6f4e2e7150ad99827721ada1ae4badcc5e90.zip
chore(ai): archive gptel and remove it from the live config
I archived gptel to archive/gptel/ since I rarely use it. Moved there: the six gptel modules (ai-config, ai-conversations, ai-conversations-browser, ai-mcp, ai-quick-ask, ai-rewrite), the gptel-tools/ directory, custom/gptel-prompts.el, their test files and utilities, and the four gptel-only specs. Scrubbed from the live config: the ai-config require in init.el, which also drops the whole C-; a keymap; the gptel-mode emojify hook in font-config.el; the gptel-tools entries in the Makefile clean target and the coverage runner; and the gptel feature notes in README. Cancelled the open gptel tasks in todo.org (the AI Open Work issues, the feature-extension brainstorm, the velox gptel-magit bug). ai-term stays. It is the ghostel Claude launcher, independent of gptel. Verified: every module loads, a batch init launch reaches completion clean, and the full test suite shows only pre-existing coverage failures unrelated to this change.
Diffstat (limited to 'archive/gptel/tests/test-ai-config-commands.el')
-rw-r--r--archive/gptel/tests/test-ai-config-commands.el160
1 files changed, 160 insertions, 0 deletions
diff --git a/archive/gptel/tests/test-ai-config-commands.el b/archive/gptel/tests/test-ai-config-commands.el
new file mode 100644
index 00000000..fed06d82
--- /dev/null
+++ b/archive/gptel/tests/test-ai-config-commands.el
@@ -0,0 +1,160 @@
+;;; test-ai-config-commands.el --- Tests for ai-config interactive commands -*- lexical-binding: t; -*-
+
+;;; Commentary:
+;; Sibling tests cover the pure helpers (model-to-string, build-model-list,
+;; current-model-selection, fresh-org-prefix, backend-and-model). This
+;; file covers the user-facing wrappers:
+;;
+;; cj/gptel--available-backends
+;; cj/gptel-change-model
+;; cj/gptel-add-file
+;; cj/gptel-add-this-buffer
+;; cj/toggle-gptel
+;; cj/gptel-context-clear
+
+;;; Code:
+
+(require 'ert)
+(require 'cl-lib)
+
+(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory))
+(require 'ai-config)
+
+;; Top-level defvars so let-bindings reach the dynamic binding under
+;; lexical scope.
+(defvar gptel-backend nil)
+(defvar gptel-model nil)
+(defvar gptel-claude-backend nil)
+(defvar gptel-chatgpt-backend nil)
+(defvar gptel-context--alist nil)
+
+;;; cj/gptel--available-backends
+
+(ert-deftest test-ai-available-backends-returns-claude-and-chatgpt ()
+ "Normal: both backends present become alist entries."
+ (let ((gptel-claude-backend 'claude-obj)
+ (gptel-chatgpt-backend 'chatgpt-obj))
+ (cl-letf (((symbol-function 'require) (lambda (&rest _) t))
+ ((symbol-function 'cj/ensure-gptel-backends) #'ignore))
+ (let ((result (cj/gptel--available-backends)))
+ (should (equal (assoc "Anthropic - Claude" result)
+ '("Anthropic - Claude" . claude-obj)))
+ (should (equal (assoc "OpenAI - ChatGPT" result)
+ '("OpenAI - ChatGPT" . chatgpt-obj)))))))
+
+(ert-deftest test-ai-available-backends-skips-nil-entries ()
+ "Boundary: only configured backends appear in the alist."
+ (let ((gptel-claude-backend nil)
+ (gptel-chatgpt-backend 'chatgpt-only))
+ (cl-letf (((symbol-function 'require) (lambda (&rest _) t))
+ ((symbol-function 'cj/ensure-gptel-backends) #'ignore))
+ (let ((result (cj/gptel--available-backends)))
+ (should-not (assoc "Anthropic - Claude" result))
+ (should (assoc "OpenAI - ChatGPT" result))))))
+
+;;; cj/gptel-change-model
+
+(ert-deftest test-ai-change-model-global-sets-globals-and-messages ()
+ "Normal: choosing 'global' sets `gptel-backend' and `gptel-model'
+globally and reports via `message'."
+ (let ((gptel-backend 'old-backend)
+ (gptel-model 'old-model)
+ (gptel-claude-backend 'claude-obj)
+ (gptel-chatgpt-backend nil)
+ msg)
+ (cl-letf (((symbol-function 'require) (lambda (&rest _) t))
+ ((symbol-function 'cj/ensure-gptel-backends) #'ignore)
+ ((symbol-function 'gptel-backend-models)
+ (lambda (_) '("claude-opus-4-7")))
+ ((symbol-function 'completing-read)
+ (lambda (prompt &rest _)
+ (if (string-prefix-p "Set model for" prompt)
+ "global"
+ "Anthropic - Claude: claude-opus-4-7")))
+ ((symbol-function 'message)
+ (lambda (fmt &rest args) (setq msg (apply #'format fmt args)))))
+ (cj/gptel-change-model))
+ (should (eq gptel-backend 'claude-obj))
+ (should (eq gptel-model 'claude-opus-4-7))
+ (should (string-match-p "global" msg))))
+
+;;; cj/gptel-add-file
+
+(ert-deftest test-ai-add-file-outside-projectile-uses-read-file-name ()
+ "Normal: without projectile, add-file routes through read-file-name."
+ (let* ((target (make-temp-file "cj-ai-add-file-" nil ".org"))
+ added)
+ (unwind-protect
+ (cl-letf (((symbol-function 'featurep)
+ (lambda (sym &rest _) (not (eq sym 'projectile))))
+ ((symbol-function 'read-file-name)
+ (lambda (&rest _) target))
+ ((symbol-function 'gptel-add-file)
+ (lambda (f) (setq added f)))
+ ((symbol-function 'message) #'ignore))
+ (cj/gptel-add-file))
+ (delete-file target))
+ (should (equal added target))))
+
+;;; cj/gptel-add-this-buffer
+
+(ert-deftest test-ai-add-this-buffer-calls-gptel-add-with-prefix ()
+ "Normal: add-this-buffer calls `gptel-add' with the prefix-arg form."
+ (let (gptel-add-args msg)
+ (cl-letf (((symbol-function 'require) (lambda (&rest _) t))
+ ((symbol-function 'gptel-add)
+ (lambda (&rest args) (setq gptel-add-args args)))
+ ((symbol-function 'message)
+ (lambda (fmt &rest args) (setq msg (apply #'format fmt args)))))
+ (cj/gptel-add-this-buffer))
+ (should (equal gptel-add-args '((4))))
+ (should (string-match-p "to GPTel context" msg))))
+
+;;; cj/toggle-gptel
+
+(ert-deftest test-ai-toggle-gptel-hides-when-visible ()
+ "Normal: when the AI buffer is showing in a window, toggle hides it."
+ (let ((buffer (get-buffer-create "*AI-Assistant*"))
+ deleted-window)
+ (unwind-protect
+ (cl-letf (((symbol-function 'get-buffer-window)
+ (lambda (&rest _) 'fake-window))
+ ((symbol-function 'delete-window)
+ (lambda (w) (setq deleted-window w))))
+ (cj/toggle-gptel))
+ (kill-buffer buffer))
+ (should (eq deleted-window 'fake-window))))
+
+;;; cj/gptel-context-clear
+
+(ert-deftest test-ai-context-clear-uses-remove-all-when-available ()
+ "Normal: with `gptel-context-remove-all' present, it is called."
+ (let (called msg)
+ (cl-letf (((symbol-function 'gptel-context-remove-all)
+ (lambda () (setq called t)))
+ ((symbol-function 'call-interactively)
+ (lambda (fn &rest _) (funcall fn)))
+ ((symbol-function 'message)
+ (lambda (fmt &rest args) (setq msg (apply #'format fmt args)))))
+ (cj/gptel-context-clear))
+ (should called)
+ (should (string-match-p "cleared" msg))))
+
+(ert-deftest test-ai-context-clear-resets-alist-as-fallback ()
+ "Boundary: when no clear function exists but the alist does, it gets
+nilled directly."
+ (let ((gptel-context--alist '("item1" "item2"))
+ msg)
+ ;; Make sure the fboundp branches are skipped.
+ (cl-letf (((symbol-function 'fboundp)
+ (lambda (sym)
+ (not (memq sym '(gptel-context-remove-all
+ gptel-context-clear)))))
+ ((symbol-function 'message)
+ (lambda (fmt &rest args) (setq msg (apply #'format fmt args)))))
+ (cj/gptel-context-clear))
+ (should-not gptel-context--alist)
+ (should (string-match-p "cleared" msg))))
+
+(provide 'test-ai-config-commands)
+;;; test-ai-config-commands.el ends here