;;; test-pearl-mapping.el --- Tests for pearl mapping helpers -*- 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: ;; Unit tests for the pure mapping helpers in pearl.el: ;; Linear state <-> org keyword, the cached TODO-states regex, and ;; Linear priority -> org cookie / readable name. ;;; Code: (require 'test-bootstrap (expand-file-name "test-bootstrap.el")) ;; A small, explicit mapping used across the state tests so cases don't ;; depend on the package default. (defmacro test-pearl--with-mapping (mapping &rest body) "Run BODY with the state mapping bound to MAPPING and the cache cleared." (declare (indent 1)) `(let ((pearl-state-to-todo-mapping ,mapping) (pearl-todo-states-pattern nil) (pearl--todo-states-pattern-source nil)) ,@body)) ;;; pearl--map-linear-state-to-org (ert-deftest test-pearl-map-linear-state-to-org-mapped-returns-keyword () "A Linear state present in the mapping returns its org keyword." (test-pearl--with-mapping '(("Todo" . "TODO") ("In Progress" . "DOING")) (should (string-equal "DOING" (pearl--map-linear-state-to-org "In Progress"))))) (ert-deftest test-pearl-map-linear-state-to-org-unmapped-defaults-todo () "An unmapped Linear state falls back to TODO." (test-pearl--with-mapping '(("Todo" . "TODO") ("Done" . "DONE")) (should (string-equal "TODO" (pearl--map-linear-state-to-org "Triage"))))) (ert-deftest test-pearl-map-linear-state-to-org-nil-defaults-todo () "A nil state falls back to TODO rather than erroring." (test-pearl--with-mapping '(("Todo" . "TODO")) (should (string-equal "TODO" (pearl--map-linear-state-to-org nil))))) ;;; pearl--map-org-state-to-linear (ert-deftest test-pearl-map-org-state-to-linear-mapped-returns-state () "An org keyword present in the mapping returns its Linear state." (test-pearl--with-mapping '(("Todo" . "TODO") ("In Progress" . "DOING")) (should (string-equal "In Progress" (pearl--map-org-state-to-linear "DOING"))))) (ert-deftest test-pearl-map-org-state-to-linear-unmapped-returns-nil () "An org keyword not in the mapping returns nil." (test-pearl--with-mapping '(("Todo" . "TODO") ("Done" . "DONE")) (should (null (pearl--map-org-state-to-linear "WAITING"))))) (ert-deftest test-pearl-map-org-state-to-linear-nil-returns-nil () "A nil org keyword returns nil." (test-pearl--with-mapping '(("Todo" . "TODO")) (should (null (pearl--map-org-state-to-linear nil))))) ;;; pearl--get-todo-states-pattern (ert-deftest test-pearl-get-todo-states-pattern-builds-alternation () "The pattern is the org keywords joined with regex alternation." (test-pearl--with-mapping '(("Todo" . "TODO") ("In Progress" . "IN-PROGRESS") ("Done" . "DONE")) (should (string-equal "TODO\\|IN-PROGRESS\\|DONE" (pearl--get-todo-states-pattern))))) (ert-deftest test-pearl-get-todo-states-pattern-empty-mapping () "An empty mapping yields an empty pattern string." (test-pearl--with-mapping '() (should (string-equal "" (pearl--get-todo-states-pattern))))) (ert-deftest test-pearl-get-todo-states-pattern-recomputes-after-mapping-change () "The cached pattern is recomputed when the mapping changes mid-session. Regression for the stale-cache bug: a once-populated pattern must not outlive a change to `pearl-state-to-todo-mapping'." (test-pearl--with-mapping '(("Todo" . "TODO") ("Done" . "DONE")) (should (string-equal "TODO\\|DONE" (pearl--get-todo-states-pattern))) ;; Change the mapping after the pattern has been cached. (setq pearl-state-to-todo-mapping '(("Todo" . "TODO") ("In Progress" . "DOING") ("Done" . "DONE"))) (should (string-equal "TODO\\|DOING\\|DONE" (pearl--get-todo-states-pattern))))) ;;; pearl--map-linear-priority-to-org (ert-deftest test-pearl-map-linear-priority-to-org-known-values () "Linear priorities 1-4 map to org cookies A-D." (should (string-equal "[#A]" (pearl--map-linear-priority-to-org 1))) (should (string-equal "[#B]" (pearl--map-linear-priority-to-org 2))) (should (string-equal "[#C]" (pearl--map-linear-priority-to-org 3))) (should (string-equal "[#D]" (pearl--map-linear-priority-to-org 4)))) (ert-deftest test-pearl-map-linear-priority-to-org-zero-defaults-c () "Priority 0 (No priority) falls back to [#C]." (should (string-equal "[#C]" (pearl--map-linear-priority-to-org 0)))) (ert-deftest test-pearl-map-linear-priority-to-org-nil-and-unknown-default-c () "A nil or out-of-range priority falls back to [#C]." (should (string-equal "[#C]" (pearl--map-linear-priority-to-org nil))) (should (string-equal "[#C]" (pearl--map-linear-priority-to-org 99)))) ;;; pearl--get-linear-priority-name (ert-deftest test-pearl-get-linear-priority-name-known-values () "Linear priorities 1-4 have readable names." (should (string-equal "Urgent" (pearl--get-linear-priority-name 1))) (should (string-equal "High" (pearl--get-linear-priority-name 2))) (should (string-equal "Medium" (pearl--get-linear-priority-name 3))) (should (string-equal "Low" (pearl--get-linear-priority-name 4)))) (ert-deftest test-pearl-get-linear-priority-name-nil-and-unknown-default-medium () "A nil, zero, or out-of-range priority falls back to Medium." (should (string-equal "Medium" (pearl--get-linear-priority-name 0))) (should (string-equal "Medium" (pearl--get-linear-priority-name nil))) (should (string-equal "Medium" (pearl--get-linear-priority-name 99)))) ;;; pearl-get-priorities (ert-deftest test-pearl-get-priorities-returns-fixed-alist () "The priority list maps the five Linear priority names to their integers." (let ((priorities (pearl-get-priorities))) (should (equal 0 (cdr (assoc "No priority" priorities)))) (should (equal 1 (cdr (assoc "Urgent" priorities)))) (should (equal 2 (cdr (assoc "High" priorities)))) (should (equal 3 (cdr (assoc "Medium" priorities)))) (should (equal 4 (cdr (assoc "Low" priorities)))))) (provide 'test-pearl-mapping) ;;; test-pearl-mapping.el ends here