;;; test-external-open-commands.el --- Tests for external-open commands -*- lexical-binding: t; -*- ;;; Commentary: ;; Sibling tests in `test-external-open-lib-*.el' cover the pure ;; `cj/external-open-command' and launcher-p helpers. This file ;; covers the user-facing wrappers: ;; ;; cj/xdg-open ;; cj/open-this-file-with ;; cj/find-file-auto ;; ;; Process primitives and host-environment predicates are stubbed. ;;; Code: (require 'ert) (require 'cl-lib) (add-to-list 'load-path (expand-file-name "modules" user-emacs-directory)) (require 'external-open) ;;; cj/xdg-open (ert-deftest test-external-open-xdg-open-runs-call-process-on-posix () "Normal: a usable command and file yields a `call-process' invocation." (let ((tmp (make-temp-file "test-ext-open-" nil ".tmp")) (call-args nil)) (unwind-protect (cl-letf (((symbol-function 'env-windows-p) (lambda () nil)) ((symbol-function 'cj/external-open-command) (lambda () "/usr/bin/xdg-open")) ((symbol-function 'call-process) (lambda (prog _infile _buf _disp &rest args) (setq call-args (cons prog args)) 0))) (cj/xdg-open tmp)) (delete-file tmp)) (should (equal (car call-args) "/usr/bin/xdg-open")) ;; The file's basename lands somewhere in the args. (let ((basename (file-name-nondirectory tmp))) (should (cl-find-if (lambda (a) (and (stringp a) (string-match-p basename a))) call-args))))) (ert-deftest test-external-open-xdg-open-errors-when-no-file () "Error: a buffer with no associated file signals user-error." (with-temp-buffer (cl-letf (((symbol-function 'cj/file-from-context) (lambda (_) nil))) (should-error (cj/xdg-open) :type 'user-error)))) (ert-deftest test-external-open-xdg-open-errors-when-no-command () "Error: an unsupported host environment signals user-error." (let ((tmp (make-temp-file "test-ext-open-no-cmd-" nil ".tmp"))) (unwind-protect (cl-letf (((symbol-function 'cj/external-open-command) (lambda () nil))) (should-error (cj/xdg-open tmp) :type 'user-error)) (delete-file tmp)))) ;;; cj/open-this-file-with (ert-deftest test-external-open-open-this-file-with-errors-no-file () "Error: outside a file-visiting buffer signals user-error." (with-temp-buffer (should-error (cj/open-this-file-with "vlc") :type 'user-error))) (ert-deftest test-external-open-open-this-file-with-spawns-detached-process () "Normal: posix path invokes `call-process-shell-command' with nohup + bg." (let ((cmd nil)) (with-temp-buffer (setq buffer-file-name "/tmp/foo.mp4") (cl-letf (((symbol-function 'env-windows-p) (lambda () nil)) ((symbol-function 'call-process-shell-command) (lambda (c _infile _buf &rest _) (setq cmd c)))) (cj/open-this-file-with "vlc")) (setq buffer-file-name nil)) (should (string-match-p "^nohup vlc " cmd)) (should (string-match-p "&$" cmd)) (should (string-match-p ">/dev/null" cmd)))) ;;; cj/find-file-auto (ert-deftest test-external-open-find-file-auto-routes-media-externally () "Normal: a `.mp4' filename (in `default-open-extensions') triggers `cj/xdg-open' instead of the original `find-file'." (let ((opened nil) (orig-called nil)) (cl-letf (((symbol-function 'cj/xdg-open) (lambda (file) (setq opened file))) ;; orig-fun replacement -- shouldn't run for a routed extension. ((symbol-function 'cj/find-file-auto--orig-stub) (lambda (&rest _) (setq orig-called t)))) (cj/find-file-auto #'cj/find-file-auto--orig-stub "/tmp/video.mp4")) (should (equal opened "/tmp/video.mp4")) (should-not orig-called))) (ert-deftest test-external-open-find-file-auto-passes-through-text-files () "Boundary: a `.txt' filename falls through to the original `find-file'." (let ((opened nil) (orig-args nil)) (cl-letf (((symbol-function 'cj/xdg-open) (lambda (file) (setq opened file))) ((symbol-function 'cj/find-file-auto--orig-stub) (lambda (&rest args) (setq orig-args args)))) (cj/find-file-auto #'cj/find-file-auto--orig-stub "/tmp/notes.txt")) (should-not opened) (should (equal (car orig-args) "/tmp/notes.txt")))) (ert-deftest test-external-open-find-file-auto-non-string-passes-through () "Boundary: a nil filename falls through (the routing only matches strings)." (let ((orig-called nil)) (cl-letf (((symbol-function 'cj/xdg-open) (lambda (_) (error "should not be called"))) ((symbol-function 'cj/find-file-auto--orig-stub) (lambda (&rest _) (setq orig-called t)))) (cj/find-file-auto #'cj/find-file-auto--orig-stub nil)) (should orig-called))) (provide 'test-external-open-commands) ;;; test-external-open-commands.el ends here