aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-05-24 04:29:57 -0500
committerCraig Jennings <c@cjennings.net>2026-05-24 04:29:57 -0500
commitb26b74cb447966c0283a46afba908866777bd6ae (patch)
treefa9112ae3ed13be6f23d44ee4cebd512c1e9cc95 /tests
parent35e4d70116c8a2a5b82eaf4b8c58889dc02cbe46 (diff)
downloaddotemacs-b26b74cb447966c0283a46afba908866777bd6ae.tar.gz
dotemacs-b26b74cb447966c0283a46afba908866777bd6ae.zip
refactor(video-capture): scope capture URL to a dynamic binding
quick-video-capture passed the org-protocol URL through a global cj/video-download-current-url: the protocol handler setq the global, the capture handler read and cleared it. If a capture was aborted or errored between those steps, the stale URL survived into the next manual capture. Renamed it to cj/--video-download-url and let-bind it around the org-capture call in the protocol handler instead of setq-ing a global. The binding lives only for the dynamic extent of the capture, so the handler still sees the URL while the capture runs, and an abort or error unwinds the binding automatically — no stale state, no manual clear. The handler still prompts when invoked manually with no URL bound. Tests cover the bound-URL download, the manual prompt, the empty-URL error, that the URL is visible during the capture, and that an aborted capture leaves nothing behind.
Diffstat (limited to 'tests')
-rw-r--r--tests/test-quick-video-capture--url-state.el75
1 files changed, 75 insertions, 0 deletions
diff --git a/tests/test-quick-video-capture--url-state.el b/tests/test-quick-video-capture--url-state.el
new file mode 100644
index 00000000..6a0cd583
--- /dev/null
+++ b/tests/test-quick-video-capture--url-state.el
@@ -0,0 +1,75 @@
+;;; test-quick-video-capture--url-state.el --- Tests for video-capture URL state -*- lexical-binding: t; -*-
+
+;;; Commentary:
+;; Unit tests for the URL handoff between the org-protocol entry point and the
+;; capture handler in quick-video-capture.el. The URL is passed via a
+;; dynamically-bound variable scoped to the org-capture call, so an aborted or
+;; erroring capture cannot leave a stale URL behind for the next manual capture.
+
+;;; Code:
+
+(require 'ert)
+(require 'cl-lib)
+
+(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory))
+(require 'quick-video-capture)
+
+;;; cj/video-download-capture-handler
+
+(ert-deftest test-qvc-handler-downloads-bound-url ()
+ "Normal: the handler downloads the dynamically-bound URL and saves nothing."
+ (let (downloaded)
+ (cl-letf (((symbol-function 'require) (lambda (&rest _) nil))
+ ((symbol-function 'cj/yt-dl-it) (lambda (u) (setq downloaded u))))
+ (let ((cj/--video-download-url "https://example.com/v"))
+ (should (equal "" (cj/video-download-capture-handler))))
+ (should (equal "https://example.com/v" downloaded)))))
+
+(ert-deftest test-qvc-handler-prompts-when-no-bound-url ()
+ "Boundary: with no bound URL the handler prompts the user."
+ (let (downloaded)
+ (cl-letf (((symbol-function 'require) (lambda (&rest _) nil))
+ ((symbol-function 'cj/yt-dl-it) (lambda (u) (setq downloaded u)))
+ ((symbol-function 'read-string) (lambda (&rest _) "https://typed/v")))
+ (let ((cj/--video-download-url nil))
+ (cj/video-download-capture-handler))
+ (should (equal "https://typed/v" downloaded)))))
+
+(ert-deftest test-qvc-handler-empty-url-errors ()
+ "Error: an empty URL signals rather than downloading nothing."
+ (cl-letf (((symbol-function 'require) (lambda (&rest _) nil))
+ ((symbol-function 'read-string) (lambda (&rest _) "")))
+ (let ((cj/--video-download-url ""))
+ (should-error (cj/video-download-capture-handler)))))
+
+;;; cj/org-protocol-video-download — no global leak
+
+(ert-deftest test-qvc-protocol-binds-url-during-capture ()
+ "Normal: the protocol handler makes the URL visible to the capture call."
+ (let (seen-during)
+ (cl-letf (((symbol-function 'cj/ensure-video-download-initialized) #'ignore)
+ ((symbol-function 'org-capture)
+ (lambda (&rest _) (setq seen-during cj/--video-download-url))))
+ (cj/org-protocol-video-download '(:url "https://example.com/p")))
+ (should (equal "https://example.com/p" seen-during))))
+
+(ert-deftest test-qvc-protocol-leaves-no-stale-url ()
+ "Boundary: after the protocol capture returns, no URL remains bound."
+ (cl-letf (((symbol-function 'cj/ensure-video-download-initialized) #'ignore)
+ ((symbol-function 'org-capture) #'ignore))
+ (cj/org-protocol-video-download '(:url "https://example.com/p")))
+ (should (null cj/--video-download-url)))
+
+(ert-deftest test-qvc-protocol-aborted-capture-clears-url ()
+ "Error: a capture that errors/aborts mid-flow still leaves no stale URL.
+This is the regression the dynamic binding prevents: the old global
+setq survived an interrupted capture into the next manual one."
+ (cl-letf (((symbol-function 'cj/ensure-video-download-initialized) #'ignore)
+ ((symbol-function 'org-capture)
+ (lambda (&rest _) (error "simulated capture abort"))))
+ (ignore-errors
+ (cj/org-protocol-video-download '(:url "https://example.com/p"))))
+ (should (null cj/--video-download-url)))
+
+(provide 'test-quick-video-capture--url-state)
+;;; test-quick-video-capture--url-state.el ends here