aboutsummaryrefslogtreecommitdiff
path: root/tests/test-ai-config-helpers.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 /tests/test-ai-config-helpers.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 'tests/test-ai-config-helpers.el')
-rw-r--r--tests/test-ai-config-helpers.el183
1 files changed, 0 insertions, 183 deletions
diff --git a/tests/test-ai-config-helpers.el b/tests/test-ai-config-helpers.el
deleted file mode 100644
index cdbc0f6e..00000000
--- a/tests/test-ai-config-helpers.el
+++ /dev/null
@@ -1,183 +0,0 @@
-;;; test-ai-config-helpers.el --- Tests for ai-config helper functions -*- lexical-binding: t; -*-
-
-;;; Commentary:
-;; Covers helpers that don't depend on a live gptel install:
-;;
-;; cj/auth-source-secret
-;; cj/anthropic-api-key (caching wrapper)
-;; cj/openai-api-key (caching wrapper)
-;; cj/gptel--add-file-to-context
-;; cj/gptel-clear-buffer
-;; cj/gptel-context-clear
-;; cj/gptel-insert-model-heading
-;;
-;; External primitives (`auth-source-search', `gptel-add-file', etc.)
-;; are stubbed so the tests never touch the keyring or the network.
-
-;;; Code:
-
-(require 'ert)
-(require 'cl-lib)
-
-(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory))
-(require 'ai-config)
-
-;; Make `gptel-context--alist' a real dynamic variable for the fallback
-;; test below. Under lexical-binding a plain `let' is lexical, so the
-;; `setq' inside `cj/gptel-context-clear' would otherwise miss it.
-(defvar gptel-context--alist nil
- "Dynamic stand-in for the gptel-context alist (gptel not loaded here).")
-
-;;; cj/auth-source-secret
-
-(ert-deftest test-ai-config-auth-source-secret-returns-string ()
- "Normal: a plain-string secret comes back as-is."
- (cl-letf (((symbol-function 'auth-source-search)
- (lambda (&rest _) '((:secret "plaintext")))))
- (should (equal (cj/auth-source-secret "example.com" "user")
- "plaintext"))))
-
-(ert-deftest test-ai-config-auth-source-secret-unwraps-function ()
- "Normal: a function secret is funcall'd to retrieve the value."
- (cl-letf (((symbol-function 'auth-source-search)
- (lambda (&rest _) (list (list :secret (lambda () "called"))))))
- (should (equal (cj/auth-source-secret "example.com" "user")
- "called"))))
-
-(ert-deftest test-ai-config-auth-source-secret-errors-when-missing ()
- "Error: an empty result raises a clear error."
- (cl-letf (((symbol-function 'auth-source-search)
- (lambda (&rest _) nil)))
- (should-error (cj/auth-source-secret "nope.example.com" "user")
- :type 'error)))
-
-;;; cj/anthropic-api-key / cj/openai-api-key
-
-(ert-deftest test-ai-config-anthropic-api-key-caches-after-first-call ()
- "Normal: a subsequent call returns the cached value without re-fetching."
- (let ((cj/anthropic-api-key-cached nil)
- (call-count 0))
- (cl-letf (((symbol-function 'auth-source-search)
- (lambda (&rest _)
- (cl-incf call-count)
- '((:secret "anth-key")))))
- (should (equal (cj/anthropic-api-key) "anth-key"))
- (should (equal (cj/anthropic-api-key) "anth-key"))
- (should (= call-count 1)))))
-
-(ert-deftest test-ai-config-openai-api-key-caches-after-first-call ()
- "Normal: same caching contract as the anthropic key."
- (let ((cj/openai-api-key-cached nil)
- (call-count 0))
- (cl-letf (((symbol-function 'auth-source-search)
- (lambda (&rest _)
- (cl-incf call-count)
- '((:secret "oai-key")))))
- (should (equal (cj/openai-api-key) "oai-key"))
- (should (equal (cj/openai-api-key) "oai-key"))
- (should (= call-count 1)))))
-
-;;; cj/gptel--add-file-to-context
-
-(ert-deftest test-ai-config-add-file-to-context-adds-existing-file ()
- "Normal: an existing file is added and the function returns t."
- (let ((tmp (make-temp-file "ai-config-add-file-")))
- (unwind-protect
- (let ((gptel-context--alist nil)
- (added nil))
- (cl-letf (((symbol-function 'gptel-add-file)
- (lambda (f) (setq added f)))
- ((symbol-function 'message) #'ignore))
- (should (eq (cj/gptel--add-file-to-context tmp) t))
- (should (equal added tmp))))
- (delete-file tmp))))
-
-(ert-deftest test-ai-config-add-file-to-context-skips-missing-file ()
- "Boundary: a non-existent path returns nil and doesn't call gptel-add-file."
- (let ((called nil))
- (cl-letf (((symbol-function 'gptel-add-file)
- (lambda (_) (setq called t))))
- (should-not (cj/gptel--add-file-to-context "/no/such/path"))
- (should-not called))))
-
-(ert-deftest test-ai-config-add-file-to-context-skips-nil-path ()
- "Boundary: a nil path returns nil without calling gptel-add-file."
- (let ((called nil))
- (cl-letf (((symbol-function 'gptel-add-file)
- (lambda (_) (setq called t))))
- (should-not (cj/gptel--add-file-to-context nil))
- (should-not called))))
-
-;;; cj/gptel-clear-buffer
-
-(ert-deftest test-ai-config-clear-buffer-erases-in-gptel-org-buffer ()
- "Normal: a gptel-mode org buffer is erased and the fresh org prefix is reinserted."
- (with-temp-buffer
- (delay-mode-hooks (org-mode))
- (setq-local gptel-mode t)
- (insert "* Existing conversation\nstuff\n")
- (let ((msg nil))
- (cl-letf (((symbol-function 'message)
- (lambda (fmt &rest args)
- (setq msg (apply #'format fmt args)))))
- (cj/gptel-clear-buffer))
- (should (string-match-p "cleared" msg)))
- ;; The fresh prefix is an org heading starting with "* ".
- (should (string-prefix-p "* " (buffer-string)))
- (should-not (string-match-p "Existing conversation" (buffer-string)))))
-
-(ert-deftest test-ai-config-clear-buffer-noop-when-not-gptel-org ()
- "Boundary: in a non-gptel buffer the function messages and changes nothing."
- (with-temp-buffer
- (insert "untouched\n")
- (let ((msg nil))
- (cl-letf (((symbol-function 'message)
- (lambda (fmt &rest args)
- (setq msg (apply #'format fmt args)))))
- (cj/gptel-clear-buffer))
- (should (string-match-p "Not a GPTel buffer" msg))
- (should (equal (buffer-string) "untouched\n")))))
-
-;;; cj/gptel-context-clear
-
-(ert-deftest test-ai-config-context-clear-uses-remove-all-when-available ()
- "Normal: when `gptel-context-remove-all' is bound, it wins the cond.
-The stub must be a command because `cj/gptel-context-clear' invokes it
-via `call-interactively'."
- (let ((called nil)
- (msg nil))
- (cl-letf (((symbol-function 'gptel-context-remove-all)
- (lambda () (interactive) (setq called 'remove-all)))
- ((symbol-function 'message)
- (lambda (fmt &rest args) (setq msg (apply #'format fmt args)))))
- (cj/gptel-context-clear))
- (should (eq called 'remove-all))
- (should (string-match-p "cleared" msg))))
-
-(ert-deftest test-ai-config-context-clear-falls-back-to-alist-setq ()
- "Boundary: when no clearing function exists, the alist is set to nil."
- (let ((gptel-context--alist '((:dummy)))
- (msg nil))
- (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 (null gptel-context--alist))
- (should (string-match-p "cleared" msg))))
-
-;;; cj/gptel-insert-model-heading
-
-(ert-deftest test-ai-config-insert-model-heading-inserts-at-given-position ()
- "Normal: an Org heading is inserted at RESPONSE-BEGIN-POS."
- (with-temp-buffer
- (insert "response text")
- (cl-letf (((symbol-function 'cj/gptel-backend-and-model)
- (lambda () "Anthropic: claude-test [2026-05-13 12:00:00]")))
- (cj/gptel-insert-model-heading (point-min) (point-max)))
- (should (string-prefix-p "* Anthropic: claude-test" (buffer-string)))
- (should (string-match-p "\nresponse text" (buffer-string)))))
-
-(provide 'test-ai-config-helpers)
-;;; test-ai-config-helpers.el ends here