diff options
| author | Craig Jennings <c@cjennings.net> | 2026-05-14 03:47:01 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-05-14 03:47:01 -0500 |
| commit | ec66cc02c89c0d378c0333cb4f6e35234e39d2f0 (patch) | |
| tree | 91bbe53d06d9d3ce8709f0889e66919e9c34ced5 /tests/test-system-commands-resolve-and-run.el | |
| parent | f6cfaee02412944e281c7ec4c6b20512b3e45708 (diff) | |
| download | dotemacs-ec66cc02c89c0d378c0333cb4f6e35234e39d2f0.tar.gz dotemacs-ec66cc02c89c0d378c0333cb4f6e35234e39d2f0.zip | |
test(system-commands): cover resolve, run wrapper, exit/restart, menu
Sibling `test-system-commands-keymap.el` locked the keymap shape. This batch covers the runtime helpers and commands:
- `cj/system-cmd--resolve`: trims strings, errors on empty/non-string-non-symbol, round-trips a symbol whose value is a non-empty string, errors on a symbol with empty value.
- `cj/system-cmd`: wraps a plain string in `nohup ... &` and hands it to `start-process-shell-command`; a confirm-tagged var with an N response signals user-error.
- `cj/system-cmd-exit-emacs`: declining the prompt aborts; accepting calls `kill-emacs`.
- `cj/system-cmd-restart-emacs`: declining aborts before scheduling; accepting schedules two timers.
- `cj/system-command-menu`: the completing-read pick routes through `call-interactively` to the right command symbol.
Top-level defvars for `test-sc-my-cmd` and `test-sc-empty-cmd` make the let-bindings dynamic so `symbol-value` reaches them under lexical scope.
Diffstat (limited to 'tests/test-system-commands-resolve-and-run.el')
| -rw-r--r-- | tests/test-system-commands-resolve-and-run.el | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/tests/test-system-commands-resolve-and-run.el b/tests/test-system-commands-resolve-and-run.el new file mode 100644 index 00000000..105628b6 --- /dev/null +++ b/tests/test-system-commands-resolve-and-run.el @@ -0,0 +1,142 @@ +;;; test-system-commands-resolve-and-run.el --- Tests for system-commands helpers + wrappers -*- lexical-binding: t; -*- + +;;; Commentary: +;; Sibling `test-system-commands-keymap.el' locks the keymap shape. +;; This file covers the runtime helpers and commands: +;; +;; cj/system-cmd--resolve +;; cj/system-cmd +;; cj/system-cmd-exit-emacs +;; cj/system-cmd-restart-emacs +;; cj/system-command-menu +;; +;; Process and prompt primitives are stubbed. + +;;; Code: + +(require 'ert) +(require 'cl-lib) + +(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory)) +(require 'system-commands) + +;; Top-level defvars so `let' bindings reach `symbol-value' under +;; lexical scope. +(defvar test-sc-my-cmd nil + "Dynamic test var for `cj/system-cmd--resolve' symbol-resolution test.") +(defvar test-sc-empty-cmd nil + "Dynamic test var for the empty-value test.") + +;;; cj/system-cmd--resolve + +(ert-deftest test-system-cmd-resolve-string-trims-and-returns () + "Normal: a non-empty string comes back trimmed with a nil symbol slot." + (let ((result (cj/system-cmd--resolve " echo hi "))) + (should (null (nth 0 result))) + (should (equal (nth 1 result) "echo hi")) + (should (equal (nth 2 result) "command")))) + +(ert-deftest test-system-cmd-resolve-empty-string-errors () + "Error: an empty string signals user-error." + (should-error (cj/system-cmd--resolve " ") :type 'user-error)) + +(ert-deftest test-system-cmd-resolve-symbol-uses-its-value () + "Normal: a symbol whose value is a non-empty string round-trips." + (let ((test-sc-my-cmd "echo hello")) + (let ((result (cj/system-cmd--resolve 'test-sc-my-cmd))) + (should (eq (nth 0 result) 'test-sc-my-cmd)) + (should (equal (nth 1 result) "echo hello")) + (should (equal (nth 2 result) "test-sc-my-cmd"))))) + +(ert-deftest test-system-cmd-resolve-symbol-with-empty-value-errors () + "Error: a symbol whose value isn't a non-empty string signals user-error." + (let ((test-sc-empty-cmd "")) + (should-error (cj/system-cmd--resolve 'test-sc-empty-cmd) :type 'user-error))) + +(ert-deftest test-system-cmd-resolve-non-string-non-symbol-errors () + "Error: passing a number signals user-error." + (should-error (cj/system-cmd--resolve 42) :type 'user-error)) + +;;; cj/system-cmd + +(ert-deftest test-system-cmd-string-runs-shell-process () + "Normal: a plain string is wrapped in nohup and handed to +`start-process-shell-command'." + (let (cmd-line) + (cl-letf (((symbol-function 'start-process-shell-command) + (lambda (_name _buf c) (setq cmd-line c) 'fake-proc)) + ((symbol-function 'set-process-query-on-exit-flag) #'ignore) + ((symbol-function 'set-process-sentinel) #'ignore) + ((symbol-function 'message) #'ignore)) + (cj/system-cmd "echo hi")) + (should (string-match-p "^nohup echo hi" cmd-line)) + (should (string-match-p "&$" cmd-line)))) + +(ert-deftest test-system-cmd-confirm-decline-aborts () + "Boundary: a confirm-tagged var with N response signals user-error." + (defvar test-sc-confirm-cmd "test-confirm-cmd") + (put 'test-sc-confirm-cmd 'cj/system-confirm t) + (unwind-protect + (cl-letf (((symbol-function 'read-char-choice) (lambda (&rest _) ?n)) + ((symbol-function 'start-process-shell-command) + (lambda (&rest _) (error "shouldn't run")))) + (should-error (cj/system-cmd 'test-sc-confirm-cmd) :type 'user-error)) + (put 'test-sc-confirm-cmd 'cj/system-confirm nil))) + +;;; cj/system-cmd-exit-emacs + +(ert-deftest test-system-cmd-exit-emacs-decline-aborts () + "Boundary: declining the prompt signals user-error; kill-emacs is not called." + (let ((killed nil)) + (cl-letf (((symbol-function 'read-char-choice) (lambda (&rest _) ?n)) + ((symbol-function 'kill-emacs) + (lambda (&rest _) (setq killed t)))) + (should-error (cj/system-cmd-exit-emacs) :type 'user-error)) + (should-not killed))) + +(ert-deftest test-system-cmd-exit-emacs-accept-calls-kill-emacs () + "Normal: accepting the prompt calls `kill-emacs'." + (let ((killed nil)) + (cl-letf (((symbol-function 'read-char-choice) (lambda (&rest _) ?y)) + ((symbol-function 'kill-emacs) + (lambda (&rest _) (setq killed t)))) + (cj/system-cmd-exit-emacs)) + (should killed))) + +;;; cj/system-cmd-restart-emacs + +(ert-deftest test-system-cmd-restart-emacs-decline-aborts () + "Boundary: declining the prompt signals user-error before scheduling." + (let ((scheduled nil)) + (cl-letf (((symbol-function 'read-char-choice) (lambda (&rest _) ?n)) + ((symbol-function 'save-some-buffers) #'ignore) + ((symbol-function 'run-at-time) + (lambda (&rest _) (setq scheduled t)))) + (should-error (cj/system-cmd-restart-emacs) :type 'user-error)) + (should-not scheduled))) + +(ert-deftest test-system-cmd-restart-emacs-accept-schedules-restart () + "Normal: accepting the prompt schedules the restart + kill timers." + (let ((schedules 0)) + (cl-letf (((symbol-function 'read-char-choice) (lambda (&rest _) ?y)) + ((symbol-function 'save-some-buffers) #'ignore) + ((symbol-function 'run-at-time) + (lambda (&rest _) (cl-incf schedules))) + ((symbol-function 'message) #'ignore)) + (cj/system-cmd-restart-emacs)) + (should (= schedules 2)))) + +;;; cj/system-command-menu + +(ert-deftest test-system-command-menu-dispatches-by-name () + "Normal: the completing-read selection routes through `call-interactively'." + (let ((called nil)) + (cl-letf (((symbol-function 'completing-read) + (lambda (&rest _) "Lock Screen")) + ((symbol-function 'call-interactively) + (lambda (cmd) (setq called cmd)))) + (cj/system-command-menu)) + (should (eq called 'cj/system-cmd-lock)))) + +(provide 'test-system-commands-resolve-and-run) +;;; test-system-commands-resolve-and-run.el ends here |
