diff options
Diffstat (limited to 'tests/test-music-config--completion-table.el')
| -rw-r--r-- | tests/test-music-config--completion-table.el | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/tests/test-music-config--completion-table.el b/tests/test-music-config--completion-table.el new file mode 100644 index 00000000..5be0479d --- /dev/null +++ b/tests/test-music-config--completion-table.el @@ -0,0 +1,134 @@ +;;; test-music-config--completion-table.el --- Tests for completion table generation -*- coding: utf-8; lexical-binding: t; -*- +;; +;; Author: Craig Jennings <c@cjennings.net> +;; +;;; Commentary: +;; Unit tests for cj/music--completion-table function. +;; Tests the completion table generator that creates custom completion tables. +;; +;; Test organization: +;; - Normal Cases: Metadata, completions, case-insensitive matching +;; - Boundary Cases: Empty candidates, partial matching, exact matches +;; - Error Cases: Nil candidates +;; +;;; Code: + +(require 'ert) + +;; Stub missing dependencies before loading music-config +(defvar-keymap cj/custom-keymap + :doc "Stub keymap for testing") + +;; Load production code +(require 'music-config) + +;;; Normal Cases + +(ert-deftest test-music-config--completion-table-normal-metadata-action-returns-metadata () + "Completion table returns metadata when action is 'metadata." + (let* ((candidates '("Rock" "Jazz" "Classical")) + (table (cj/music--completion-table candidates)) + (result (funcall table "" nil 'metadata))) + (should (eq (car result) 'metadata)) + ;; Check metadata contains expected properties + (should (equal (alist-get 'display-sort-function (cdr result)) 'identity)) + (should (equal (alist-get 'cycle-sort-function (cdr result)) 'identity)) + (should (eq (alist-get 'completion-ignore-case (cdr result)) t)))) + +(ert-deftest test-music-config--completion-table-normal-t-action-returns-all-completions () + "Completion table returns all matching completions when action is t." + (let* ((candidates '("Rock" "Jazz" "Classical")) + (table (cj/music--completion-table candidates)) + (result (funcall table "" nil t))) + ;; Empty string should match all candidates + (should (equal (sort result #'string<) '("Classical" "Jazz" "Rock"))))) + +(ert-deftest test-music-config--completion-table-normal-nil-action-tries-completion () + "Completion table tries completion when action is nil." + (let* ((candidates '("Rock" "Jazz" "Classical")) + (table (cj/music--completion-table candidates)) + (result (funcall table "Roc" nil nil))) + ;; Should return completion attempt for "Roc" -> "Rock" + (should (stringp result)) + (should (string-prefix-p "Roc" result)))) + +(ert-deftest test-music-config--completion-table-normal-case-insensitive-metadata () + "Completion table metadata indicates case-insensitive completion." + (let* ((candidates '("Rock" "Jazz" "Classical")) + (table (cj/music--completion-table candidates)) + (metadata (funcall table "" nil 'metadata))) + ;; Metadata should indicate case-insensitive + (should (eq (alist-get 'completion-ignore-case (cdr metadata)) t)))) + +;;; Boundary Cases + +(ert-deftest test-music-config--completion-table-boundary-empty-candidates () + "Completion table with empty candidate list returns no completions." + (let* ((candidates '()) + (table (cj/music--completion-table candidates)) + (result (funcall table "anything" nil t))) + (should (null result)))) + +(ert-deftest test-music-config--completion-table-boundary-single-candidate () + "Completion table with single candidate returns it on match." + (let* ((candidates '("OnlyOne")) + (table (cj/music--completion-table candidates)) + (result (funcall table "Only" nil t))) + (should (equal result '("OnlyOne"))))) + +(ert-deftest test-music-config--completion-table-boundary-partial-matching () + "Completion table matches multiple candidates with common prefix." + (let* ((candidates '("playlist1" "playlist2" "jazz")) + (table (cj/music--completion-table candidates)) + (result (funcall table "play" nil t))) + (should (= (length result) 2)) + (should (member "playlist1" result)) + (should (member "playlist2" result)) + (should-not (member "jazz" result)))) + +(ert-deftest test-music-config--completion-table-boundary-no-matches () + "Completion table returns empty when no candidates match." + (let* ((candidates '("Rock" "Jazz" "Classical")) + (table (cj/music--completion-table candidates)) + (result (funcall table "Metal" nil t))) + (should (null result)))) + +(ert-deftest test-music-config--completion-table-boundary-exact-match () + "Completion table returns t for exact match with nil action." + (let* ((candidates '("Rock" "Jazz" "Classical")) + (table (cj/music--completion-table candidates)) + (result (funcall table "Jazz" nil nil))) + ;; Exact match with nil action returns t + (should (eq result t)))) + +(ert-deftest test-music-config--completion-table-boundary-mixed-case-candidates () + "Completion table with mixed-case duplicate candidates." + (let* ((candidates '("Rock" "ROCK" "rock")) + (table (cj/music--completion-table candidates)) + (result (funcall table "R" nil t))) + ;; All start with "R", but exact case matters for complete-with-action + ;; Only exact case match "R" prefix + (should (member "Rock" result)) + (should (member "ROCK" result)) + ;; "rock" doesn't match "R" prefix (lowercase) + (should-not (member "rock" result)))) + +(ert-deftest test-music-config--completion-table-boundary-unicode-candidates () + "Completion table handles unicode characters in candidates." + (let* ((candidates '("中文" "日本語" "한국어")) + (table (cj/music--completion-table candidates)) + (result (funcall table "中" nil t))) + (should (member "中文" result)))) + +;;; Error Cases + +(ert-deftest test-music-config--completion-table-error-nil-candidates-handles-gracefully () + "Completion table with nil candidates handles gracefully." + (let* ((candidates nil) + (table (cj/music--completion-table candidates)) + (result (funcall table "anything" nil t))) + ;; Should not crash, returns empty + (should (null result)))) + +(provide 'test-music-config--completion-table) +;;; test-music-config--completion-table.el ends here |
