aboutsummaryrefslogtreecommitdiff
path: root/tests/test-prog-python--lsp-guard.el
blob: 071e1ca96586e6739ed147029ab78cd98a3db2df (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
;;; test-prog-python--lsp-guard.el --- Python LSP guard tests -*- lexical-binding: t; -*-

;;; Commentary:
;; The config audit found lsp-pyright's unguarded :hook lambda calling
;; (require 'lsp-pyright) + (lsp-deferred) on every python-ts buffer, so
;; pyright-less machines got the LSP attach prompt that cj/python-setup's
;; guard exists to prevent.  The guarded branch now owns the require and
;; the attach, and both classic and treesit modes run the same setup.

;;; Code:

(require 'ert)
(require 'cl-lib)

(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory))
(require 'prog-python)

(defmacro test-python-guard--setup (pyright-found &rest body)
  "Run `cj/python-setup' with pyright presence set to PYRIGHT-FOUND.
Records requires into `required' and lsp attaches into `attached';
BODY sees both.  Package minor modes are stubbed at their boundary."
  (declare (indent 1))
  `(let ((required '()) (attached nil))
     (cl-letf (((symbol-function 'company-mode) #'ignore)
               ((symbol-function 'flyspell-prog-mode) #'ignore)
               ((symbol-function 'superword-mode) #'ignore)
               ((symbol-function 'executable-find)
                (lambda (&rest _) ,pyright-found))
               ((symbol-function 'require)
                (lambda (feature &rest _) (push feature required) feature))
               ((symbol-function 'lsp-deferred)
                (lambda () (setq attached t))))
       (with-temp-buffer
         (cj/python-setup))
       ,@body)))

(ert-deftest test-prog-python-setup-pyright-absent-no-lsp ()
  "Error: without pyright, setup neither loads lsp-pyright nor attaches."
  (test-python-guard--setup nil
    (should-not (memq 'lsp-pyright required))
    (should-not attached)))

(ert-deftest test-prog-python-setup-pyright-present-attaches ()
  "Normal: with pyright on PATH, setup loads lsp-pyright then attaches."
  (test-python-guard--setup "/usr/bin/pyright"
    (should (memq 'lsp-pyright required))
    (should attached)))

(ert-deftest test-prog-python-hooks-cover-both-mode-variants ()
  "Normal: classic and treesit python modes both run the same setup."
  (dolist (hook '(python-mode-hook python-ts-mode-hook))
    (should (memq #'cj/python-setup (symbol-value hook)))
    (should (memq #'cj/python-mode-keybindings (symbol-value hook)))))

(ert-deftest test-prog-python-no-anonymous-hook-lambdas ()
  "Boundary: no anonymous lambda remains on the python hooks.
The audit's unguarded lsp-pyright lambda was anonymous; symbols only
means every hook entry is a named, greppable function."
  (dolist (hook '(python-mode-hook python-ts-mode-hook))
    (dolist (fn (symbol-value hook))
      (should (symbolp fn)))))

(provide 'test-prog-python--lsp-guard)
;;; test-prog-python--lsp-guard.el ends here