From 4aaf3ce0ba7911ad55a1823902737acc14658a9a Mon Sep 17 00:00:00 2001 From: mahmoodsheikh36 Date: Sat, 25 Apr 2026 20:31:38 +0300 Subject: [PATCH] add some transient tests --- Makefile | 1 + extensions/transient/lem-transient.asd | 8 ++- extensions/transient/tests/main.lisp | 97 ++++++++++++++++++++++++++ extensions/transient/transient.lisp | 1 + extensions/vi-mode/lem-vi-mode.asd | 3 +- 5 files changed, 108 insertions(+), 2 deletions(-) create mode 100644 extensions/transient/tests/main.lisp diff --git a/Makefile b/Makefile index 96f81a4e7..601689636 100644 --- a/Makefile +++ b/Makefile @@ -81,6 +81,7 @@ test: $(LISP) --load .qlot/setup.lisp \ --eval '(asdf:test-system "lem-tests")' \ --eval '(asdf:test-system "lem-vi-mode")' \ + --eval '(asdf:test-system "lem-transient")' \ --quit doc: diff --git a/extensions/transient/lem-transient.asd b/extensions/transient/lem-transient.asd index 2c9413d8c..149580153 100644 --- a/extensions/transient/lem-transient.asd +++ b/extensions/transient/lem-transient.asd @@ -3,4 +3,10 @@ :components ((:file "transient") (:file "keymap") (:file "popup") - (:file "demo"))) \ No newline at end of file + (:file "demo")) + :in-order-to ((test-op (test-op "lem-transient/tests")))) + +(defsystem "lem-transient/tests" + :depends-on ("lem-transient" "rove") + :components ((:file "tests/main")) + :perform (test-op (op c) (symbol-call :rove '#:run c))) \ No newline at end of file diff --git a/extensions/transient/tests/main.lisp b/extensions/transient/tests/main.lisp new file mode 100644 index 000000000..71e49f0f5 --- /dev/null +++ b/extensions/transient/tests/main.lisp @@ -0,0 +1,97 @@ +(defpackage :lem/transient/tests + (:use :cl :rove :lem/transient)) + +(in-package :lem/transient/tests) + +(defun segments->string (segments) + "flatten rendered segment lines to a plain string." + (with-output-to-string (s) + (loop for line in segments + for first := t then nil + do (unless first (write-char #\newline s)) + (dolist (seg line) + (write-string (car seg) s))))) + +(deftest keymap-creation + (testing "lem/transient::parse-transient produces keymap with correct properties" + (let ((km (lem/transient::parse-transient + '(:description "test" + :display-style :column + (:key "a" :suffix 'lem:nop-command :description "do a") + (:key "b" :suffix 'lem:nop-command :description "do b"))))) + (ok (lem/transient::keymap-show-p km)) + (ok (eq :column (lem/transient::keymap-display-style km))) + (ok (string= "test" (lem:keymap-description km))) + (ok (= 2 (length (lem:keymap-prefixes km))))))) + +(deftest key-binding-and-idempotency + (testing "assign-transient-key adds binding and replaces on repeat" + (let ((km (make-instance 'lem:keymap))) + (assign-transient-key km "z" '(:suffix 'lem:nop-command :description "first")) + (ok (= 1 (length (lem:keymap-prefixes km)))) + (assign-transient-key km "z" '(:suffix 'lem:nop-command :description "updated")) + (ok (= 1 (length (lem:keymap-prefixes km))) "no duplicate on re-bind") + (ok (string= "updated" (lem:prefix-description (first (lem:keymap-prefixes km))))))) + (testing "multi-key sequences interpreted as an intermediate prefix chain" + (let ((km (make-instance 'lem:keymap))) + (assign-transient-key km "e a" '(:suffix 'lem:nop-command)) + (let ((inter (first (lem:keymap-prefixes km)))) + (ok (lem:prefix-intermediate-p inter)) + (ok (typep (prefix-suffix inter) 'lem:keymap)) + (ok (= 1 (length (lem:keymap-prefixes (prefix-suffix inter))))))))) + +(deftest keymap-containment + (testing "lem/transient::keymap-contains-p works for nested and unrelated keymaps" + (let* ((inner (lem/transient::parse-transient '((:key "x" :suffix 'lem:nop-command)))) + (outer (make-instance 'lem:keymap))) + (lem:keymap-add-child outer inner) + (ok (lem/transient::keymap-contains-p outer inner)) + (ng (lem/transient::keymap-contains-p inner outer))))) + +(deftest infix-values + (testing "toggle starts nil, can be flipped" + (let ((p (parse-prefix '(:key "t" :type :toggle)))) + (ng (prefix-value p)) + (setf (prefix-value p) t) + (ok (prefix-value p)))) + (testing "choice defaults to first option, can be changed" + (let ((p (parse-prefix '(:key "c" :type :choice :choices '("alpha" "beta"))))) + (ok (string= "alpha" (prefix-value p))) + (setf (prefix-value p) "beta") + (ok (string= "beta" (prefix-value p))))) + (testing "variable-synced infix reads and writes to symbol" + (let ((var (gensym "TV-"))) + (set var "initial") + (let ((p (make-instance 'lem/transient::infix))) + (setf (lem/transient::infix-variable p) var) + (ok (string= "initial" (prefix-value p))) + (setf (prefix-value p) "changed") + (ok (string= "changed" (symbol-value var))))))) + +(deftest prefix-lookup-by-id + (testing "find-prefix-by-id locates prefix by id, returns nil when missing" + (let ((km (lem/transient::parse-transient '((:key "a" :id :my-id :suffix 'lem:nop-command) + (:key "b" :suffix 'lem:nop-command))))) + (let ((found (find-prefix-by-id km :my-id))) + (ok found) + (ok (eq :my-id (lem/transient::prefix-id found)))) + (ng (find-prefix-by-id km :missing))))) + +(deftest grid-buffer-text + (let* ((km (lem/transient::parse-transient + '(:display-style :row + (:keymap + :description "nav" + (:key "h" :description "left") + (:key "j" :description "down") + (:key "k" :description "up")) + (:keymap + :description "edit" + (:key "d" :description "delete") + (:key "y" :description "yank"))))) + (layout (lem/transient::generate-layout km)) + (text (segments->string (lem/transient::render-layout-to-segments layout)))) + (ok (string= "[nav] | [edit] +h left | d delete +j down | y yank +k up | " text)))) \ No newline at end of file diff --git a/extensions/transient/transient.lisp b/extensions/transient/transient.lisp index 01606f329..2f9353386 100644 --- a/extensions/transient/transient.lisp +++ b/extensions/transient/transient.lisp @@ -19,6 +19,7 @@ :prefix-active-p :prefix-suffix :transient-mode + :find-prefix-by-id )) (in-package :lem/transient) diff --git a/extensions/vi-mode/lem-vi-mode.asd b/extensions/vi-mode/lem-vi-mode.asd index 1fbf423c6..45b5a3a2c 100644 --- a/extensions/vi-mode/lem-vi-mode.asd +++ b/extensions/vi-mode/lem-vi-mode.asd @@ -57,7 +57,8 @@ (:file "registers") (:file "kbdmacro") (:file "jumplist") - (:file "options"))) + (:file "options") + (:file "insert"))) (:file "utils" :pathname "tests/utils")) :perform (test-op (op c) (symbol-call :rove '#:run c)))