;;; test-pearl-saved.el --- Tests for saved queries + sort -*- lexical-binding: t; -*- ;; Copyright (C) 2026 Craig Jennings ;; Author: Craig Jennings ;; This program 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 of the License, or ;; (at your option) any later version. ;; This program 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 this program. If not, see . ;;; Commentary: ;; Tests for local saved queries and the sort layer: the client-side ;; `--sort-issues', the sort->orderBy mapping, and `pearl-run-saved-query' ;; threading the filter, source, and order through. ;;; Code: (require 'test-bootstrap (expand-file-name "test-bootstrap.el")) (require 'cl-lib) ;;; --sort-issues (defconst test-pearl--sort-sample '((:title "banana" :priority 2 :updated-at "2026-05-23T10:00:00.000Z") (:title "apple" :priority 1 :updated-at "2026-05-23T12:00:00.000Z") (:title "cherry" :priority 3 :updated-at "2026-05-23T08:00:00.000Z")) "Three issues for exercising the client-side sort.") (ert-deftest test-pearl-sort-issues-nil-sort-unchanged () "With no sort key, the issues are returned in their original order." (should (equal test-pearl--sort-sample (pearl--sort-issues test-pearl--sort-sample nil nil)))) (ert-deftest test-pearl-sort-issues-title-asc () "Sorting by title ascending orders alphabetically." (let ((out (pearl--sort-issues test-pearl--sort-sample 'title 'asc))) (should (equal '("apple" "banana" "cherry") (mapcar (lambda (i) (plist-get i :title)) out))))) (ert-deftest test-pearl-sort-issues-updated-desc-default () "Sorting by updated, descending, puts the most recent first." (let ((out (pearl--sort-issues test-pearl--sort-sample 'updated 'desc))) (should (string= "apple" (plist-get (car out) :title))) (should (string= "cherry" (plist-get (car (last out)) :title))))) (ert-deftest test-pearl-sort-issues-priority-asc () "Sorting by priority ascending orders by the numeric value." (let ((out (pearl--sort-issues test-pearl--sort-sample 'priority 'asc))) (should (equal '(1 2 3) (mapcar (lambda (i) (plist-get i :priority)) out))))) ;;; --sort->order-by (ert-deftest test-pearl-sort-to-order-by () "Updated/created map to the server orderBy; everything else defaults to updatedAt." (should (eq 'updatedAt (pearl--sort->order-by 'updated))) (should (eq 'createdAt (pearl--sort->order-by 'created))) (should (eq 'updatedAt (pearl--sort->order-by 'title)))) ;;; run-saved-query (ert-deftest test-pearl-run-saved-query-threads-filter-and-source () "Running a saved query compiles its filter and renders with a sorted source." (let ((pearl-saved-queries '(("My bugs" :filter (:labels ("bug") :open t) :sort priority :order asc))) (built nil) (rendered-source nil) (order nil)) (cl-letf (((symbol-function 'pearl--build-issue-filter) (lambda (plist) (setq built plist) '((compiled . t)))) ((symbol-function 'pearl--query-issues-async) (lambda (_filter cb &optional ord) (setq order ord) (funcall cb (pearl--make-query-result 'ok :issues nil)))) ((symbol-function 'pearl--render-query-result) (lambda (_result source) (setq rendered-source source)))) (pearl-run-saved-query "My bugs") (should (equal '(:labels ("bug") :open t) built)) (should (eq 'priority (plist-get rendered-source :sort))) (should (eq 'asc (plist-get rendered-source :order))) (should (eq 'filter (plist-get rendered-source :type))) (should (eq 'updatedAt order))))) (ert-deftest test-pearl-run-saved-query-unknown-errors () "An unknown saved-query name signals a user error." (let ((pearl-saved-queries '(("Known" :filter (:open t))))) (should-error (pearl-run-saved-query "Missing") :type 'user-error))) ;;; render applies the source sort (ert-deftest test-pearl-render-query-result-sorts-by-source () "The render boundary sorts issues by the source's sort/order before writing." (let ((written nil) (source '(:type filter :name "By title" :filter nil :sort title :order asc))) (cl-letf (((symbol-function 'pearl--normalize-issue) #'identity) ((symbol-function 'pearl--update-org-from-issues) (lambda (issues &optional _s _t) (setq written issues)))) (pearl--render-query-result (pearl--make-query-result 'ok :issues '((:title "banana") (:title "apple"))) source) (should (equal '("apple" "banana") (mapcar (lambda (i) (plist-get i :title)) written)))))) (provide 'test-pearl-saved) ;;; test-pearl-saved.el ends here