aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-01 23:40:11 -0500
committerCraig Jennings <c@cjennings.net>2026-06-01 23:40:11 -0500
commit8bae955521cdf3e2f8d5ff015b3ae36b5b8a75e8 (patch)
tree2d765a0aba944e0af418f0dbf736e10d07eef73d /tests
parent5ef986c880fa6fdfafe3f11943524119065bd044 (diff)
downloadpearl-8bae955521cdf3e2f8d5ff015b3ae36b5b8a75e8.tar.gz
pearl-8bae955521cdf3e2f8d5ff015b3ae36b5b8a75e8.zip
feat(filter): :state accepts a list of state names
I made :state polymorphic, mirroring :state-type. A string still compiles to state.name.eq. A list now compiles to state.name.in, so (:state ("Todo" "In Review")) matches issues in either state. The reverse-compile inverts state.name.in back to a scalar (one name) or a list (several), so copy-down no longer refuses a Linear view filtering on a set of named states. The validator accepts a string or a list of non-empty names, the same shape it already enforces for :labels, and a list-valued :state keeps its precedence over :state-type and :open. Phase 1 of docs/multi-state-filter-spec.org. Suite, compile, and lint green.
Diffstat (limited to 'tests')
-rw-r--r--tests/test-pearl-filter.el26
-rw-r--r--tests/test-pearl-reverse-compile.el18
2 files changed, 44 insertions, 0 deletions
diff --git a/tests/test-pearl-filter.el b/tests/test-pearl-filter.el
index 38d254e..d3fca88 100644
--- a/tests/test-pearl-filter.el
+++ b/tests/test-pearl-filter.el
@@ -83,6 +83,16 @@
(should (equal (pearl--build-issue-filter '(:state-type "started"))
'(("state" ("type" ("in" . ["started"])))))))
+(ert-deftest test-pearl-filter-state-name-list ()
+ ":state with a list of names compiles to state.name.in."
+ (should (equal (pearl--build-issue-filter '(:state ("Todo" "In Review")))
+ '(("state" ("name" ("in" . ["Todo" "In Review"])))))))
+
+(ert-deftest test-pearl-filter-state-list-beats-open ()
+ "A list-valued :state keeps precedence over :open."
+ (should (equal (pearl--build-issue-filter '(:state ("Todo" "Done") :open t))
+ '(("state" ("name" ("in" . ["Todo" "Done"])))))))
+
(ert-deftest test-pearl-filter-project-team-cycle ()
":project / :cycle compile to id.eq; :team to key.eq."
(should (equal (pearl--build-issue-filter '(:project "p-1"))
@@ -189,6 +199,22 @@
"A non-string entry in :labels is a user-error."
(should-error (pearl--validate-issue-filter '(:labels ("bug" 7))) :type 'user-error))
+(ert-deftest test-pearl-filter-validate-accepts-state-list ()
+ "A :state list of non-empty names validates."
+ (should (eq t (pearl--validate-issue-filter '(:state ("Todo" "In Review"))))))
+
+(ert-deftest test-pearl-filter-validate-accepts-state-string ()
+ "A single-string :state still validates."
+ (should (eq t (pearl--validate-issue-filter '(:state "In Progress")))))
+
+(ert-deftest test-pearl-filter-validate-rejects-empty-name-in-state-list ()
+ "An empty name anywhere in a :state list is a user-error."
+ (should-error (pearl--validate-issue-filter '(:state ("" "Todo"))) :type 'user-error))
+
+(ert-deftest test-pearl-filter-validate-rejects-empty-state-string ()
+ "An empty single :state string is a user-error."
+ (should-error (pearl--validate-issue-filter '(:state "")) :type 'user-error))
+
;;; id-based forms (rename-proof; used by favorite-derived filter sources)
(ert-deftest test-pearl-filter-assignee-id ()
diff --git a/tests/test-pearl-reverse-compile.el b/tests/test-pearl-reverse-compile.el
index ec67391..382c72a 100644
--- a/tests/test-pearl-reverse-compile.el
+++ b/tests/test-pearl-reverse-compile.el
@@ -57,6 +57,24 @@
(ert-deftest test-pearl-rc-roundtrip-state-name ()
(test-pearl-rc--should-roundtrip '(:state "In Progress")))
+(ert-deftest test-pearl-rc-roundtrip-state-name-list ()
+ "A multi-state :state round-trips (state.name.in with several names)."
+ (let ((r (test-pearl-rc--roundtrip '(:state ("Todo" "In Review")))))
+ (should (eq 'ok (car r)))
+ (should (equal (cdr r) '(:state ("Todo" "In Review"))))))
+
+(ert-deftest test-pearl-rc-state-name-in-many-to-list ()
+ "state.name.in with several names reverse-compiles to a list :state."
+ (should (equal (test-pearl-rc--from-json
+ "{\"state\":{\"name\":{\"in\":[\"Todo\",\"In Review\"]}}}")
+ '(ok :state ("Todo" "In Review")))))
+
+(ert-deftest test-pearl-rc-state-name-in-one-to-scalar ()
+ "state.name.in with one name normalizes to a scalar :state."
+ (should (equal (test-pearl-rc--from-json
+ "{\"state\":{\"name\":{\"in\":[\"Todo\"]}}}")
+ '(ok :state "Todo"))))
+
(ert-deftest test-pearl-rc-roundtrip-state-type-single ()
(let ((r (test-pearl-rc--roundtrip '(:state-type "started"))))
(should (eq 'ok (car r)))