branch: externals/ellama
commit 4cb9bdaf98bab0fd0fd3e667dd29952849494489
Author: Sergey Kostyaev <[email protected]>
Commit: Sergey Kostyaev <[email protected]>
Add community prompts tests and refactor download logic
Implemented comprehensive unit tests for community prompts, updated
Makefile to
run the new test, and refactored the prompt download routine in
ellama-community-prompts.el to simplify directory handling and response
processing. The changes improve reliability, test coverage, and code
readability.
---
Makefile | 1 +
ellama-community-prompts.el | 27 +++---
tests/test-ellama-community-prompts.el | 149 +++++++++++++++++++++++++++++++++
3 files changed, 166 insertions(+), 11 deletions(-)
diff --git a/Makefile b/Makefile
index 095d54844d..557f8e9433 100644
--- a/Makefile
+++ b/Makefile
@@ -10,6 +10,7 @@ test:
-l ellama.el \
-l tests/test-ellama.el \
-l tests/test-ellama-blueprint.el \
+ -l tests/test-ellama-community-prompts.el \
--eval "(ert t)"
check-compile-warnings:
diff --git a/ellama-community-prompts.el b/ellama-community-prompts.el
index 8c31335c91..761ef50d29 100644
--- a/ellama-community-prompts.el
+++ b/ellama-community-prompts.el
@@ -53,17 +53,21 @@ within your `user-emacs-directory'."
Downloads the file from `ellama-community-prompts-url` if it does
not already exist."
(unless (file-exists-p ellama-community-prompts-file)
- (let* ((directory (file-name-directory ellama-community-prompts-file))
- (response (plz 'get ellama-community-prompts-url
- :as 'file
- :then (lambda (filename)
- (rename-file filename
ellama-community-prompts-file t))
- :else (lambda (error)
- (message "Failed to download community prompts:
%s" error)))))
- (when (and response (not (file-directory-p directory)))
+ (let ((directory (file-name-directory ellama-community-prompts-file)))
+ (unless (file-directory-p directory)
(make-directory directory t))
- (when response
- (message "Community prompts file downloaded successfully.")))))
+ (let ((response (plz 'get ellama-community-prompts-url
+ :as 'file
+ :then (lambda (filename)
+ (rename-file filename
+ ellama-community-prompts-file
+ t))
+ :else (lambda (error)
+ (message
+ "Failed to download community prompts: %s"
+ error)))))
+ (when response
+ (message "Community prompts file downloaded successfully."))))))
(defun ellama-community-prompts-parse-csv-line (line)
"Parse a single CSV LINE into a list of fields, handling quotes.
@@ -133,7 +137,8 @@ Returns the collection of community prompts."
line)))
(cdr (string-lines
(buffer-substring-no-properties
- (point-min) (point-max)))))))))
+ (point-min) (point-max))
+ t)))))))
ellama-community-prompts-collection)
;;;###autoload
diff --git a/tests/test-ellama-community-prompts.el
b/tests/test-ellama-community-prompts.el
new file mode 100644
index 0000000000..dad0c95019
--- /dev/null
+++ b/tests/test-ellama-community-prompts.el
@@ -0,0 +1,149 @@
+;;; test-ellama-community-prompts.el --- Community prompts tests -*-
lexical-binding: t; package-lint-main-file: "../ellama.el"; -*-
+
+;; Copyright (C) 2023-2026 Free Software Foundation, Inc.
+
+;; Author: Sergey Kostyaev <[email protected]>
+
+;; This file is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; This file is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Community prompt collection tests.
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'ert)
+
+(defconst ellama-community-prompts-test-root
+ (expand-file-name
+ ".."
+ (file-name-directory (or load-file-name buffer-file-name)))
+ "Project root directory for community prompts tests.")
+
+(load-file
+ (expand-file-name
+ "ellama-community-prompts.el"
+ ellama-community-prompts-test-root))
+
+(ert-deftest test-ellama-community-prompts-parse-csv-line-basic ()
+ (should (equal (ellama-community-prompts-parse-csv-line
+ "writer,Write a poem,FALSE")
+ '("writer" "Write a poem" "FALSE"))))
+
+(ert-deftest test-ellama-community-prompts-parse-csv-line-quoted-comma ()
+ (should (equal (ellama-community-prompts-parse-csv-line
+ "writer,\"Prompt, with comma\",FALSE")
+ '("writer" "Prompt, with comma" "FALSE"))))
+
+(ert-deftest test-ellama-community-prompts-parse-csv-line-escaped-quote ()
+ (should (equal (ellama-community-prompts-parse-csv-line
+ "writer,\"He said \"\"Hi\"\"\",TRUE")
+ '("writer" "He said \"Hi\"" "TRUE"))))
+
+(ert-deftest test-ellama-community-prompts-convert-to-plist ()
+ (should (equal (ellama-community-prompts-convert-to-plist
+ '("dev" "Use tests" "TRUE"))
+ '(:act "dev" :prompt "Use tests" :for-devs t)))
+ (should (equal (ellama-community-prompts-convert-to-plist
+ '("all" "General" "FALSE"))
+ '(:act "all" :prompt "General" :for-devs nil))))
+
+(ert-deftest test-ellama-community-prompts-ensure-file-skip-download ()
+ (let ((ellama-community-prompts-file
+ (make-temp-file "ellama-community-prompts-existing-"))
+ (plz-called nil))
+ (unwind-protect
+ (progn
+ (cl-letf (((symbol-function 'plz)
+ (lambda (&rest _args)
+ (setq plz-called t))))
+ (ellama-community-prompts-ensure-file))
+ (should-not plz-called))
+ (when (file-exists-p ellama-community-prompts-file)
+ (delete-file ellama-community-prompts-file)))))
+
+(ert-deftest test-ellama-community-prompts-ensure-file-download ()
+ (let* ((root-dir (make-temp-file "ellama-community-prompts-root-" t))
+ (target-dir (expand-file-name "nested/path" root-dir))
+ (ellama-community-prompts-file
+ (expand-file-name "community-prompts.csv" target-dir))
+ (ellama-community-prompts-url "https://example.invalid/prompts.csv")
+ (downloaded (make-temp-file "ellama-community-prompts-downloaded-"))
+ (called nil))
+ (unwind-protect
+ (progn
+ (with-temp-file downloaded
+ (insert "act,prompt,for_dev\nwriter,Prompt,FALSE\n"))
+ (cl-letf (((symbol-function 'plz)
+ (lambda (method url &rest args)
+ (setq called t)
+ (should (eq method 'get))
+ (should (equal url ellama-community-prompts-url))
+ (should (eq (plist-get args :as) 'file))
+ (funcall (plist-get args :then) downloaded)
+ t)))
+ (ellama-community-prompts-ensure-file))
+ (should called)
+ (should (file-exists-p ellama-community-prompts-file))
+ (should (equal (with-temp-buffer
+ (insert-file-contents ellama-community-prompts-file)
+ (buffer-string))
+ "act,prompt,for_dev\nwriter,Prompt,FALSE\n")))
+ (when (file-exists-p ellama-community-prompts-file)
+ (delete-file ellama-community-prompts-file))
+ (when (file-exists-p root-dir)
+ (delete-directory root-dir t))
+ (when (file-exists-p downloaded)
+ (delete-file downloaded)))))
+
+(ert-deftest test-ellama-community-prompts-ensure-loads-and-caches ()
+ (let ((ellama-community-prompts-collection nil)
+ (csv-file (make-temp-file "ellama-community-prompts-csv-")))
+ (unwind-protect
+ (progn
+ (with-temp-file csv-file
+ (insert
+ "act,prompt,for_dev\n"
+ "dev,\"Prompt, with comma\",TRUE\n"
+ "all,General,FALSE\n"))
+ (let ((ellama-community-prompts-file csv-file))
+ (let ((first (ellama-community-prompts-ensure)))
+ (should (equal first
+ '((:act "dev"
+ :prompt "Prompt, with comma"
+ :for-devs t)
+ (:act "all"
+ :prompt "General"
+ :for-devs nil))))
+ (with-temp-file csv-file
+ (insert
+ "act,prompt,for_dev\n"
+ "changed,Changed,FALSE\n"))
+ (let ((second (ellama-community-prompts-ensure)))
+ (should (eq first second))
+ (should (= 2 (length second)))))))
+ (when (file-exists-p csv-file)
+ (delete-file csv-file)))))
+
+(ert-deftest test-ellama-community-prompts-select-blueprint ()
+ (let ((called-args nil))
+ (cl-letf (((symbol-function 'ellama-blueprint-select)
+ (lambda (args)
+ (setq called-args args))))
+ (ellama-community-prompts-select-blueprint)
+ (should (equal called-args '(:source community))))))
+
+(provide 'test-ellama-community-prompts)
+;;; test-ellama-community-prompts.el ends here.