xwidget-plus-follow-link-test.el 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. ;;; xwidget-plus-follow-link-test.el -- xwwp follow link test suite -*- lexical-binding: t; -*-
  2. ;; Copyright (C) 2020 Damien Merenne <dam@cosinux.org>
  3. ;; This program is free software: you can redistribute it and/or modify
  4. ;; it under the terms of the GNU General Public License as published by
  5. ;; the Free Software Foundation, either version 3 of the License, or
  6. ;; (at your option) any later version.
  7. ;; This program is distributed in the hope that it will be useful,
  8. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. ;; GNU General Public License for more details.
  11. ;; You should have received a copy of the GNU General Public License
  12. ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. ;;; Commentary:
  14. ;; Test suite for xwidget-webkit-plus-follow-link feature
  15. ;;; Code:
  16. (require 'test-helper)
  17. (require 'with-simulated-input)
  18. (require 'xwidget-plus-follow-link)
  19. (setq completing-read-function #'completing-read-default)
  20. ;; A mocked backend class that doesn't interactively read anything.
  21. (defclass xwidget-plus-completion-backend-test (xwidget-plus-completion-backend)
  22. ((candidates-mock :initarg :candidates-mock)
  23. (selected-mock :initarg :selected-mock)
  24. (action-fn)
  25. (classes)))
  26. (defun xwidget-plus-update-fn-callback (result)
  27. "Called after updating candidates with the css classes in RESULT."
  28. (let ((backend xwidget-plus-follow-link-completion-backend-instance))
  29. ;; Store the results.
  30. (oset backend classes result)
  31. ;; Trigger the action function with the mocked selected link
  32. (funcall (oref backend action-fn) (oref backend selected-mock))
  33. (xwidget-plus-event-dispatch)))
  34. (cl-defmethod xwidget-plus-follow-link-candidates ((backend xwidget-plus-completion-backend-test))
  35. "Return the list of BACKEND mocked candidates."
  36. (oref backend candidates-mock))
  37. (cl-defmethod xwidget-plus-follow-link-read ((backend xwidget-plus-completion-backend-test) _ _ action-fn update-fn)
  38. "Store ACTION-FN in BACKEND, call the UPDATE-FN, and fetch the link element classes."
  39. ;; Stoire action so that we can call it after having fetch the css classes.
  40. (oset backend action-fn action-fn)
  41. ;; Trigger the javascript update.
  42. (funcall update-fn)
  43. ;; Fetch css classes.
  44. (xwidget-webkit-execute-script (xwidget-webkit-current-session) (--js "
  45. map = Array.prototype.map;
  46. r = {};
  47. document.querySelectorAll('a').forEach(l => {
  48. r[l.id] = map.call(l.classList, t => {
  49. return t.toString();
  50. });
  51. });
  52. r
  53. " js--) #'xwidget-plus-update-fn-callback)
  54. (xwidget-plus-event-dispatch))
  55. (cl-defmethod backend-test-link-classes ((backend xwidget-plus-completion-backend-test) link-id)
  56. "Return test BACKEND css class names for LINK-ID."
  57. (cdr (assoc link-id (oref backend classes))))
  58. (defmacro with-backend (backend &rest body)
  59. "Run BODY with the specified BACKEND."
  60. (declare (indent 1))
  61. `(let* ((backend (,(intern (concat "xwidget-plus-completion-backend-" (symbol-name backend)))))
  62. (xwidget-plus-follow-link-completion-backend-instance backend))
  63. ,@body))
  64. (defmacro with-test-backend-browse (candidates selected url &rest body)
  65. "Run BODY with the specified BACKEND mocking CANDIDATES and SELECTED while browsing URL."
  66. (declare (indent 3))
  67. `(let* ((xwidget-plus-completion-system (lambda () (xwidget-plus-completion-backend-test :candidates-mock ,candidates
  68. :selected-mock ,selected))))
  69. (with-browse ,url
  70. ,@body)))
  71. (ert-deftest test-xwidget-plus-follow-link-prepare-links ()
  72. (let ((links '(("3" . "Functions")
  73. ("1" . "Function Cells")
  74. ("12" . "Structures")
  75. ("2" . "Anonymous Functions")
  76. ("9" . "Declare Form"))))
  77. (should (equal '(("Function Cells" . 1)
  78. ("Anonymous Functions" . 2)
  79. ("Functions" . 3)
  80. ("Declare Form" . 9)
  81. ("Structures" . 12))
  82. (xwidget-plus-follow-link-prepare-links links)))))
  83. (ert-deftest test-xwidget-plus-follow-link-highlight ()
  84. (with-test-backend-browse '(0 0 1) 0 "links.html"
  85. (xwidget-plus-follow-link)
  86. (xwidget-plus-event-dispatch)
  87. (should (string= "test-1.html" (file-name-nondirectory (xwidget-webkit-current-url))))
  88. (let ((backend xwidget-plus-follow-link-completion-backend-instance))
  89. (should (equal (backend-test-link-classes backend "test-1") '["xwidget-plus-follow-link-selected"]))
  90. (should (equal (backend-test-link-classes backend "test-2") '["xwidget-plus-follow-link-candidate"]))))
  91. (with-test-backend-browse '(1 0 1) 1 "links.html"
  92. (split-window-vertically)
  93. (save-excursion (switch-to-buffer-other-window "*Messages*"))
  94. (xwidget-plus-follow-link)
  95. (xwidget-plus-event-dispatch)
  96. (should (string= "test-2.html" (file-name-nondirectory (xwidget-webkit-current-url))))
  97. (let ((backend xwidget-plus-follow-link-completion-backend-instance))
  98. (should (equal (backend-test-link-classes backend "test-1") '["xwidget-plus-follow-link-candidate"]))
  99. (should (equal (backend-test-link-classes backend "test-2") '["xwidget-plus-follow-link-selected"])))))
  100. (defmacro with-read-fixtures (backend &rest body)
  101. (declare (indent 1))
  102. `(let* ((links '(("test 1" . 0) ("test 2" . 1)))
  103. link
  104. (action (lambda (l) (setq link l)))
  105. (update (lambda ())))
  106. (with-backend ,backend
  107. (with-browse "links.html"
  108. ,@body))))
  109. (ert-deftest test-xwidget-plus-follow-link-read-default ()
  110. (with-read-fixtures default
  111. (with-simulated-input "test SPC 2 RET"
  112. (xwidget-plus-follow-link-read backend "Test: " links action update)
  113. (should (= 1 link)))))
  114. (ert-deftest test-xwidget-plus-follow-link-read-ido ()
  115. (require 'ido)
  116. (with-read-fixtures ido
  117. (with-simulated-input "2 RET"
  118. (xwidget-plus-follow-link-read backend "Test: " links action update)
  119. (should (= 1 link)))))
  120. (ert-deftest test-xwidget-plus-follow-link-read-ivy ()
  121. (require 'ivy)
  122. (with-read-fixtures ivy
  123. (with-simulated-input "2 RET"
  124. (xwidget-plus-follow-link-read backend "Test: " links action update)
  125. (should (= 1 link)))))
  126. (ert-deftest test-xwidget-plus-follow-link-read-helm ()
  127. (require 'helm)
  128. (with-read-fixtures helm
  129. (with-simulated-input '("2" (wsi-simulate-idle-time 0.1) "RET")
  130. (xwidget-plus-follow-link-read backend "Test: " links action update)
  131. (should (= 1 link)))))
  132. (defmacro with-feature (feature &rest body)
  133. (declare (indent 1))
  134. `(progn (when (featurep 'ido) (unload-feature 'ido t))
  135. (when (featurep 'ivy) (unload-feature 'ivy t))
  136. (when (featurep 'helm) (unload-feature 'helm t))
  137. (when ,feature (require ,feature))
  138. ,@body))
  139. (ert-deftest test-xwidget-plus-follow-link-make-backend-use-feature ()
  140. (with-feature nil
  141. (should (eq #'xwidget-plus-completion-backend-default (xwidget-plus-follow-link-make-backend))))
  142. (with-feature 'ido
  143. (should (eq #'xwidget-plus-completion-backend-ido (xwidget-plus-follow-link-make-backend))))
  144. (with-feature 'ivy
  145. (should (eq #'xwidget-plus-completion-backend-ivy (xwidget-plus-follow-link-make-backend))))
  146. (with-feature 'helm
  147. (should (eq #'xwidget-plus-completion-backend-helm (xwidget-plus-follow-link-make-backend)))))
  148. (ert-deftest test-xwidget-plus-follow-link-make-backend-use-custom ()
  149. (let ((xwidget-plus-completion-system 'default))
  150. (with-feature nil
  151. (should (eq #'xwidget-plus-completion-backend-default (xwidget-plus-follow-link-make-backend)))))
  152. (let ((xwidget-plus-completion-system 'ido))
  153. (should (eq #'xwidget-plus-completion-backend-ido (xwidget-plus-follow-link-make-backend))))
  154. (let ((xwidget-plus-completion-system 'ivy))
  155. (should (eq #'xwidget-plus-completion-backend-ivy (xwidget-plus-follow-link-make-backend))))
  156. (let ((xwidget-plus-completion-system 'helm))
  157. (should (eq #'xwidget-plus-completion-backend-helm (xwidget-plus-follow-link-make-backend))))
  158. (let ((xwidget-plus-completion-system #'identity))
  159. (should (eq #'identity (xwidget-plus-follow-link-make-backend)))))
  160. ;; Local Variables:
  161. ;; eval: (mmm-mode)
  162. ;; eval: (mmm-add-classes '((elisp-js :submode js-mode :face mmm-code-submode-face :delimiter-mode nil :front "--js \"" :back "\" js--")))
  163. ;; mmm-classes: elisp-js
  164. ;; End:
  165. (provide 'xwidget-plus-follow-link-test)
  166. ;;; xwidget-plus-follow-link-test.el ends here